ia64/xen-unstable

changeset 5186:a825a76d6b0f

bitkeeper revision 1.1577 (429831a31IZvEeEnalH3oKUTY7jV7A)

[PATCH] vmx-worldswitch-1-to-1.patch

Fix VMX world switch to use 1:1 page tables when the guest has paging
disabled. Also do a printk instead of VMX_DBG_LOG() anytime we crash
a domain.

Signed-off-by: Arun Sharma <arun.sharma@intel.com>
author arun.sharma@intel.com[kaf24]
date Sat May 28 08:53:55 2005 +0000 (2005-05-28)
parents af908567e181
children 7d7ad3d01377
files tools/libxc/xc_vmx_build.c xen/arch/x86/domain.c xen/arch/x86/vmx.c xen/arch/x86/vmx_io.c xen/arch/x86/vmx_platform.c xen/arch/x86/vmx_vmcs.c xen/arch/x86/x86_32/traps.c xen/include/asm-x86/shadow.h xen/include/asm-x86/vmx.h xen/include/asm-x86/vmx_vmcs.h
line diff
     1.1 --- a/tools/libxc/xc_vmx_build.c	Sat May 28 08:53:39 2005 +0000
     1.2 +++ b/tools/libxc/xc_vmx_build.c	Sat May 28 08:53:55 2005 +0000
     1.3 @@ -10,7 +10,7 @@
     1.4  #include <zlib.h>
     1.5  #include "linux_boot_params.h"
     1.6  
     1.7 -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
     1.8 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
     1.9  #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
    1.10  
    1.11  #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
     2.1 --- a/xen/arch/x86/domain.c	Sat May 28 08:53:39 2005 +0000
     2.2 +++ b/xen/arch/x86/domain.c	Sat May 28 08:53:55 2005 +0000
     2.3 @@ -339,7 +339,6 @@ static int vmx_final_setup_guest(
     2.4      }
     2.5  
     2.6      ed->arch.schedule_tail = arch_vmx_do_launch;
     2.7 -    clear_bit(VMX_CPU_STATE_PG_ENABLED, &ed->arch.arch_vmx.cpu_state);
     2.8  
     2.9  #if defined (__i386)
    2.10      ed->arch.arch_vmx.vmx_platform.real_mode_data = 
     3.1 --- a/xen/arch/x86/vmx.c	Sat May 28 08:53:39 2005 +0000
     3.2 +++ b/xen/arch/x86/vmx.c	Sat May 28 08:53:55 2005 +0000
     3.3 @@ -122,7 +122,6 @@ static void inline __update_guest_eip(un
     3.4  
     3.5  static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs) 
     3.6  {
     3.7 -    struct exec_domain *ed = current;
     3.8      unsigned long eip;
     3.9      l1_pgentry_t gpte;
    3.10      unsigned long gpa; /* FIXME: PAE */
    3.11 @@ -137,15 +136,8 @@ static int vmx_do_page_fault(unsigned lo
    3.12      }
    3.13  #endif
    3.14  
    3.15 -    /*
    3.16 -     * If vpagetable is zero, then we are still emulating 1:1 page tables,
    3.17 -     * and we should have never gotten here.
    3.18 -     */
    3.19 -    if ( !test_bit(VMX_CPU_STATE_PG_ENABLED, &ed->arch.arch_vmx.cpu_state) )
    3.20 -    {
    3.21 -        printk("vmx_do_page_fault while running on 1:1 page table\n");
    3.22 -        return 0;
    3.23 -    }
    3.24 +    if (!vmx_paging_enabled(current))
    3.25 +        handle_mmio(va, va);
    3.26  
    3.27      gpte = gva_to_gpte(va);
    3.28      if (!(l1e_get_flags(gpte) & _PAGE_PRESENT) )
    3.29 @@ -399,7 +391,7 @@ static void vmx_io_instruction(struct cp
    3.30  
    3.31      vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va;
    3.32      if (vio == 0) {
    3.33 -        VMX_DBG_LOG(DBG_LEVEL_1, "bad shared page: %lx", (unsigned long) vio);
    3.34 +        printk("bad shared page: %lx", (unsigned long) vio);
    3.35          domain_crash_synchronous(); 
    3.36      }
    3.37      p = &vio->vp_ioreq;
    3.38 @@ -423,7 +415,10 @@ static void vmx_io_instruction(struct cp
    3.39              laddr = (p->dir == IOREQ_WRITE) ? regs->esi : regs->edi;
    3.40          }
    3.41          p->pdata_valid = 1;
    3.42 -        p->u.pdata = (void *) gva_to_gpa(laddr);
    3.43 +
    3.44 +        p->u.data = laddr;
    3.45 +        if (vmx_paging_enabled(d))
    3.46 +                p->u.pdata = (void *) gva_to_gpa(p->u.data);
    3.47          p->df = (eflags & X86_EFLAGS_DF) ? 1 : 0;
    3.48  
    3.49          if (test_bit(5, &exit_qualification)) /* "rep" prefix */
    3.50 @@ -481,7 +476,7 @@ vmx_copy(void *buf, unsigned long laddr,
    3.51  	return 0;
    3.52      }
    3.53  
    3.54 -    mfn = phys_to_machine_mapping(l1e_get_pfn(gva_to_gpte(laddr)));
    3.55 +    mfn = phys_to_machine_mapping(laddr >> PAGE_SHIFT);
    3.56      addr = map_domain_mem((mfn << PAGE_SHIFT) | (laddr & ~PAGE_MASK));
    3.57  
    3.58      if (dir == COPY_IN)
    3.59 @@ -570,6 +565,12 @@ vmx_world_restore(struct exec_domain *d,
    3.60  
    3.61      error |= __vmwrite(CR0_READ_SHADOW, c->cr0);
    3.62  
    3.63 +    if (!vmx_paging_enabled(d)) {
    3.64 +	VMX_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table");
    3.65 +	__vmwrite(GUEST_CR3, pagetable_val(d->domain->arch.phys_table));
    3.66 +        goto skip_cr3;
    3.67 +    }
    3.68 +
    3.69      if (c->cr3 == d->arch.arch_vmx.cpu_cr3) {
    3.70  	/* 
    3.71  	 * This is simple TLB flush, implying the guest has 
    3.72 @@ -578,7 +579,7 @@ vmx_world_restore(struct exec_domain *d,
    3.73  	 */
    3.74  	mfn = phys_to_machine_mapping(c->cr3 >> PAGE_SHIFT);
    3.75  	if ((mfn << PAGE_SHIFT) != pagetable_val(d->arch.guest_table)) {
    3.76 -	    VMX_DBG_LOG(DBG_LEVEL_VMMU, "Invalid CR3 value=%lx", c->cr3);
    3.77 +	    printk("Invalid CR3 value=%lx", c->cr3);
    3.78  	    domain_crash_synchronous();
    3.79  	    return 0;
    3.80  	}
    3.81 @@ -590,7 +591,7 @@ vmx_world_restore(struct exec_domain *d,
    3.82  	 */
    3.83  	VMX_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %lx", c->cr3);
    3.84  	if ((c->cr3 >> PAGE_SHIFT) > d->domain->max_pages) {
    3.85 -	    VMX_DBG_LOG(DBG_LEVEL_VMMU, "Invalid CR3 value=%lx", c->cr3);
    3.86 +	    printk("Invalid CR3 value=%lx", c->cr3);
    3.87  	    domain_crash_synchronous(); 
    3.88  	    return 0;
    3.89  	}
    3.90 @@ -605,6 +606,8 @@ vmx_world_restore(struct exec_domain *d,
    3.91  	__vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
    3.92      }
    3.93  
    3.94 +skip_cr3:
    3.95 +
    3.96      error |= __vmread(CR4_READ_SHADOW, &old_cr4);
    3.97      error |= __vmwrite(GUEST_CR4, (c->cr4 | X86_CR4_VMXE));
    3.98      error |= __vmwrite(CR4_READ_SHADOW, c->cr4);
    3.99 @@ -731,18 +734,18 @@ static int vmx_set_cr0(unsigned long val
   3.100      struct exec_domain *d = current;
   3.101      unsigned long old_base_mfn, mfn;
   3.102      unsigned long eip;
   3.103 +    int paging_enabled;
   3.104  
   3.105      /* 
   3.106       * CR0: We don't want to lose PE and PG.
   3.107       */
   3.108 +    paging_enabled = vmx_paging_enabled(d);
   3.109      __vmwrite(GUEST_CR0, (value | X86_CR0_PE | X86_CR0_PG));
   3.110 +    __vmwrite(CR0_READ_SHADOW, value);
   3.111  
   3.112 -    if (value & (X86_CR0_PE | X86_CR0_PG) &&
   3.113 -        !test_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state)) {
   3.114 -        /*
   3.115 -         * Enable paging
   3.116 -         */
   3.117 -        set_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state);
   3.118 +    VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
   3.119 +    if ((value & X86_CR0_PE) && (value & X86_CR0_PG) 
   3.120 +        && !paging_enabled) {
   3.121          /*
   3.122           * The guest CR3 must be pointing to the guest physical.
   3.123           */
   3.124 @@ -750,8 +753,7 @@ static int vmx_set_cr0(unsigned long val
   3.125                              d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)) ||
   3.126               !get_page(pfn_to_page(mfn), d->domain) )
   3.127          {
   3.128 -            VMX_DBG_LOG(DBG_LEVEL_VMMU, "Invalid CR3 value = %lx",
   3.129 -                        d->arch.arch_vmx.cpu_cr3);
   3.130 +            printk("Invalid CR3 value = %lx", d->arch.arch_vmx.cpu_cr3);
   3.131              domain_crash_synchronous(); /* need to take a clean path */
   3.132          }
   3.133          old_base_mfn = pagetable_get_pfn(d->arch.guest_table);
   3.134 @@ -776,8 +778,7 @@ static int vmx_set_cr0(unsigned long val
   3.135      } else {
   3.136          if ((value & X86_CR0_PE) == 0) {
   3.137              __vmread(GUEST_EIP, &eip);
   3.138 -            VMX_DBG_LOG(DBG_LEVEL_1,
   3.139 -		"Disabling CR0.PE at %%eip 0x%lx", eip);
   3.140 +            VMX_DBG_LOG(DBG_LEVEL_1, "Disabling CR0.PE at %%eip 0x%lx\n", eip);
   3.141  	    if (vmx_assist(d, VMX_ASSIST_INVOKE)) {
   3.142  		set_bit(VMX_CPU_STATE_ASSIST_ENABLED,
   3.143  					&d->arch.arch_vmx.cpu_state);
   3.144 @@ -838,7 +839,6 @@ static int mov_to_cr(int gp, int cr, str
   3.145      switch(cr) {
   3.146      case 0: 
   3.147      {
   3.148 -	__vmwrite(CR0_READ_SHADOW, value);
   3.149  	return vmx_set_cr0(value);
   3.150      }
   3.151      case 3: 
   3.152 @@ -848,7 +848,7 @@ static int mov_to_cr(int gp, int cr, str
   3.153          /*
   3.154           * If paging is not enabled yet, simply copy the value to CR3.
   3.155           */
   3.156 -        if (!test_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state)) {
   3.157 +        if (!vmx_paging_enabled(d)) {
   3.158              d->arch.arch_vmx.cpu_cr3 = value;
   3.159              break;
   3.160          }
   3.161 @@ -876,8 +876,7 @@ static int mov_to_cr(int gp, int cr, str
   3.162                   !VALID_MFN(mfn = phys_to_machine_mapping(value >> PAGE_SHIFT)) ||
   3.163                   !get_page(pfn_to_page(mfn), d->domain) )
   3.164              {
   3.165 -                VMX_DBG_LOG(DBG_LEVEL_VMMU, 
   3.166 -                        "Invalid CR3 value=%lx", value);
   3.167 +                printk("Invalid CR3 value=%lx", value);
   3.168                  domain_crash_synchronous(); /* need to take a clean path */
   3.169              }
   3.170              old_base_mfn = pagetable_get_pfn(d->arch.guest_table);
   3.171 @@ -1133,6 +1132,7 @@ asmlinkage void vmx_vmexit_handler(struc
   3.172          VMX_DBG_LOG(DBG_LEVEL_0, "exit reason = %x", exit_reason);
   3.173  
   3.174      if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
   3.175 +        printk("Failed vm entry\n");
   3.176          domain_crash_synchronous();         
   3.177          return;
   3.178      }
     4.1 --- a/xen/arch/x86/vmx_io.c	Sat May 28 08:53:39 2005 +0000
     4.2 +++ b/xen/arch/x86/vmx_io.c	Sat May 28 08:53:55 2005 +0000
     4.3 @@ -465,7 +465,7 @@ void vmx_intr_assist(struct exec_domain 
     4.4  void vmx_do_resume(struct exec_domain *d) 
     4.5  {
     4.6      vmx_stts();
     4.7 -    if ( test_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state) )
     4.8 +    if ( vmx_paging_enabled(d) )
     4.9          __vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
    4.10      else
    4.11          // paging is not enabled in the guest
     5.1 --- a/xen/arch/x86/vmx_platform.c	Sat May 28 08:53:39 2005 +0000
     5.2 +++ b/xen/arch/x86/vmx_platform.c	Sat May 28 08:53:55 2005 +0000
     5.3 @@ -418,8 +418,12 @@ int inst_copy_from_guest(unsigned char *
     5.4      }
     5.5  
     5.6      if ((guest_eip & PAGE_MASK) == ((guest_eip + inst_len) & PAGE_MASK)) {
     5.7 -        gpte = gva_to_gpte(guest_eip);
     5.8 -        mfn = phys_to_machine_mapping(l1e_get_pfn(gpte));
     5.9 +        if (vmx_paging_enabled(current)) {
    5.10 +                gpte = gva_to_gpte(guest_eip);
    5.11 +                mfn = phys_to_machine_mapping(l1e_get_pfn(gpte));
    5.12 +        } else {
    5.13 +                mfn = phys_to_machine_mapping(guest_eip >> PAGE_SHIFT);
    5.14 +        }
    5.15          ma = (mfn << PAGE_SHIFT) | (guest_eip & (PAGE_SIZE - 1));
    5.16          inst_start = (unsigned char *)map_domain_mem(ma);
    5.17                  
    5.18 @@ -508,7 +512,7 @@ static void send_mmio_req(unsigned long 
    5.19      } else
    5.20          p->count = 1;
    5.21  
    5.22 -    if (pvalid)
    5.23 +    if ((pvalid) && vmx_paging_enabled(current))
    5.24          p->u.pdata = (void *) gva_to_gpa(p->u.data);
    5.25  
    5.26  #if 0
     6.1 --- a/xen/arch/x86/vmx_vmcs.c	Sat May 28 08:53:39 2005 +0000
     6.2 +++ b/xen/arch/x86/vmx_vmcs.c	Sat May 28 08:53:55 2005 +0000
     6.3 @@ -291,7 +291,7 @@ construct_init_vmcs_guest(struct cpu_use
     6.4  
     6.5      /* Initally PG, PE are not set*/
     6.6      shadow_cr = host_env->cr0;
     6.7 -    shadow_cr &= ~(X86_CR0_PE | X86_CR0_PG);
     6.8 +    shadow_cr &= ~X86_CR0_PG;
     6.9      error |= __vmwrite(CR0_READ_SHADOW, shadow_cr);
    6.10      /* CR3 is set in vmx_final_setup_guest */
    6.11      error |= __vmwrite(GUEST_CR4, host_env->cr4);
     7.1 --- a/xen/arch/x86/x86_32/traps.c	Sat May 28 08:53:39 2005 +0000
     7.2 +++ b/xen/arch/x86/x86_32/traps.c	Sat May 28 08:53:55 2005 +0000
     7.3 @@ -20,8 +20,9 @@ void show_registers(struct cpu_user_regs
     7.4      unsigned long ss, ds, es, fs, gs, cs;
     7.5      unsigned long eip, esp, eflags;
     7.6      const char *context;
     7.7 +#ifdef CONFIG_VMX
     7.8 +    unsigned long cr0, cr3;
     7.9  
    7.10 -#ifdef CONFIG_VMX
    7.11      if ( VMX_DOMAIN(current) && (regs->eflags == 0) )
    7.12      {
    7.13          __vmread(GUEST_EIP, &eip);
    7.14 @@ -33,6 +34,8 @@ void show_registers(struct cpu_user_regs
    7.15          __vmread(GUEST_FS_SELECTOR, &fs);
    7.16          __vmread(GUEST_GS_SELECTOR, &gs);
    7.17          __vmread(GUEST_CS_SELECTOR, &cs);
    7.18 +        __vmread(CR0_READ_SHADOW, &cr0);
    7.19 +        __vmread(GUEST_CR3, &cr3);
    7.20          context = "vmx guest";
    7.21      }
    7.22      else
    7.23 @@ -77,6 +80,9 @@ void show_registers(struct cpu_user_regs
    7.24      printk("ds: %04lx   es: %04lx   fs: %04lx   gs: %04lx   "
    7.25             "ss: %04lx   cs: %04lx\n",
    7.26             ds, es, fs, gs, ss, cs);
    7.27 +#ifdef CONFIG_VMX
    7.28 +    printk("cr0: %08lx   cr3: %08lx\n", cr0, cr3);
    7.29 +#endif
    7.30  
    7.31      if ( GUEST_MODE(regs) )
    7.32          show_guest_stack();
     8.1 --- a/xen/include/asm-x86/shadow.h	Sat May 28 08:53:39 2005 +0000
     8.2 +++ b/xen/include/asm-x86/shadow.h	Sat May 28 08:53:55 2005 +0000
     8.3 @@ -31,6 +31,9 @@
     8.4  #include <asm/processor.h>
     8.5  #include <asm/domain_page.h>
     8.6  #include <public/dom0_ops.h>
     8.7 +#ifdef CONFIG_VMX
     8.8 +#include <asm/vmx.h>
     8.9 +#endif
    8.10  
    8.11  /* Shadow PT operation mode : shadow-mode variable in arch_domain. */
    8.12  
    8.13 @@ -1672,8 +1675,8 @@ static inline void update_pagetables(str
    8.14  
    8.15  #ifdef CONFIG_VMX
    8.16      if ( VMX_DOMAIN(ed) )
    8.17 -        paging_enabled =
    8.18 -            test_bit(VMX_CPU_STATE_PG_ENABLED, &ed->arch.arch_vmx.cpu_state);
    8.19 +        paging_enabled = vmx_paging_enabled(ed);
    8.20 +            
    8.21      else
    8.22  #endif
    8.23          // HACK ALERT: there's currently no easy way to figure out if a domU
     9.1 --- a/xen/include/asm-x86/vmx.h	Sat May 28 08:53:39 2005 +0000
     9.2 +++ b/xen/include/asm-x86/vmx.h	Sat May 28 08:53:55 2005 +0000
     9.3 @@ -294,5 +294,14 @@ static inline void vmx_stts()
     9.4      if (!(cr0 & X86_CR0_TS))
     9.5         __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
     9.6  }
     9.7 - 
     9.8 +
     9.9 +/* Works only for ed == current */
    9.10 +static inline int vmx_paging_enabled(struct exec_domain *ed)
    9.11 +{
    9.12 +    unsigned long cr0;
    9.13 +
    9.14 +    __vmread(CR0_READ_SHADOW, &cr0);
    9.15 +    return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
    9.16 +}
    9.17 +
    9.18  #endif /* __ASM_X86_VMX_H__ */
    10.1 --- a/xen/include/asm-x86/vmx_vmcs.h	Sat May 28 08:53:39 2005 +0000
    10.2 +++ b/xen/include/asm-x86/vmx_vmcs.h	Sat May 28 08:53:55 2005 +0000
    10.3 @@ -29,7 +29,6 @@ extern void stop_vmx(void);
    10.4  
    10.5  void vmx_enter_scheduler(void);
    10.6  
    10.7 -#define VMX_CPU_STATE_PG_ENABLED        0       
    10.8  #define	VMX_CPU_STATE_ASSIST_ENABLED	1
    10.9  
   10.10  struct vmcs_struct {