[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] [v2] xen: Add FS and GS base to HVM VCPU context



On Tue, Apr 24, 2012 at 1:20 PM, Keir Fraser <keir.xen@xxxxxxxxx> wrote:
> On 24/04/2012 20:35, "Aravindh Puthiyaparambil" <aravindh@xxxxxxxxxxxx>
> wrote:
>
>> On Tue, Apr 24, 2012 at 10:33 AM, Aravindh Puthiyaparambil
>> <aravindh@xxxxxxxxxxxx> wrote:
>>> On Tue, Apr 24, 2012 at 12:52 AM, Jan Beulich <JBeulich@xxxxxxxx> wrote:
>
>>>> Which still leaves one of gs_base_* unfilled in all cases. You'll need
>>>> to get ahold of vmcb->kerngsbase (AMD/SVM) or
>>>> v->arch.hvm_vmx.shadow_gs (Intel/VMX). You could either
>>>> introduce a new wrapper, or expose {svm,vmx}_save_cpu_state()
>>>> as a new function table entry, or pay the price of calling
>>>> ->save_cpu_ctxt(). But you will need to pay extra attention to
>>>> the case of the subject vCPU being current.
>>>
>>> OK, I will try introducing a new wrapper that will return
>>> vmcb->kerngsbase /  v->arch.hvm_vmx.shadow_gs.
>>
>> Jan,
>>
>> How does this look?
>
> Only the code in domctl.c needs to be ifdef x86_64. In fact as it is, the
> patch won't compile on i386, as you have inconsistently ifdef'ed. Just
> remove the ifdefs as far as possible, we'd rather have dead code on i386
> than ifdefs.

Does this look better? I couldn't get away with adding ifdef x86_64
only to domctl.c. I also had to add it to the
(svm/vmx)_get_shadow_gs_base(). It now complies for x86_32.

Aravindh

diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1585,18 +1585,33 @@ void arch_get_info_guest(struct vcpu *v,
         hvm_get_segment_register(v, x86_seg_ss, &sreg);
         c.nat->user_regs.ss = sreg.sel;
         hvm_get_segment_register(v, x86_seg_ds, &sreg);
         c.nat->user_regs.ds = sreg.sel;
         hvm_get_segment_register(v, x86_seg_es, &sreg);
         c.nat->user_regs.es = sreg.sel;
         hvm_get_segment_register(v, x86_seg_fs, &sreg);
         c.nat->user_regs.fs = sreg.sel;
+#ifdef __x86_64__
+        c.nat->fs_base = sreg.base;
+#endif
         hvm_get_segment_register(v, x86_seg_gs, &sreg);
         c.nat->user_regs.gs = sreg.sel;
+#ifdef __x86_64__
+        if ( ring_0(&c.nat->user_regs) )
+        {
+            c.nat->gs_base_kernel = sreg.base;
+            c.nat->gs_base_user = hvm_get_shadow_gs_base(v);
+        }
+        else
+        {
+            c.nat->gs_base_user = sreg.base;
+            c.nat->gs_base_kernel = hvm_get_shadow_gs_base(v);
+        }
+#endif
     }
     else
     {
         c(ldt_base = v->arch.pv_vcpu.ldt_base);
         c(ldt_ents = v->arch.pv_vcpu.ldt_ents);
         for ( i = 0; i < ARRAY_SIZE(v->arch.pv_vcpu.gdt_frames); ++i )
             c(gdt_frames[i] = v->arch.pv_vcpu.gdt_frames[i]);
 #ifdef CONFIG_COMPAT
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -640,16 +640,27 @@ static void svm_set_segment_register(str
     default:
         BUG();
     }

     if ( sync )
         svm_vmload(vmcb);
 }

+static unsigned long svm_get_shadow_gs_base(struct vcpu *v)
+{
+#ifdef __x86_64__
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    return vmcb->kerngsbase;
+#else
+    return 0;
+#endif
+}
+
 static int svm_set_guest_pat(struct vcpu *v, u64 gpat)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;

     if ( !paging_mode_hap(v->domain) )
         return 0;

     vmcb_set_g_pat(vmcb, gpat);
