All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 1/2] ASID: Flush by ASID
@ 2011-01-11 17:55 Wei Wang2
  2011-01-11 18:06 ` Keir Fraser
  0 siblings, 1 reply; 2+ messages in thread
From: Wei Wang2 @ 2011-01-11 17:55 UTC (permalink / raw)
  To: xen-devel@lists.xensource.com

[-- Attachment #1: Type: text/plain, Size: 368 bytes --]

This patch implements the framework for both SVM and VMX.
Thanks,
Wei

Signed-off-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Wei Wang <wei.wang2@amd.com>
--
Advanced Micro Devices GmbH
Sitz: Dornach, Gemeinde Aschheim, 
Landkreis München Registergericht München, 
HRB Nr. 43632
WEEE-Reg-Nr: DE 12919551
Geschäftsführer:
Alberto Bozzo, Andrew Bowd

[-- Attachment #2: flush_by_asid_1.patch --]
[-- Type: text/x-diff, Size: 9431 bytes --]

diff -r 7926538a6332 xen/arch/x86/hvm/asid.c
--- a/xen/arch/x86/hvm/asid.c	Tue Jan 11 11:41:39 2011 +0000
+++ b/xen/arch/x86/hvm/asid.c	Tue Jan 11 14:18:19 2011 +0100
@@ -52,11 +52,19 @@ struct hvm_asid_data {
    u32 next_asid;
    u32 max_asid;
    bool_t disabled;
+   bool_t flush_by_asid;
 };
+
+/* ASID generation 0 and 1 are reserved for special purposes */
+#define FLUSH_TLB_BY_OWN_ASID 0
+#define FLUSH_TLB_BY_NEW_ASID 1
+#define FIRST_VALID_ASID_GEN  2
 
 static DEFINE_PER_CPU(struct hvm_asid_data, hvm_asid_data);
 
-void hvm_asid_init(int nasids)
+/* Caller needs to provide two parameters: # of ASIDs and whether the CPU
+ * supports flush by ASID. */
+void hvm_asid_init(int nasids, bool_t flush_by_asid)
 {
     static s8 g_disabled = -1;
     struct hvm_asid_data *data = &this_cpu(hvm_asid_data);
@@ -66,21 +74,37 @@ void hvm_asid_init(int nasids)
 
     if ( g_disabled != data->disabled )
     {
-        printk("HVM: ASIDs %sabled.\n", data->disabled ? "dis" : "en");
+        printk("HVM: ASIDs %sabled", data->disabled ? "dis" : "en");
+        if ( data->disabled )
+            printk("\n");
+        else
+            printk(" (# of ASIDs = 0x%x, flush by ASID = %s)\n", nasids,
+                   flush_by_asid ? "true" : "false");
+
         if ( g_disabled < 0 )
             g_disabled = data->disabled;
     }
 
-    /* Zero indicates 'invalid generation', so we start the count at one. */
-    data->core_asid_generation = 1;
+    data->flush_by_asid = flush_by_asid;
+
+    /* 0 and 1 are reserved. They indicates 'invalid generation' for special
+     * purposes. So we start the count at 2. */
+    data->core_asid_generation = FIRST_VALID_ASID_GEN;
 
     /* Zero indicates 'ASIDs disabled', so we start the count at one. */
     data->next_asid = 1;
 }
 
-void hvm_asid_flush_vcpu(struct vcpu *v)
+/* There are two ways to flush VCPU with ASID: (1) assign a new ASID or (2)
+ * flush by ASID if CPU supports this feature. The second parameter of this
+ * function specifies whether caller wants a new ASID. For instance if guest
+ * changes its CR3 or paging mode, this parameter is FALSE. For VCPU migration,
+ * this is TRUE.
+ */
+void hvm_asid_flush_vcpu(struct vcpu *v, bool_t need_new_asid)
 {
-    v->arch.hvm_vcpu.asid_generation = 0;
+    v->arch.hvm_vcpu.asid_generation = need_new_asid ? FLUSH_TLB_BY_NEW_ASID :
+                                                       FLUSH_TLB_BY_OWN_ASID;
 }
 
 void hvm_asid_flush_core(void)
@@ -102,7 +126,7 @@ void hvm_asid_flush_core(void)
     data->disabled = 1;
 }
 
-bool_t hvm_asid_handle_vmenter(void)
+asid_action_t hvm_asid_handle_vmenter(void)
 {
     struct vcpu *curr = current;
     struct hvm_asid_data *data = &this_cpu(hvm_asid_data);
@@ -114,7 +138,16 @@ bool_t hvm_asid_handle_vmenter(void)
 
     /* Test if VCPU has valid ASID. */
     if ( curr->arch.hvm_vcpu.asid_generation == data->core_asid_generation )
-        return 0;
+        return asid_flush_none;
+
+    /* If VCPU doesn't need a new ASID and CPU supports flush by ASID, we
+     * skip ASID incremental and return directly from here */
+    if ( curr->arch.hvm_vcpu.asid_generation == FLUSH_TLB_BY_OWN_ASID &&
+          data->flush_by_asid )
+    {
+        curr->arch.hvm_vcpu.asid_generation = data->core_asid_generation;
+        return asid_flush_itself;
+    }
 
     /* If there are no free ASIDs, need to go to a new generation */
     if ( unlikely(data->next_asid > data->max_asid) )
@@ -131,13 +164,14 @@ bool_t hvm_asid_handle_vmenter(void)
 
     /*
      * When we assign ASID 1, flush all TLB entries as we are starting a new
-     * generation, and all old ASID allocations are now stale. 
+     * generation, and all old ASID allocations are now stale. Otherwise,
+     * Nothing needs to be flushed.
      */
-    return (curr->arch.hvm_vcpu.asid == 1);
+    return (curr->arch.hvm_vcpu.asid == 1) ? asid_flush_all : asid_flush_none;
 
  disabled:
     curr->arch.hvm_vcpu.asid = 0;
-    return 0;
+    return asid_flush_none;
 }
 
 /*
diff -r 7926538a6332 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c	Tue Jan 11 11:41:39 2011 +0000
+++ b/xen/arch/x86/hvm/hvm.c	Tue Jan 11 14:18:19 2011 +0100
@@ -935,7 +935,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
 {
     int rc;
 
-    hvm_asid_flush_vcpu(v);
+    hvm_asid_flush_vcpu(v, 1);
 
     if ( (rc = vlapic_init(v)) != 0 )
         goto fail1;
diff -r 7926538a6332 xen/arch/x86/hvm/svm/asid.c
--- a/xen/arch/x86/hvm/svm/asid.c	Tue Jan 11 11:41:39 2011 +0000
+++ b/xen/arch/x86/hvm/svm/asid.c	Tue Jan 11 14:18:19 2011 +0100
@@ -31,7 +31,7 @@ void svm_asid_init(struct cpuinfo_x86 *c
     if ( !cpu_has_amd_erratum(c, AMD_ERRATUM_170) )
         nasids = cpuid_ebx(0x8000000A);
 
-    hvm_asid_init(nasids);
+    hvm_asid_init(nasids, 0);
 }
 
 /*
@@ -42,7 +42,7 @@ asmlinkage void svm_asid_handle_vmrun(vo
 {
     struct vcpu *curr = current;
     struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
-    bool_t need_flush = hvm_asid_handle_vmenter();
+    bool_t need_flush = !!hvm_asid_handle_vmenter();
 
     /* ASID 0 indicates that ASIDs are disabled. */
     if ( curr->arch.hvm_vcpu.asid == 0 )
diff -r 7926538a6332 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c	Tue Jan 11 11:41:39 2011 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c	Tue Jan 11 14:18:19 2011 +0100
@@ -409,7 +409,7 @@ static void svm_update_guest_cr(struct v
         break;
     case 3:
         vmcb_set_cr3(vmcb, v->arch.hvm_vcpu.hw_cr[3]);
-        hvm_asid_flush_vcpu(v);
+        hvm_asid_flush_vcpu(v, 0);
         break;
     case 4:
         value = HVM_CR4_HOST_MASK;
@@ -707,7 +707,7 @@ static void svm_do_resume(struct vcpu *v
         hvm_migrate_timers(v);
 
         /* Migrating to another ASID domain.  Request a new ASID. */
-        hvm_asid_flush_vcpu(v);
+        hvm_asid_flush_vcpu(v, 1);
     }
 
     /* Reflect the vlapic's TPR in the hardware vtpr */
diff -r 7926538a6332 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c	Tue Jan 11 11:41:39 2011 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c	Tue Jan 11 14:18:19 2011 +0100
@@ -522,7 +522,7 @@ int vmx_cpu_up(void)
         BUG();
     }
 
-    hvm_asid_init(cpu_has_vmx_vpid ? (1u << VMCS_VPID_WIDTH) : 0);
+    hvm_asid_init(cpu_has_vmx_vpid ? (1u << VMCS_VPID_WIDTH) : 0, 0);
 
     if ( cpu_has_vmx_ept )
         ept_sync_all();
@@ -1079,7 +1079,7 @@ void vmx_do_resume(struct vcpu *v)
         hvm_migrate_timers(v);
         hvm_migrate_pirqs(v);
         vmx_set_host_env(v);
-        hvm_asid_flush_vcpu(v);
+        hvm_asid_flush_vcpu(v, 1);
     }
 
     debug_state = v->domain->debugger_attached 
diff -r 7926538a6332 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c	Tue Jan 11 11:41:39 2011 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c	Tue Jan 11 14:18:19 2011 +0100
@@ -1150,7 +1150,7 @@ static void vmx_update_guest_cr(struct v
         }
  
         __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr[3]);
-        hvm_asid_flush_vcpu(v);
+        hvm_asid_flush_vcpu(v, 0);
         break;
     case 4:
         v->arch.hvm_vcpu.hw_cr[4] = HVM_CR4_HOST_MASK;
@@ -1335,7 +1335,7 @@ static void vmx_set_uc_mode(struct vcpu 
     if ( paging_mode_hap(v->domain) )
         ept_change_entry_emt_with_range(
             v->domain, 0, p2m_get_hostp2m(v->domain)->max_mapped_pfn);
-    hvm_asid_flush_vcpu(v);
+    hvm_asid_flush_vcpu(v, 0);
 }
 
 static void vmx_set_info_guest(struct vcpu *v)
@@ -2665,7 +2665,7 @@ asmlinkage void vmx_vmenter_helper(void)
         goto out;
 
     old_asid = curr->arch.hvm_vcpu.asid;
-    need_flush = hvm_asid_handle_vmenter();
+    need_flush = !!hvm_asid_handle_vmenter(); /* convert to boolean */
     new_asid = curr->arch.hvm_vcpu.asid;
 
     if ( unlikely(new_asid != old_asid) )
diff -r 7926538a6332 xen/include/asm-x86/hvm/asid.h
--- a/xen/include/asm-x86/hvm/asid.h	Tue Jan 11 11:41:39 2011 +0000
+++ b/xen/include/asm-x86/hvm/asid.h	Tue Jan 11 14:18:19 2011 +0100
@@ -24,18 +24,25 @@
 
 struct vcpu;
 
+typedef enum {
+    asid_flush_none   = 0x0, /* don't need to flush any TLBs */
+    asid_flush_all    = 0x1, /* flush TLBs with all ASIDs */
+    asid_flush_itself = 0x3, /* only flush ASID's own TLBs. Note 3 is used
+                              * here (from AMD's flush by ASID feature). */
+} asid_action_t;
+
 /* Initialise ASID management for the current physical CPU. */
-void hvm_asid_init(int nasids);
+void hvm_asid_init(int nasids, bool_t flush_by_asid);
 
-/* Invalidate a VCPU's current ASID allocation: forces re-allocation. */
-void hvm_asid_flush_vcpu(struct vcpu *v);
+/* Invalidate a VCPU's current ASID */
+void hvm_asid_flush_vcpu(struct vcpu *v, bool_t need_new_asid);
 
 /* Flush all ASIDs on this processor core. */
 void hvm_asid_flush_core(void);
 
 /* Called before entry to guest context. Checks ASID allocation, returns a
  * boolean indicating whether all ASIDs must be flushed. */
-bool_t hvm_asid_handle_vmenter(void);
+asid_action_t hvm_asid_handle_vmenter(void);
 
 #endif /* __ASM_X86_HVM_ASID_H__ */
 
diff -r 7926538a6332 xen/include/asm-x86/hvm/svm/asid.h
--- a/xen/include/asm-x86/hvm/svm/asid.h	Tue Jan 11 11:41:39 2011 +0000
+++ b/xen/include/asm-x86/hvm/svm/asid.h	Tue Jan 11 14:18:19 2011 +0100
@@ -41,7 +41,7 @@ static inline void svm_asid_g_invlpg(str
 #endif
 
     /* Safe fallback. Take a new ASID. */
-    hvm_asid_flush_vcpu(v);
+    hvm_asid_flush_vcpu(v, 0);
 }
 
 #endif /* __ASM_X86_HVM_SVM_ASID_H__ */

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [RFC PATCH 1/2] ASID: Flush by ASID
  2011-01-11 17:55 [RFC PATCH 1/2] ASID: Flush by ASID Wei Wang2
@ 2011-01-11 18:06 ` Keir Fraser
  0 siblings, 0 replies; 2+ messages in thread
From: Keir Fraser @ 2011-01-11 18:06 UTC (permalink / raw)
  To: Wei Wang2, xen-devel@lists.xensource.com

On 11/01/2011 17:55, "Wei Wang2" <wei.wang2@amd.com> wrote:

> This patch implements the framework for both SVM and VMX.

I'll put this to one side for when 4.2 development window opens. It's too
late for 4.1 now.

 -- Keir

> Thanks,
> Wei
> 
> Signed-off-by: Wei Huang <wei.huang2@amd.com>
> Signed-off-by: Wei Wang <wei.wang2@amd.com>
> --
> Advanced Micro Devices GmbH
> Sitz: Dornach, Gemeinde Aschheim,
> Landkreis München Registergericht München,
> HRB Nr. 43632
> WEEE-Reg-Nr: DE 12919551
> Geschäftsführer:
> Alberto Bozzo, Andrew Bowd
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-01-11 18:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-11 17:55 [RFC PATCH 1/2] ASID: Flush by ASID Wei Wang2
2011-01-11 18:06 ` Keir Fraser

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.