diff mbox

[2/3] x86/mm: make {cmpxchg, write}_guest_entry() hook shadow mode specific

Message ID 56B4650B02000078000CEDBB@prv-mh.provo.novell.com
State New, archived
Headers show

Commit Message

Jan Beulich Feb. 5, 2016, 8:02 a.m. UTC
... as they're being used for PV guests only, which don't use HAP mode.
This eliminates another pair of NULL callbacks in HAP as well as in 2-
and 3-guest-level shadow modes.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
x86/mm: make {cmpxchg,write}_guest_entry() hook shadow mode specific

... as they're being used for PV guests only, which don't use HAP mode.
This eliminates another pair of NULL callbacks in HAP as well as in 2-
and 3-guest-level shadow modes.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -369,15 +369,14 @@ static void sh_audit_gw(struct vcpu *v,
 #endif /* audit code */
 
 
-#if (CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS)
 /*
  * Write a new value into the guest pagetable, and update the shadows
  * appropriately.  Returns 0 if we page-faulted, 1 for success.
  */
-static int
-sh_write_guest_entry(struct vcpu *v, guest_intpte_t *p,
-                     guest_intpte_t new, mfn_t gmfn)
+static bool_t
+sh_write_guest_entry(struct vcpu *v, intpte_t *p, intpte_t new, mfn_t gmfn)
 {
+#if CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS
     int failed;
 
     paging_lock(v->domain);
@@ -387,6 +386,9 @@ sh_write_guest_entry(struct vcpu *v, gue
     paging_unlock(v->domain);
 
     return !failed;
+#else
+    return 0;
+#endif
 }
 
 /*
@@ -395,10 +397,11 @@ sh_write_guest_entry(struct vcpu *v, gue
  * N.B. caller should check the value of "old" to see if the cmpxchg itself
  * was successful.
  */
-static int
-sh_cmpxchg_guest_entry(struct vcpu *v, guest_intpte_t *p,
-                       guest_intpte_t *old, guest_intpte_t new, mfn_t gmfn)
+static bool_t
+sh_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, intpte_t *old,
+                       intpte_t new, mfn_t gmfn)
 {
+#if CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS
     int failed;
     guest_intpte_t t = *old;
 
@@ -410,8 +413,10 @@ sh_cmpxchg_guest_entry(struct vcpu *v, g
     paging_unlock(v->domain);
 
     return !failed;
+#else
+    return 0;
+#endif
 }
-#endif /* CONFIG == GUEST (== SHADOW) */
 
 /**************************************************************************/
 /* Functions to compute the correct index into a shadow page, given an
@@ -5194,14 +5199,12 @@ const struct paging_mode sh_paging_mode
     .update_cr3                    = sh_update_cr3,
     .update_paging_modes           = shadow_update_paging_modes,
     .write_p2m_entry               = shadow_write_p2m_entry,
-#if CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS
-    .write_guest_entry             = sh_write_guest_entry,
-    .cmpxchg_guest_entry           = sh_cmpxchg_guest_entry,
-#endif
     .guest_levels                  = GUEST_PAGING_LEVELS,
     .shadow.detach_old_tables      = sh_detach_old_tables,
     .shadow.x86_emulate_write      = sh_x86_emulate_write,
     .shadow.x86_emulate_cmpxchg    = sh_x86_emulate_cmpxchg,
+    .shadow.write_guest_entry      = sh_write_guest_entry,
+    .shadow.cmpxchg_guest_entry    = sh_cmpxchg_guest_entry,
     .shadow.make_monitor_table     = sh_make_monitor_table,
     .shadow.destroy_monitor_table  = sh_destroy_monitor_table,
 #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC
--- a/xen/include/asm-x86/paging.h
+++ b/xen/include/asm-x86/paging.h
@@ -87,6 +87,11 @@ struct shadow_paging_mode {
                                             unsigned long new,
                                             unsigned int bytes,
                                             struct sh_emulate_ctxt *sh_ctxt);
+    bool_t        (*write_guest_entry     )(struct vcpu *v, intpte_t *p,
+                                            intpte_t new, mfn_t gmfn);
+    bool_t        (*cmpxchg_guest_entry   )(struct vcpu *v, intpte_t *p,
+                                            intpte_t *old, intpte_t new,
+                                            mfn_t gmfn);
     mfn_t         (*make_monitor_table    )(struct vcpu *v);
     void          (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn);
     int           (*guess_wrmap           )(struct vcpu *v, 
@@ -119,11 +124,6 @@ struct paging_mode {
     void          (*write_p2m_entry       )(struct domain *d, unsigned long gfn,
                                             l1_pgentry_t *p, l1_pgentry_t new,
                                             unsigned int level);
-    int           (*write_guest_entry     )(struct vcpu *v, intpte_t *p,
-                                            intpte_t new, mfn_t gmfn);
-    int           (*cmpxchg_guest_entry   )(struct vcpu *v, intpte_t *p,
-                                            intpte_t *old, intpte_t new,
-                                            mfn_t gmfn);
 
     unsigned int guest_levels;
 
@@ -299,14 +299,15 @@ static inline void paging_update_paging_
 /* Write a new value into the guest pagetable, and update the
  * paging-assistance state appropriately.  Returns 0 if we page-faulted,
  * 1 for success. */
-static inline int paging_write_guest_entry(struct vcpu *v, intpte_t *p,
-                                           intpte_t new, mfn_t gmfn)
+static inline bool_t paging_write_guest_entry(struct vcpu *v, intpte_t *p,
+                                              intpte_t new, mfn_t gmfn)
 {
-    if ( unlikely(paging_mode_enabled(v->domain) 
-                  && v->arch.paging.mode != NULL) )
-        return paging_get_hostmode(v)->write_guest_entry(v, p, new, gmfn);
-    else 
-        return (!__copy_to_user(p, &new, sizeof(new)));
+#ifdef CONFIG_SHADOW_PAGING
+    if ( unlikely(paging_mode_shadow(v->domain)) && paging_get_hostmode(v) )
+        return paging_get_hostmode(v)->shadow.write_guest_entry(v, p, new,
+                                                                gmfn);
+#endif
+    return !__copy_to_user(p, &new, sizeof(new));
 }
 
 
@@ -314,15 +315,16 @@ static inline int paging_write_guest_ent
  * paging-assistance state appropriately.  Returns 0 if we page-faulted,
  * 1 if not.  N.B. caller should check the value of "old" to see if the
  * cmpxchg itself was successful. */
-static inline int paging_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p,
-                                             intpte_t *old, intpte_t new, 
-                                             mfn_t gmfn)
-{
-    if ( unlikely(paging_mode_enabled(v->domain) 
-                  && v->arch.paging.mode != NULL) )
-        return paging_get_hostmode(v)->cmpxchg_guest_entry(v, p, old, new, gmfn);
-    else 
-        return (!cmpxchg_user(p, *old, new));
+static inline bool_t paging_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p,
+                                                intpte_t *old, intpte_t new,
+                                                mfn_t gmfn)
+{
+#ifdef CONFIG_SHADOW_PAGING
+    if ( unlikely(paging_mode_shadow(v->domain)) && paging_get_hostmode(v) )
+        return paging_get_hostmode(v)->shadow.cmpxchg_guest_entry(v, p, old,
+                                                                  new, gmfn);
+#endif
+    return !cmpxchg_user(p, *old, new);
 }
 
 /* Helper function that writes a pte in such a way that a concurrent read

Comments

Andrew Cooper Feb. 5, 2016, 2:59 p.m. UTC | #1
On 05/02/16 08:02, Jan Beulich wrote:
> ... as they're being used for PV guests only, which don't use HAP mode.
> This eliminates another pair of NULL callbacks in HAP as well as in 2-
> and 3-guest-level shadow modes.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>, but with two
suggestions.

> @@ -299,14 +299,15 @@ static inline void paging_update_paging_
>  /* Write a new value into the guest pagetable, and update the
>   * paging-assistance state appropriately.  Returns 0 if we page-faulted,
>   * 1 for success. */
> -static inline int paging_write_guest_entry(struct vcpu *v, intpte_t *p,
> -                                           intpte_t new, mfn_t gmfn)
> +static inline bool_t paging_write_guest_entry(struct vcpu *v, intpte_t *p,
> +                                              intpte_t new, mfn_t gmfn)
>  {
> -    if ( unlikely(paging_mode_enabled(v->domain) 
> -                  && v->arch.paging.mode != NULL) )
> -        return paging_get_hostmode(v)->write_guest_entry(v, p, new, gmfn);
> -    else 
> -        return (!__copy_to_user(p, &new, sizeof(new)));
> +#ifdef CONFIG_SHADOW_PAGING
> +    if ( unlikely(paging_mode_shadow(v->domain)) && paging_get_hostmode(v) )
> +        return paging_get_hostmode(v)->shadow.write_guest_entry(v, p, new,
> +                                                                gmfn);

I would be tempted to split the line at the -> in this case, to avoid
squashing all the parameters together on the RHS like that, but I
suppose it doesn't matter too much.

> +#endif
> +    return !__copy_to_user(p, &new, sizeof(new));

I realise that the old function behaved the same, but this really should
ASSERT(v == current) before trampling the wrong virtual address space.

~Andrew
diff mbox

Patch

--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -369,15 +369,14 @@  static void sh_audit_gw(struct vcpu *v,
 #endif /* audit code */
 
 
-#if (CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS)
 /*
  * Write a new value into the guest pagetable, and update the shadows
  * appropriately.  Returns 0 if we page-faulted, 1 for success.
  */
-static int
-sh_write_guest_entry(struct vcpu *v, guest_intpte_t *p,
-                     guest_intpte_t new, mfn_t gmfn)
+static bool_t
+sh_write_guest_entry(struct vcpu *v, intpte_t *p, intpte_t new, mfn_t gmfn)
 {
+#if CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS
     int failed;
 
     paging_lock(v->domain);
@@ -387,6 +386,9 @@  sh_write_guest_entry(struct vcpu *v, gue
     paging_unlock(v->domain);
 
     return !failed;
+#else
+    return 0;
+#endif
 }
 
 /*
@@ -395,10 +397,11 @@  sh_write_guest_entry(struct vcpu *v, gue
  * N.B. caller should check the value of "old" to see if the cmpxchg itself
  * was successful.
  */
-static int
-sh_cmpxchg_guest_entry(struct vcpu *v, guest_intpte_t *p,
-                       guest_intpte_t *old, guest_intpte_t new, mfn_t gmfn)
+static bool_t
+sh_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, intpte_t *old,
+                       intpte_t new, mfn_t gmfn)
 {
+#if CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS
     int failed;
     guest_intpte_t t = *old;
 
@@ -410,8 +413,10 @@  sh_cmpxchg_guest_entry(struct vcpu *v, g
     paging_unlock(v->domain);
 
     return !failed;
+#else
+    return 0;
+#endif
 }
-#endif /* CONFIG == GUEST (== SHADOW) */
 
 /**************************************************************************/
 /* Functions to compute the correct index into a shadow page, given an
@@ -5194,14 +5199,12 @@  const struct paging_mode sh_paging_mode
     .update_cr3                    = sh_update_cr3,
     .update_paging_modes           = shadow_update_paging_modes,
     .write_p2m_entry               = shadow_write_p2m_entry,
-#if CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS
-    .write_guest_entry             = sh_write_guest_entry,
-    .cmpxchg_guest_entry           = sh_cmpxchg_guest_entry,
-#endif
     .guest_levels                  = GUEST_PAGING_LEVELS,
     .shadow.detach_old_tables      = sh_detach_old_tables,
     .shadow.x86_emulate_write      = sh_x86_emulate_write,
     .shadow.x86_emulate_cmpxchg    = sh_x86_emulate_cmpxchg,
+    .shadow.write_guest_entry      = sh_write_guest_entry,
+    .shadow.cmpxchg_guest_entry    = sh_cmpxchg_guest_entry,
     .shadow.make_monitor_table     = sh_make_monitor_table,
     .shadow.destroy_monitor_table  = sh_destroy_monitor_table,
 #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC
--- a/xen/include/asm-x86/paging.h
+++ b/xen/include/asm-x86/paging.h
@@ -87,6 +87,11 @@  struct shadow_paging_mode {
                                             unsigned long new,
                                             unsigned int bytes,
                                             struct sh_emulate_ctxt *sh_ctxt);
+    bool_t        (*write_guest_entry     )(struct vcpu *v, intpte_t *p,
+                                            intpte_t new, mfn_t gmfn);
+    bool_t        (*cmpxchg_guest_entry   )(struct vcpu *v, intpte_t *p,
+                                            intpte_t *old, intpte_t new,
+                                            mfn_t gmfn);
     mfn_t         (*make_monitor_table    )(struct vcpu *v);
     void          (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn);
     int           (*guess_wrmap           )(struct vcpu *v, 
@@ -119,11 +124,6 @@  struct paging_mode {
     void          (*write_p2m_entry       )(struct domain *d, unsigned long gfn,
                                             l1_pgentry_t *p, l1_pgentry_t new,
                                             unsigned int level);
-    int           (*write_guest_entry     )(struct vcpu *v, intpte_t *p,
-                                            intpte_t new, mfn_t gmfn);
-    int           (*cmpxchg_guest_entry   )(struct vcpu *v, intpte_t *p,
-                                            intpte_t *old, intpte_t new,
-                                            mfn_t gmfn);
 
     unsigned int guest_levels;
 
@@ -299,14 +299,15 @@  static inline void paging_update_paging_
 /* Write a new value into the guest pagetable, and update the
  * paging-assistance state appropriately.  Returns 0 if we page-faulted,
  * 1 for success. */
-static inline int paging_write_guest_entry(struct vcpu *v, intpte_t *p,
-                                           intpte_t new, mfn_t gmfn)
+static inline bool_t paging_write_guest_entry(struct vcpu *v, intpte_t *p,
+                                              intpte_t new, mfn_t gmfn)
 {
-    if ( unlikely(paging_mode_enabled(v->domain) 
-                  && v->arch.paging.mode != NULL) )
-        return paging_get_hostmode(v)->write_guest_entry(v, p, new, gmfn);
-    else 
-        return (!__copy_to_user(p, &new, sizeof(new)));
+#ifdef CONFIG_SHADOW_PAGING
+    if ( unlikely(paging_mode_shadow(v->domain)) && paging_get_hostmode(v) )
+        return paging_get_hostmode(v)->shadow.write_guest_entry(v, p, new,
+                                                                gmfn);
+#endif
+    return !__copy_to_user(p, &new, sizeof(new));
 }
 
 
@@ -314,15 +315,16 @@  static inline int paging_write_guest_ent
  * paging-assistance state appropriately.  Returns 0 if we page-faulted,
  * 1 if not.  N.B. caller should check the value of "old" to see if the
  * cmpxchg itself was successful. */
-static inline int paging_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p,
-                                             intpte_t *old, intpte_t new, 
-                                             mfn_t gmfn)
-{
-    if ( unlikely(paging_mode_enabled(v->domain) 
-                  && v->arch.paging.mode != NULL) )
-        return paging_get_hostmode(v)->cmpxchg_guest_entry(v, p, old, new, gmfn);
-    else 
-        return (!cmpxchg_user(p, *old, new));
+static inline bool_t paging_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p,
+                                                intpte_t *old, intpte_t new,
+                                                mfn_t gmfn)
+{
+#ifdef CONFIG_SHADOW_PAGING
+    if ( unlikely(paging_mode_shadow(v->domain)) && paging_get_hostmode(v) )
+        return paging_get_hostmode(v)->shadow.cmpxchg_guest_entry(v, p, old,
+                                                                  new, gmfn);
+#endif
+    return !cmpxchg_user(p, *old, new);
 }
 
 /* Helper function that writes a pte in such a way that a concurrent read