ia64/xen-unstable

changeset 15930:6146bea9e67f

hvm: hvm_{load,store}_cpu_guest_regs() does not touch segment
selectors. We have separate accessors for that now. It is now an
invariant that guest_cpu_user_regs()->{cs,ds,es,fs,gs,ss} are invalid
for an HVM guest.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Sep 19 10:24:24 2007 +0100 (2007-09-19)
parents 45548c83daef
children fadd1f8222b3
files xen/arch/x86/domctl.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/platform.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/mm/shadow/multi.c xen/arch/x86/oprofile/op_model_athlon.c xen/arch/x86/x86_32/traps.c xen/arch/x86/x86_64/traps.c xen/include/asm-x86/hvm/hvm.h
line diff
     1.1 --- a/xen/arch/x86/domctl.c	Wed Sep 19 09:24:20 2007 +0100
     1.2 +++ b/xen/arch/x86/domctl.c	Wed Sep 19 10:24:24 2007 +0100
     1.3 @@ -555,18 +555,27 @@ void arch_get_info_guest(struct vcpu *v,
     1.4      if ( is_hvm_vcpu(v) )
     1.5      {
     1.6          if ( !is_pv_32on64_domain(v->domain) )
     1.7 -            hvm_store_cpu_guest_regs(v, &c.nat->user_regs, c.nat->ctrlreg);
     1.8 +        {
     1.9 +            hvm_store_cpu_guest_regs(v, &c.nat->user_regs);
    1.10 +            memset(c.nat->ctrlreg, 0, sizeof(c.nat->ctrlreg));
    1.11 +            c.nat->ctrlreg[0] = v->arch.hvm_vcpu.guest_cr[0];
    1.12 +            c.nat->ctrlreg[2] = v->arch.hvm_vcpu.guest_cr[2];
    1.13 +            c.nat->ctrlreg[3] = v->arch.hvm_vcpu.guest_cr[3];
    1.14 +            c.nat->ctrlreg[4] = v->arch.hvm_vcpu.guest_cr[4];
    1.15 +        }
    1.16  #ifdef CONFIG_COMPAT
    1.17          else
    1.18          {
    1.19              struct cpu_user_regs user_regs;
    1.20 -            typeof(c.nat->ctrlreg) ctrlreg;
    1.21              unsigned i;
    1.22  
    1.23 -            hvm_store_cpu_guest_regs(v, &user_regs, ctrlreg);
    1.24 +            hvm_store_cpu_guest_regs(v, &user_regs);
    1.25              XLAT_cpu_user_regs(&c.cmp->user_regs, &user_regs);
    1.26 -            for ( i = 0; i < ARRAY_SIZE(c.cmp->ctrlreg); ++i )
    1.27 -                c.cmp->ctrlreg[i] = ctrlreg[i];
    1.28 +            memset(c.cmp->ctrlreg, 0, sizeof(c.cmp->ctrlreg));
    1.29 +            c.cmp->ctrlreg[0] = v->arch.hvm_vcpu.guest_cr[0];
    1.30 +            c.cmp->ctrlreg[2] = v->arch.hvm_vcpu.guest_cr[2];
    1.31 +            c.cmp->ctrlreg[3] = v->arch.hvm_vcpu.guest_cr[3];
    1.32 +            c.cmp->ctrlreg[4] = v->arch.hvm_vcpu.guest_cr[4];
    1.33          }
    1.34  #endif
    1.35      }
     2.1 --- a/xen/arch/x86/hvm/hvm.c	Wed Sep 19 09:24:20 2007 +0100
     2.2 +++ b/xen/arch/x86/hvm/hvm.c	Wed Sep 19 10:24:24 2007 +0100
     2.3 @@ -973,7 +973,7 @@ void hvm_task_switch(
     2.4          goto out;
     2.5      }
     2.6  
     2.7 -    hvm_store_cpu_guest_regs(v, regs, NULL);
     2.8 +    hvm_store_cpu_guest_regs(v, regs);
     2.9  
    2.10      ptss = hvm_map(prev_tr.base, sizeof(tss));
    2.11      if ( ptss == NULL )
    2.12 @@ -1322,7 +1322,7 @@ int hvm_do_hypercall(struct cpu_user_reg
    2.13  #endif
    2.14      case 4:
    2.15      case 2:
    2.16 -        hvm_store_cpu_guest_regs(current, regs, NULL);
    2.17 +        hvm_store_cpu_guest_regs(current, regs);
    2.18          if ( unlikely(ring_3(regs)) )
    2.19          {
    2.20      default:
     3.1 --- a/xen/arch/x86/hvm/platform.c	Wed Sep 19 09:24:20 2007 +0100
     3.2 +++ b/xen/arch/x86/hvm/platform.c	Wed Sep 19 10:24:24 2007 +0100
     3.3 @@ -1032,7 +1032,7 @@ void handle_mmio(unsigned long gpa)
     3.4  
     3.5      /* Copy current guest state into io instruction state structure. */
     3.6      memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
     3.7 -    hvm_store_cpu_guest_regs(v, regs, NULL);
     3.8 +    hvm_store_cpu_guest_regs(v, regs);
     3.9  
    3.10      df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
    3.11  
     4.1 --- a/xen/arch/x86/hvm/svm/svm.c	Wed Sep 19 09:24:20 2007 +0100
     4.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Wed Sep 19 10:24:24 2007 +0100
     4.3 @@ -109,27 +109,13 @@ static int svm_lme_is_set(struct vcpu *v
     4.4  }
     4.5  
     4.6  static void svm_store_cpu_guest_regs(
     4.7 -    struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs)
     4.8 +    struct vcpu *v, struct cpu_user_regs *regs)
     4.9  {
    4.10      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
    4.11  
    4.12 -    if ( regs != NULL )
    4.13 -    {
    4.14 -        regs->ss     = vmcb->ss.sel;
    4.15 -        regs->esp    = vmcb->rsp;
    4.16 -        regs->eflags = vmcb->rflags;
    4.17 -        regs->cs     = vmcb->cs.sel;
    4.18 -        regs->eip    = vmcb->rip;
    4.19 -    }
    4.20 -
    4.21 -    if ( crs != NULL )
    4.22 -    {
    4.23 -        /* Returning the guest's regs */
    4.24 -        crs[0] = v->arch.hvm_vcpu.guest_cr[0];
    4.25 -        crs[2] = v->arch.hvm_vcpu.guest_cr[2];
    4.26 -        crs[3] = v->arch.hvm_vcpu.guest_cr[3];
    4.27 -        crs[4] = v->arch.hvm_vcpu.guest_cr[4];
    4.28 -    }
    4.29 +    regs->esp    = vmcb->rsp;
    4.30 +    regs->eflags = vmcb->rflags;
    4.31 +    regs->eip    = vmcb->rip;
    4.32  }
    4.33  
    4.34  static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
    4.35 @@ -702,7 +688,6 @@ static void svm_set_segment_register(str
    4.36      {
    4.37      case x86_seg_cs:
    4.38          memcpy(&vmcb->cs, reg, sizeof(*reg));
    4.39 -        guest_cpu_user_regs()->cs = reg->sel;
    4.40          break;
    4.41      case x86_seg_ds:
    4.42          memcpy(&vmcb->ds, reg, sizeof(*reg));
    4.43 @@ -722,7 +707,7 @@ static void svm_set_segment_register(str
    4.44          break;
    4.45      case x86_seg_ss:
    4.46          memcpy(&vmcb->ss, reg, sizeof(*reg));
    4.47 -        guest_cpu_user_regs()->ss = reg->sel;
    4.48 +        vmcb->cpl = vmcb->ss.attr.fields.dpl;
    4.49          break;
    4.50      case x86_seg_tr:
    4.51          svm_sync_vmcb(v);
    4.52 @@ -829,10 +814,8 @@ static void svm_load_cpu_guest_regs(stru
    4.53  {
    4.54      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
    4.55  
    4.56 -    vmcb->ss.sel   = regs->ss;
    4.57      vmcb->rsp      = regs->esp;   
    4.58      vmcb->rflags   = regs->eflags | 2UL;
    4.59 -    vmcb->cs.sel   = regs->cs;
    4.60      vmcb->rip      = regs->eip;
    4.61  }
    4.62  
    4.63 @@ -1518,7 +1501,7 @@ static void svm_io_instruction(struct vc
    4.64  
    4.65      /* Copy current guest state into io instruction state structure. */
    4.66      memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
    4.67 -    svm_store_cpu_guest_regs(v, regs, NULL);
    4.68 +    svm_store_cpu_guest_regs(v, regs);
    4.69  
    4.70      info.bytes = vmcb->exitinfo1;
    4.71  
    4.72 @@ -2292,7 +2275,7 @@ asmlinkage void svm_vmexit_handler(struc
    4.73  
    4.74      case VMEXIT_EXCEPTION_MC:
    4.75          HVMTRACE_0D(MCE, v);
    4.76 -        svm_store_cpu_guest_regs(v, regs, NULL);
    4.77 +        svm_store_cpu_guest_regs(v, regs);
    4.78          do_machine_check(regs);
    4.79          break;
    4.80  
     5.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed Sep 19 09:24:20 2007 +0100
     5.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed Sep 19 10:24:24 2007 +0100
     5.3 @@ -794,61 +794,25 @@ static void vmx_ctxt_switch_to(struct vc
     5.4  }
     5.5  
     5.6  static void vmx_store_cpu_guest_regs(
     5.7 -    struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs)
     5.8 +    struct vcpu *v, struct cpu_user_regs *regs)
     5.9  {
    5.10      vmx_vmcs_enter(v);
    5.11  
    5.12 -    if ( regs != NULL )
    5.13 -    {
    5.14 -        regs->eflags = __vmread(GUEST_RFLAGS);
    5.15 -        regs->ss = __vmread(GUEST_SS_SELECTOR);
    5.16 -        regs->cs = __vmread(GUEST_CS_SELECTOR);
    5.17 -        regs->eip = __vmread(GUEST_RIP);
    5.18 -        regs->esp = __vmread(GUEST_RSP);
    5.19 -    }
    5.20 -
    5.21 -    if ( crs != NULL )
    5.22 -    {
    5.23 -        crs[0] = v->arch.hvm_vcpu.guest_cr[0];
    5.24 -        crs[2] = v->arch.hvm_vcpu.guest_cr[2];
    5.25 -        crs[3] = v->arch.hvm_vcpu.guest_cr[3];
    5.26 -        crs[4] = v->arch.hvm_vcpu.guest_cr[4];
    5.27 -    }
    5.28 +    regs->eflags = __vmread(GUEST_RFLAGS);
    5.29 +    regs->eip = __vmread(GUEST_RIP);
    5.30 +    regs->esp = __vmread(GUEST_RSP);
    5.31  
    5.32      vmx_vmcs_exit(v);
    5.33  }
    5.34  
    5.35  static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
    5.36  {
    5.37 -    unsigned long base;
    5.38 -
    5.39      vmx_vmcs_enter(v);
    5.40  
    5.41 -    __vmwrite(GUEST_SS_SELECTOR, regs->ss);
    5.42 -    __vmwrite(GUEST_RSP, regs->esp);
    5.43 -
    5.44      /* NB. Bit 1 of RFLAGS must be set for VMENTRY to succeed. */
    5.45      __vmwrite(GUEST_RFLAGS, regs->eflags | 2UL);
    5.46 -
    5.47 -    if ( regs->eflags & EF_VM )
    5.48 -    {
    5.49 -        /*
    5.50 -         * The VMX spec (section 4.3.1.2, Checks on Guest Segment
    5.51 -         * Registers) says that virtual-8086 mode guests' segment
    5.52 -         * base-address fields in the VMCS must be equal to their
    5.53 -         * corresponding segment selector field shifted right by
    5.54 -         * four bits upon vmentry.
    5.55 -         */
    5.56 -        base = __vmread(GUEST_CS_BASE);
    5.57 -        if ( (regs->cs << 4) != base )
    5.58 -            __vmwrite(GUEST_CS_BASE, regs->cs << 4);
    5.59 -        base = __vmread(GUEST_SS_BASE);
    5.60 -        if ( (regs->ss << 4) != base )
    5.61 -            __vmwrite(GUEST_SS_BASE, regs->ss << 4);
    5.62 -    }
    5.63 -
    5.64 -    __vmwrite(GUEST_CS_SELECTOR, regs->cs);
    5.65      __vmwrite(GUEST_RIP, regs->eip);
    5.66 +    __vmwrite(GUEST_RSP, regs->esp);
    5.67  
    5.68      vmx_vmcs_exit(v);
    5.69  }
    5.70 @@ -978,7 +942,6 @@ static void vmx_set_segment_register(str
    5.71          __vmwrite(GUEST_CS_LIMIT, reg->limit);
    5.72          __vmwrite(GUEST_CS_BASE, reg->base);
    5.73          __vmwrite(GUEST_CS_AR_BYTES, attr);
    5.74 -        guest_cpu_user_regs()->cs = reg->sel;
    5.75          break;
    5.76      case x86_seg_ds:
    5.77          __vmwrite(GUEST_DS_SELECTOR, reg->sel);
    5.78 @@ -1009,7 +972,6 @@ static void vmx_set_segment_register(str
    5.79          __vmwrite(GUEST_SS_LIMIT, reg->limit);
    5.80          __vmwrite(GUEST_SS_BASE, reg->base);
    5.81          __vmwrite(GUEST_SS_AR_BYTES, attr);
    5.82 -        guest_cpu_user_regs()->ss = reg->sel;
    5.83          break;
    5.84      case x86_seg_tr:
    5.85          __vmwrite(GUEST_TR_SELECTOR, reg->sel);
    5.86 @@ -1890,7 +1852,7 @@ static void vmx_io_instruction(unsigned 
    5.87  
    5.88      /* Copy current guest state into io instruction state structure. */
    5.89      memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
    5.90 -    vmx_store_cpu_guest_regs(current, regs, NULL);
    5.91 +    vmx_store_cpu_guest_regs(current, regs);
    5.92  
    5.93      HVM_DBG_LOG(DBG_LEVEL_IO, "vm86 %d, eip=%x:%lx, "
    5.94                  "exit_qualification = %lx",
    5.95 @@ -2639,7 +2601,7 @@ static void vmx_failed_vmentry(unsigned 
    5.96      case EXIT_REASON_MACHINE_CHECK:
    5.97          printk("caused by machine check.\n");
    5.98          HVMTRACE_0D(MCE, current);
    5.99 -        vmx_store_cpu_guest_regs(current, regs, NULL);
   5.100 +        vmx_store_cpu_guest_regs(current, regs);
   5.101          do_machine_check(regs);
   5.102          break;
   5.103      default:
   5.104 @@ -2761,12 +2723,12 @@ asmlinkage void vmx_vmexit_handler(struc
   5.105                   (X86_EVENTTYPE_NMI << 8) )
   5.106                  goto exit_and_crash;
   5.107              HVMTRACE_0D(NMI, v);
   5.108 -            vmx_store_cpu_guest_regs(v, regs, NULL);
   5.109 +            vmx_store_cpu_guest_regs(v, regs);
   5.110              do_nmi(regs); /* Real NMI, vector 2: normal processing. */
   5.111              break;
   5.112          case TRAP_machine_check:
   5.113              HVMTRACE_0D(MCE, v);
   5.114 -            vmx_store_cpu_guest_regs(v, regs, NULL);
   5.115 +            vmx_store_cpu_guest_regs(v, regs);
   5.116              do_machine_check(regs);
   5.117              break;
   5.118          default:
     6.1 --- a/xen/arch/x86/mm/shadow/multi.c	Wed Sep 19 09:24:20 2007 +0100
     6.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Wed Sep 19 10:24:24 2007 +0100
     6.3 @@ -2929,7 +2929,7 @@ static int sh_page_fault(struct vcpu *v,
     6.4              goto done;
     6.5          }
     6.6  
     6.7 -        hvm_store_cpu_guest_regs(v, regs, NULL);
     6.8 +        hvm_store_cpu_guest_regs(v, regs);
     6.9      }
    6.10  
    6.11      SHADOW_PRINTK("emulate: eip=%#lx esp=%#lx\n", 
     7.1 --- a/xen/arch/x86/oprofile/op_model_athlon.c	Wed Sep 19 09:24:20 2007 +0100
     7.2 +++ b/xen/arch/x86/oprofile/op_model_athlon.c	Wed Sep 19 10:24:24 2007 +0100
     7.3 @@ -119,7 +119,7 @@ static int athlon_check_ctrs(unsigned in
     7.4  	    (regs->eip == (unsigned long)svm_stgi_label)) {
     7.5  		/* SVM guest was running when NMI occurred */
     7.6  		ASSERT(is_hvm_vcpu(v));
     7.7 -		hvm_store_cpu_guest_regs(v, guest_regs, NULL);
     7.8 +		hvm_store_cpu_guest_regs(v, guest_regs);
     7.9  		eip = guest_regs->eip;
    7.10  		mode = xenoprofile_get_mode(v, guest_regs);
    7.11  	} else {
     8.1 --- a/xen/arch/x86/x86_32/traps.c	Wed Sep 19 09:24:20 2007 +0100
     8.2 +++ b/xen/arch/x86/x86_32/traps.c	Wed Sep 19 10:24:24 2007 +0100
     8.3 @@ -41,11 +41,29 @@ void show_registers(struct cpu_user_regs
     8.4      struct cpu_user_regs fault_regs = *regs;
     8.5      unsigned long fault_crs[8];
     8.6      const char *context;
     8.7 +    struct vcpu *v = current;
     8.8  
     8.9 -    if ( is_hvm_vcpu(current) && guest_mode(regs) )
    8.10 +    if ( is_hvm_vcpu(v) && guest_mode(regs) )
    8.11      {
    8.12 +        struct segment_register sreg;
    8.13          context = "hvm";
    8.14 -        hvm_store_cpu_guest_regs(current, &fault_regs, fault_crs);
    8.15 +        hvm_store_cpu_guest_regs(v, &fault_regs);
    8.16 +        fault_crs[0] = v->arch.hvm_vcpu.guest_cr[0];
    8.17 +        fault_crs[2] = v->arch.hvm_vcpu.guest_cr[2];
    8.18 +        fault_crs[3] = v->arch.hvm_vcpu.guest_cr[3];
    8.19 +        fault_crs[4] = v->arch.hvm_vcpu.guest_cr[4];
    8.20 +        hvm_get_segment_register(v, x86_seg_cs, &sreg);
    8.21 +        fault_regs.cs = sreg.sel;
    8.22 +        hvm_get_segment_register(v, x86_seg_ds, &sreg);
    8.23 +        fault_regs.ds = sreg.sel;
    8.24 +        hvm_get_segment_register(v, x86_seg_es, &sreg);
    8.25 +        fault_regs.es = sreg.sel;
    8.26 +        hvm_get_segment_register(v, x86_seg_fs, &sreg);
    8.27 +        fault_regs.fs = sreg.sel;
    8.28 +        hvm_get_segment_register(v, x86_seg_gs, &sreg);
    8.29 +        fault_regs.gs = sreg.sel;
    8.30 +        hvm_get_segment_register(v, x86_seg_ss, &sreg);
    8.31 +        fault_regs.ss = sreg.sel;
    8.32      }
    8.33      else
    8.34      {
    8.35 @@ -63,7 +81,7 @@ void show_registers(struct cpu_user_regs
    8.36          else
    8.37          {
    8.38              context = "guest";
    8.39 -            fault_crs[2] = current->vcpu_info->arch.cr2;
    8.40 +            fault_crs[2] = v->vcpu_info->arch.cr2;
    8.41          }
    8.42  
    8.43          fault_crs[0] = read_cr0();
     9.1 --- a/xen/arch/x86/x86_64/traps.c	Wed Sep 19 09:24:20 2007 +0100
     9.2 +++ b/xen/arch/x86/x86_64/traps.c	Wed Sep 19 10:24:24 2007 +0100
     9.3 @@ -44,18 +44,36 @@ void show_registers(struct cpu_user_regs
     9.4      struct cpu_user_regs fault_regs = *regs;
     9.5      unsigned long fault_crs[8];
     9.6      const char *context;
     9.7 +    struct vcpu *v = current;
     9.8  
     9.9 -    if ( is_hvm_vcpu(current) && guest_mode(regs) )
    9.10 +    if ( is_hvm_vcpu(v) && guest_mode(regs) )
    9.11      {
    9.12 +        struct segment_register sreg;
    9.13          context = "hvm";
    9.14 -        hvm_store_cpu_guest_regs(current, &fault_regs, fault_crs);
    9.15 +        hvm_store_cpu_guest_regs(v, &fault_regs);
    9.16 +        fault_crs[0] = v->arch.hvm_vcpu.guest_cr[0];
    9.17 +        fault_crs[2] = v->arch.hvm_vcpu.guest_cr[2];
    9.18 +        fault_crs[3] = v->arch.hvm_vcpu.guest_cr[3];
    9.19 +        fault_crs[4] = v->arch.hvm_vcpu.guest_cr[4];
    9.20 +        hvm_get_segment_register(v, x86_seg_cs, &sreg);
    9.21 +        fault_regs.cs = sreg.sel;
    9.22 +        hvm_get_segment_register(v, x86_seg_ds, &sreg);
    9.23 +        fault_regs.ds = sreg.sel;
    9.24 +        hvm_get_segment_register(v, x86_seg_es, &sreg);
    9.25 +        fault_regs.es = sreg.sel;
    9.26 +        hvm_get_segment_register(v, x86_seg_fs, &sreg);
    9.27 +        fault_regs.fs = sreg.sel;
    9.28 +        hvm_get_segment_register(v, x86_seg_gs, &sreg);
    9.29 +        fault_regs.gs = sreg.sel;
    9.30 +        hvm_get_segment_register(v, x86_seg_ss, &sreg);
    9.31 +        fault_regs.ss = sreg.sel;
    9.32      }
    9.33      else
    9.34      {
    9.35          if ( guest_mode(regs) )
    9.36          {
    9.37              context = "guest";
    9.38 -            fault_crs[2] = arch_get_cr2(current);
    9.39 +            fault_crs[2] = arch_get_cr2(v);
    9.40          }
    9.41          else
    9.42          {
    10.1 --- a/xen/include/asm-x86/hvm/hvm.h	Wed Sep 19 09:24:20 2007 +0100
    10.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Wed Sep 19 10:24:24 2007 +0100
    10.3 @@ -85,7 +85,7 @@ struct hvm_function_table {
    10.4       * 2) modify guest state (e.g., set debug flags).
    10.5       */
    10.6      void (*store_cpu_guest_regs)(
    10.7 -        struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs);
    10.8 +        struct vcpu *v, struct cpu_user_regs *r);
    10.9      void (*load_cpu_guest_regs)(
   10.10          struct vcpu *v, struct cpu_user_regs *r);
   10.11  
   10.12 @@ -168,9 +168,9 @@ void hvm_send_assist_req(struct vcpu *v)
   10.13  
   10.14  static inline void
   10.15  hvm_store_cpu_guest_regs(
   10.16 -    struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs)
   10.17 +    struct vcpu *v, struct cpu_user_regs *r)
   10.18  {
   10.19 -    hvm_funcs.store_cpu_guest_regs(v, r, crs);
   10.20 +    hvm_funcs.store_cpu_guest_regs(v, r);
   10.21  }
   10.22  
   10.23  static inline void