@@ -1978,16 +1989,17 @@ static struct hvm_function_table __read_
     .vcpu_destroy         = svm_vcpu_destroy,
     .save_cpu_ctxt        = svm_save_vmcb_ctxt,
     .load_cpu_ctxt        = svm_load_vmcb_ctxt,
     .get_interrupt_shadow = svm_get_interrupt_shadow,
     .set_interrupt_shadow = svm_set_interrupt_shadow,
     .guest_x86_mode       = svm_guest_x86_mode,
     .get_segment_register = svm_get_segment_register,
     .set_segment_register = svm_set_segment_register,
+    .get_shadow_gs_base   = svm_get_shadow_gs_base,
     .update_host_cr3      = svm_update_host_cr3,
     .update_guest_cr      = svm_update_guest_cr,
     .update_guest_efer    = svm_update_guest_efer,
     .set_guest_pat        = svm_set_guest_pat,
     .get_guest_pat        = svm_get_guest_pat,
     .set_tsc_offset       = svm_set_tsc_offset,
     .inject_exception     = svm_inject_exception,
     .init_hypercall_page  = svm_init_hypercall_page,
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -937,16 +937,25 @@ static void vmx_set_segment_register(str
         break;
     default:
         BUG();
     }

     vmx_vmcs_exit(v);
 }

