ia64/xen-unstable

changeset 3406:359fb6f68701

bitkeeper revision 1.1159.217.2 (41e3bb8ebh7B5VbNMpdDOfs7z982kw)

Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xen-unstable.bk
author kaf24@scramble.cl.cam.ac.uk
date Tue Jan 11 11:42:06 2005 +0000 (2005-01-11)
parents 9ad7af5b3f9b cc63d97d7f2f
children 46e21e3f8bee
files xen/arch/x86/memory.c xen/arch/x86/traps.c xen/include/asm-x86/mm.h xen/include/asm-x86/processor.h
line diff
     1.1 --- a/xen/arch/x86/memory.c	Mon Jan 10 22:21:26 2005 +0000
     1.2 +++ b/xen/arch/x86/memory.c	Tue Jan 11 11:42:06 2005 +0000
     1.3 @@ -937,12 +937,41 @@ int get_page_type(struct pfn_info *page,
     1.4  }
     1.5  
     1.6  
     1.7 +int new_guest_cr3(unsigned long pfn)
     1.8 +{
     1.9 +    struct exec_domain *ed = current;
    1.10 +    struct domain *d = ed->domain;
    1.11 +    int okay, cpu = smp_processor_id();
    1.12 +    unsigned long old_base_pfn;
    1.13 +    
    1.14 +    okay = get_page_and_type_from_pagenr(pfn, PGT_l2_page_table, d);
    1.15 +    if ( likely(okay) )
    1.16 +    {
    1.17 +        invalidate_shadow_ldt(ed);
    1.18 +
    1.19 +        percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB;
    1.20 +        old_base_pfn = pagetable_val(ed->mm.pagetable) >> PAGE_SHIFT;
    1.21 +        ed->mm.pagetable = mk_pagetable(pfn << PAGE_SHIFT);
    1.22 +
    1.23 +        shadow_mk_pagetable(&ed->mm);
    1.24 +
    1.25 +        write_ptbase(&ed->mm);
    1.26 +
    1.27 +        put_page_and_type(&frame_table[old_base_pfn]);
    1.28 +    }
    1.29 +    else
    1.30 +    {
    1.31 +        MEM_LOG("Error while installing new baseptr %08lx", ptr);
    1.32 +    }
    1.33 +
    1.34 +    return okay;
    1.35 +}
    1.36 +
    1.37  static int do_extended_command(unsigned long ptr, unsigned long val)
    1.38  {
    1.39      int okay = 1, cpu = smp_processor_id();
    1.40      unsigned int cmd = val & MMUEXT_CMD_MASK;
    1.41      unsigned long pfn = ptr >> PAGE_SHIFT;
    1.42 -    unsigned long old_base_pfn;
    1.43      struct pfn_info *page = &frame_table[pfn];
    1.44      struct exec_domain *ed = current;
    1.45      struct domain *d = ed->domain, *nd, *e;
    1.46 @@ -1003,25 +1032,7 @@ static int do_extended_command(unsigned 
    1.47          break;
    1.48  
    1.49      case MMUEXT_NEW_BASEPTR:
    1.50 -        okay = get_page_and_type_from_pagenr(pfn, PGT_l2_page_table, d);
    1.51 -        if ( likely(okay) )
    1.52 -        {
    1.53 -            invalidate_shadow_ldt(ed);
    1.54 -
    1.55 -            percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB;
    1.56 -            old_base_pfn = pagetable_val(ed->mm.pagetable) >> PAGE_SHIFT;
    1.57 -            ed->mm.pagetable = mk_pagetable(pfn << PAGE_SHIFT);
    1.58 -
    1.59 -            shadow_mk_pagetable(&ed->mm);
    1.60 -
    1.61 -            write_ptbase(&ed->mm);
    1.62 -
    1.63 -            put_page_and_type(&frame_table[old_base_pfn]);
    1.64 -        }
    1.65 -        else
    1.66 -        {
    1.67 -            MEM_LOG("Error while installing new baseptr %08lx", ptr);
    1.68 -        }
    1.69 +        okay = new_guest_cr3(pfn);
    1.70          break;
    1.71          
    1.72      case MMUEXT_TLB_FLUSH:
     2.1 --- a/xen/arch/x86/traps.c	Mon Jan 10 22:21:26 2005 +0000
     2.2 +++ b/xen/arch/x86/traps.c	Tue Jan 11 11:42:06 2005 +0000
     2.3 @@ -383,14 +383,30 @@ asmlinkage void do_machine_check(struct 
     2.4      fatal_trap(TRAP_machine_check, regs);
     2.5  }
     2.6  
     2.7 +static inline void propagate_page_fault(unsigned long addr, u16 error_code)
     2.8 +{
     2.9 +    trap_info_t *ti;
    2.10 +    struct exec_domain *ed = current;
    2.11 +    struct trap_bounce *tb = &ed->thread.trap_bounce;
    2.12 +
    2.13 +    ti = ed->thread.traps + 14;
    2.14 +    tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
    2.15 +    tb->cr2        = addr;
    2.16 +    tb->error_code = error_code;
    2.17 +    tb->cs         = ti->cs;
    2.18 +    tb->eip        = ti->address;
    2.19 +    if ( TI_GET_IF(ti) )
    2.20 +        ed->vcpu_info->evtchn_upcall_mask = 1;
    2.21 +
    2.22 +    ed->mm.guest_cr2 = addr;
    2.23 +}
    2.24 +
    2.25  asmlinkage int do_page_fault(struct xen_regs *regs)
    2.26  {
    2.27 -    trap_info_t *ti;
    2.28      unsigned long off, addr, fixup;
    2.29      struct exec_domain *ed = current;
    2.30      struct domain *d = ed->domain;
    2.31      extern int map_ldt_shadow_page(unsigned int);
    2.32 -    struct trap_bounce *tb = &ed->thread.trap_bounce;
    2.33      int cpu = ed->processor;
    2.34      int ret;
    2.35  
    2.36 @@ -447,14 +463,7 @@ asmlinkage int do_page_fault(struct xen_
    2.37      if ( !GUEST_FAULT(regs) )
    2.38          goto xen_fault;
    2.39  
    2.40 -    ti = ed->thread.traps + 14;
    2.41 -    tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
    2.42 -    tb->cr2        = addr;
    2.43 -    tb->error_code = regs->error_code;
    2.44 -    tb->cs         = ti->cs;
    2.45 -    tb->eip        = ti->address;
    2.46 -    if ( TI_GET_IF(ti) )
    2.47 -        ed->vcpu_info->evtchn_upcall_mask = 1;
    2.48 +    propagate_page_fault(addr, regs->error_code);
    2.49      return 0; 
    2.50  
    2.51   xen_fault:
    2.52 @@ -497,45 +506,126 @@ asmlinkage int do_page_fault(struct xen_
    2.53  
    2.54  static int emulate_privileged_op(struct xen_regs *regs)
    2.55  {
    2.56 -    u16 opcode;
    2.57 +    extern long do_fpu_taskswitch(void);
    2.58 +    extern void *decode_reg(struct xen_regs *regs, u8 b);
    2.59  
    2.60 -    if ( get_user(opcode, (u16 *)regs->eip) || ((opcode & 0xff) != 0x0f) )
    2.61 -        return 0;
    2.62 +    struct exec_domain *ed = current;
    2.63 +    unsigned long *reg, eip = regs->eip;
    2.64 +    u8 opcode;
    2.65 +
    2.66 +    if ( get_user(opcode, (u8 *)eip) )
    2.67 +        goto page_fault;
    2.68 +    eip += 1;
    2.69 +    if ( (opcode & 0xff) != 0x0f )
    2.70 +        goto fail;
    2.71  
    2.72 -    switch ( opcode >> 8 )
    2.73 +    if ( get_user(opcode, (u8 *)eip) )
    2.74 +        goto page_fault;
    2.75 +    eip += 1;
    2.76 +
    2.77 +    switch ( opcode )
    2.78      {
    2.79 +    case 0x06: /* CLTS */
    2.80 +        (void)do_fpu_taskswitch();
    2.81 +        break;
    2.82 +
    2.83      case 0x09: /* WBINVD */
    2.84 -        if ( !IS_CAPABLE_PHYSDEV(current->domain) )
    2.85 +        if ( !IS_CAPABLE_PHYSDEV(ed->domain) )
    2.86          {
    2.87              DPRINTK("Non-physdev domain attempted WBINVD.\n");
    2.88 -            return 0;
    2.89 +            goto fail;
    2.90          }
    2.91          wbinvd();
    2.92 -        regs->eip += 2;
    2.93 -        return 1;
    2.94 -        
    2.95 +        break;
    2.96 +
    2.97 +    case 0x20: /* MOV CR?,<reg> */
    2.98 +        if ( get_user(opcode, (u8 *)eip) )
    2.99 +            goto page_fault;
   2.100 +        eip += 1;
   2.101 +        if ( (opcode & 0xc0) != 0xc0 )
   2.102 +            goto fail;
   2.103 +        reg = decode_reg(regs, opcode);
   2.104 +        switch ( (opcode >> 3) & 7 )
   2.105 +        {
   2.106 +        case 0: /* Read CR0 */
   2.107 +            *reg = 
   2.108 +                (read_cr0() & ~X86_CR0_TS) | 
   2.109 +                (test_bit(EDF_GUEST_STTS, &ed->ed_flags) ? X86_CR0_TS : 0);
   2.110 +            break;
   2.111 +
   2.112 +        case 2: /* Read CR2 */
   2.113 +            *reg = ed->mm.guest_cr2;
   2.114 +            break;
   2.115 +            
   2.116 +        case 3: /* Read CR3 */
   2.117 +            *reg = pagetable_val(ed->mm.pagetable);
   2.118 +            break;
   2.119 +
   2.120 +        default:
   2.121 +            goto fail;
   2.122 +        }
   2.123 +        break;
   2.124 +
   2.125 +    case 0x22: /* MOV <reg>,CR? */
   2.126 +        if ( get_user(opcode, (u8 *)eip) )
   2.127 +            goto page_fault;
   2.128 +        eip += 1;
   2.129 +        if ( (opcode & 0xc0) != 0xc0 )
   2.130 +            goto fail;
   2.131 +        reg = decode_reg(regs, opcode);
   2.132 +        switch ( (opcode >> 3) & 7 )
   2.133 +        {
   2.134 +        case 0: /* Write CR0 */
   2.135 +            if ( *reg & X86_CR0_TS ) /* XXX ignore all but TS bit */
   2.136 +                (void)do_fpu_taskswitch;
   2.137 +            break;
   2.138 +
   2.139 +        case 2: /* Write CR2 */
   2.140 +            ed->mm.guest_cr2 = *reg;
   2.141 +            break;
   2.142 +            
   2.143 +        case 3: /* Write CR3 */
   2.144 +            LOCK_BIGLOCK(ed->domain);
   2.145 +            (void)new_guest_cr3(*reg);
   2.146 +            UNLOCK_BIGLOCK(ed->domain);
   2.147 +            break;
   2.148 +
   2.149 +        default:
   2.150 +            goto fail;
   2.151 +        }
   2.152 +        break;
   2.153 +
   2.154      case 0x30: /* WRMSR */
   2.155 -        if ( !IS_PRIV(current->domain) )
   2.156 +        if ( !IS_PRIV(ed->domain) )
   2.157          {
   2.158              DPRINTK("Non-priv domain attempted WRMSR.\n");
   2.159 -            return 0;
   2.160 +            goto fail;
   2.161          }
   2.162          wrmsr(regs->ecx, regs->eax, regs->edx);
   2.163 -        regs->eip += 2;
   2.164 -        return 1;
   2.165 +        break;
   2.166  
   2.167      case 0x32: /* RDMSR */
   2.168 -        if ( !IS_PRIV(current->domain) )
   2.169 +        if ( !IS_PRIV(ed->domain) )
   2.170          {
   2.171              DPRINTK("Non-priv domain attempted RDMSR.\n");
   2.172 -            return 0;
   2.173 +            goto fail;
   2.174          }
   2.175          rdmsr(regs->ecx, regs->eax, regs->edx);
   2.176 -        regs->eip += 2;
   2.177 -        return 1;
   2.178 +        break;
   2.179 +
   2.180 +    default:
   2.181 +        goto fail;
   2.182      }
   2.183  
   2.184 +    regs->eip = eip;
   2.185 +    return EXCRET_fault_fixed;
   2.186 +
   2.187 + fail:
   2.188      return 0;
   2.189 +
   2.190 + page_fault:
   2.191 +    propagate_page_fault(eip, 0);
   2.192 +    return EXCRET_fault_fixed;
   2.193  }
   2.194  
   2.195  asmlinkage int do_general_protection(struct xen_regs *regs)
     3.1 --- a/xen/include/asm-x86/mm.h	Mon Jan 10 22:21:26 2005 +0000
     3.2 +++ b/xen/include/asm-x86/mm.h	Tue Jan 11 11:42:06 2005 +0000
     3.3 @@ -278,6 +278,8 @@ extern ptwr_info_t ptwr_info[];
     3.4  void ptwr_flush(const int);
     3.5  int ptwr_do_page_fault(unsigned long);
     3.6  
     3.7 +int new_guest_cr3(unsigned long pfn);
     3.8 +
     3.9  #define __cleanup_writable_pagetable(_what)                                 \
    3.10  do {                                                                        \
    3.11      int cpu = smp_processor_id();                                           \
     4.1 --- a/xen/include/asm-x86/processor.h	Mon Jan 10 22:21:26 2005 +0000
     4.2 +++ b/xen/include/asm-x86/processor.h	Tue Jan 11 11:42:06 2005 +0000
     4.3 @@ -485,6 +485,9 @@ struct mm_struct {
     4.4      unsigned long min_pfn;		/* min host physical */
     4.5      unsigned long max_pfn;		/* max host physical */
     4.6  
     4.7 +    /* Virtual CR2 value. Can be read/written by guest. */
     4.8 +    unsigned long guest_cr2;
     4.9 +
    4.10      /* shadow mode status and controls */
    4.11      unsigned int shadow_mode;  /* flags to control shadow table operation */
    4.12      pagetable_t  shadow_table;