+static unsigned long vmx_get_shadow_gs_base(struct vcpu *v)
+{
+#ifdef __x86_64__
+    return v->arch.hvm_vmx.shadow_gs;
+#else
+    return 0;
+#endif
+}
+
 static int vmx_set_guest_pat(struct vcpu *v, u64 gpat)
 {
     if ( !cpu_has_vmx_pat || !paging_mode_hap(v->domain) )
         return 0;

     vmx_vmcs_enter(v);
     __vmwrite(GUEST_PAT, gpat);
 #ifdef __i386__
@@ -1517,16 +1526,17 @@ static struct hvm_function_table __read_
     .vcpu_destroy         = vmx_vcpu_destroy,
     .save_cpu_ctxt        = vmx_save_vmcs_ctxt,
     .load_cpu_ctxt        = vmx_load_vmcs_ctxt,
     .get_interrupt_shadow = vmx_get_interrupt_shadow,
     .set_interrupt_shadow = vmx_set_interrupt_shadow,
     .guest_x86_mode       = vmx_guest_x86_mode,
     .get_segment_register = vmx_get_segment_register,
     .set_segment_register = vmx_set_segment_register,
+    .get_shadow_gs_base   = vmx_get_shadow_gs_base,
     .update_host_cr3      = vmx_update_host_cr3,
     .update_guest_cr      = vmx_update_guest_cr,
     .update_guest_efer    = vmx_update_guest_efer,
     .set_guest_pat        = vmx_set_guest_pat,
     .get_guest_pat        = vmx_get_guest_pat,
     .set_tsc_offset       = vmx_set_tsc_offset,
     .inject_exception     = vmx_inject_exception,
     .init_hypercall_page  = vmx_init_hypercall_page,
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -101,16 +101,17 @@ struct hvm_function_table {
     /* Examine specifics of the guest state. */
     unsigned int (*get_interrupt_shadow)(struct vcpu *v);
     void (*set_interrupt_shadow)(struct vcpu *v, unsigned int intr_shadow);
     int (*guest_x86_mode)(struct vcpu *v);
     void (*get_segment_register)(struct vcpu *v, enum x86_segment seg,
                                  struct segment_register *reg);
     void (*set_segment_register)(struct vcpu *v, enum x86_segment seg,
                                  struct segment_register *reg);
+    unsigned long (*get_shadow_gs_base)(struct vcpu *v);

     /*
      * Re-set the value of CR3 that Xen runs on when handling VM exits.
      */
     void (*update_host_cr3)(struct vcpu *v);

     /*
      * Called to inform HVM layer that a guest CRn or EFER has changed.
@@ -300,16 +301,21 @@ hvm_get_segment_register(struct vcpu *v,

 static inline void
 hvm_set_segment_register(struct vcpu *v, enum x86_segment seg,
                          struct segment_register *reg)
 {
     hvm_funcs.set_segment_register(v, seg, reg);
 }

+static inline unsigned long hvm_get_shadow_gs_base(struct vcpu *v)
+{
+    return hvm_funcs.get_shadow_gs_base(v);
+}
+
 #define is_viridian_domain(_d)                                             \
  (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VIRIDIAN]))

 void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
                                    unsigned int *ecx, unsigned int *edx);
 void hvm_migrate_timers(struct vcpu *v);
 void hvm_do_resume(struct vcpu *v);
 void hvm_migrate_pirqs(struct vcpu *v);



>  -- Keir
>
>> PS: Come submission time, I will send it out as two separate patches.
>>
>> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
>> --- a/xen/arch/x86/domctl.c
>> +++ b/xen/arch/x86/domctl.c
>> @@ -1585,18 +1585,33 @@ void arch_get_info_guest(struct vcpu *v,
>>          hvm_get_segment_register(v, x86_seg_ss, &sreg);
>>          c.nat->user_regs.ss = sreg.sel;
>>          hvm_get_segment_register(v, x86_seg_ds, &sreg);
>>          c.nat->user_regs.ds = sreg.sel;
>>          hvm_get_segment_register(v, x86_seg_es, &sreg);
>>          c.nat->user_regs.es = sreg.sel;
>>          hvm_get_segment_register(v, x86_seg_fs, &sreg);
>>          c.nat->user_regs.fs = sreg.sel;
>> +#ifdef __x86_64__
>> +        c.nat->fs_base = sreg.base;
>> +#endif
>>          hvm_get_segment_register(v, x86_seg_gs, &sreg);
>>          c.nat->user_regs.gs = sreg.sel;
>> +#ifdef __x86_64__
>> +        if ( ring_0(&c.nat->user_regs) )
>> +        {
>> +            c.nat->gs_base_kernel = sreg.base;
>> +            c.nat->gs_base_user = hvm_get_shadow_gs_base(v);
>> +        }
>> +        else
>> +        {
>> +            c.nat->gs_base_user = sreg.base;
>> +            c.nat->gs_base_kernel = hvm_get_shadow_gs_base(v);
>> +        }
>> +#endif
>>      }
>>      else
>>      {
>>          c(ldt_base = v->arch.pv_vcpu.ldt_base);
>>          c(ldt_ents = v->arch.pv_vcpu.ldt_ents);
>>          for ( i = 0; i < ARRAY_SIZE(v->arch.pv_vcpu.gdt_frames); ++i )
>>              c(gdt_frames[i] = v->arch.pv_vcpu.gdt_frames[i]);
>>  #ifdef CONFIG_COMPAT
>> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
>> --- a/xen/arch/x86/hvm/svm/svm.c
>> +++ b/xen/arch/x86/hvm/svm/svm.c
>> @@ -640,16 +640,25 @@ static void svm_set_segment_register(str
>>      default:
>>          BUG();
>>      }
>>
>>      if ( sync )
>>          svm_vmload(vmcb);
>>  }
>>
>> +#ifdef __x86_64__
>> +static unsigned long svm_get_shadow_gs_base(struct vcpu *v)
>> +{
>> +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
>> +
>> +    return vmcb->kerngsbase;
>> +}
>> +#endif
>> +
>>  static int svm_set_guest_pat(struct vcpu *v, u64 gpat)
>>  {
>>      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
>>
>>      if ( !paging_mode_hap(v->domain) )
>>          return 0;
>>
>>      vmcb_set_g_pat(vmcb, gpat);
>> @@ -1978,16 +1987,17 @@ static struct hvm_function_table __read_
>>      .vcpu_destroy         = svm_vcpu_destroy,
>>      .save_cpu_ctxt        = svm_save_vmcb_ctxt,
>>      .load_cpu_ctxt        = svm_load_vmcb_ctxt,
>>      .get_interrupt_shadow = svm_get_interrupt_shadow,
>>      .set_interrupt_shadow = svm_set_interrupt_shadow,
>>      .guest_x86_mode       = svm_guest_x86_mode,
>>      .get_segment_register = svm_get_segment_register,
>>      .set_segment_register = svm_set_segment_register,
>> +    .get_shadow_gs_base   = svm_get_shadow_gs_base,
>>      .update_host_cr3      = svm_update_host_cr3,
>>      .update_guest_cr      = svm_update_guest_cr,
>>      .update_guest_efer    = svm_update_guest_efer,
>>      .set_guest_pat        = svm_set_guest_pat,
>>      .get_guest_pat        = svm_get_guest_pat,
>>      .set_tsc_offset       = svm_set_tsc_offset,
>>      .inject_exception     = svm_inject_exception,
>>      .init_hypercall_page  = svm_init_hypercall_page,
>> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
>> --- a/xen/arch/x86/hvm/vmx/vmx.c
>> +++ b/xen/arch/x86/hvm/vmx/vmx.c
>> @@ -937,16 +937,23 @@ static void vmx_set_segment_register(str
>>          break;
>>      default:
>>          BUG();
>>      }
>>
>>      vmx_vmcs_exit(v);
>>  }
>>
>> +#ifdef __x86_64__
>> +static unsigned long vmx_get_shadow_gs_base(struct vcpu *v)
>> +{
>> +    return v->arch.hvm_vmx.shadow_gs;
>> +}
>> +#endif
>> +
>>  static int vmx_set_guest_pat(struct vcpu *v, u64 gpat)
>>  {
>>      if ( !cpu_has_vmx_pat || !paging_mode_hap(v->domain) )
>>          return 0;
>>
>>      vmx_vmcs_enter(v);
>>      __vmwrite(GUEST_PAT, gpat);
>>  #ifdef __i386__
>> @@ -1517,16 +1524,17 @@ static struct hvm_function_table __read_
>>      .vcpu_destroy         = vmx_vcpu_destroy,
>>      .save_cpu_ctxt        = vmx_save_vmcs_ctxt,
>>      .load_cpu_ctxt        = vmx_load_vmcs_ctxt,
>>      .get_interrupt_shadow = vmx_get_interrupt_shadow,
>>      .set_interrupt_shadow = vmx_set_interrupt_shadow,
>>      .guest_x86_mode       = vmx_guest_x86_mode,
>>      .get_segment_register = vmx_get_segment_register,
>>      .set_segment_register = vmx_set_segment_register,
>> +    .get_shadow_gs_base   = vmx_get_shadow_gs_base,
>>      .update_host_cr3      = vmx_update_host_cr3,
>>      .update_guest_cr      = vmx_update_guest_cr,
>>      .update_guest_efer    = vmx_update_guest_efer,
>>      .set_guest_pat        = vmx_set_guest_pat,
>>      .get_guest_pat        = vmx_get_guest_pat,
>>      .set_tsc_offset       = vmx_set_tsc_offset,
>>      .inject_exception     = vmx_inject_exception,
>>      .init_hypercall_page  = vmx_init_hypercall_page,
>> diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
>> --- a/xen/include/asm-x86/hvm/hvm.h
>> +++ b/xen/include/asm-x86/hvm/hvm.h
>> @@ -101,16 +101,19 @@ struct hvm_function_table {
>>      /* Examine specifics of the guest state. */
>>      unsigned int (*get_interrupt_shadow)(struct vcpu *v);
>>      void (*set_interrupt_shadow)(struct vcpu *v, unsigned int intr_shadow);
>>      int (*guest_x86_mode)(struct vcpu *v);
>>      void (*get_segment_register)(struct vcpu *v, enum x86_segment seg,
>>                                   struct segment_register *reg);
>>      void (*set_segment_register)(struct vcpu *v, enum x86_segment seg,
>>                                   struct segment_register *reg);
>> +#ifdef __x86_64__
>> +    unsigned long (*get_shadow_gs_base)(struct vcpu *v);
>> +#endif
>>
>>      /*
>>       * Re-set the value of CR3 that Xen runs on when handling VM exits.
>>       */
>>      void (*update_host_cr3)(struct vcpu *v);
>>
>>      /*
>>       * Called to inform HVM layer that a guest CRn or EFER has changed.
>> @@ -300,16 +303,23 @@ hvm_get_segment_register(struct vcpu *v,
>>
>>  static inline void
>>  hvm_set_segment_register(struct vcpu *v, enum x86_segment seg,
>>                           struct segment_register *reg)
>>  {
>>      hvm_funcs.set_segment_register(v, seg, reg);
>>  }
>>
>> +#ifdef __x86_64__
>> +static inline unsigned long hvm_get_shadow_gs_base(struct vcpu *v)
>> +{
>> +    return hvm_funcs.get_shadow_gs_base(v);
>> +}
>> +#endif
>> +
>>  #define is_viridian_domain(_d)                                             \
>>   (is_hvm_domain(_d) && ((_d)->arch.hvm_domain.params[HVM_PARAM_VIRIDIAN]))
>>
>>  void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
>>                                     unsigned int *ecx, unsigned int *edx);
>>  void hvm_migrate_timers(struct vcpu *v);
>>  void hvm_do_resume(struct vcpu *v);
>>  void hvm_migrate_pirqs(struct vcpu *v);
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@xxxxxxxxxxxxx
>> http://lists.xen.org/xen-devel
>
>

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.