|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] x86/pagewalk: Clean up guest_supports_* predicates
commit c68a88583e588f6fb987f5dcb730817512277a6a
Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Thu Mar 2 14:55:38 2017 +0000
Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Mon Mar 27 11:49:25 2017 +0100
x86/pagewalk: Clean up guest_supports_* predicates
Switch them to returning bool, and taking const parameters.
Rename guest_supports_superpages() to guest_can_use_l2_superpages() to
indicate which level of pagetables it is actually referring to as well as
indicating that it is more complicated than just control register settings,
and rename guest_supports_1G_superpages() to guest_can_use_l3_superpages()
for
consistency.
guest_can_use_l3_superpages() is a static property of the domain, rather
than
control register settings, so is switched to take a domain pointer.
hvm_pse1gb_supported() is inlined into its sole user because it isn't
strictly
hvm-specific (it is hap-specific) and really should be beside a comment
explaining why the cpuid policy is ignored.
guest_supports_nx() on the other hand refers simply to a control register
bit,
and is renamed to guest_nx_enabled().
While cleaning up part of the file, clean up all trailing whilespace, and
fix
one comment which accidently refered to PG living in CR4 rather than CR0.
Requested-by: Jan Beulich <jbeulich@xxxxxxxx>
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
Acked-by: Tim Deegan <tim@xxxxxxx>
---
xen/arch/x86/mm/guest_walk.c | 6 ++--
xen/arch/x86/mm/shadow/multi.c | 12 +++----
xen/include/asm-x86/guest_pt.h | 74 ++++++++++++++++++++++++------------------
xen/include/asm-x86/hvm/hvm.h | 4 ---
4 files changed, 52 insertions(+), 44 deletions(-)
diff --git a/xen/arch/x86/mm/guest_walk.c b/xen/arch/x86/mm/guest_walk.c
index 8187226..c526363 100644
--- a/xen/arch/x86/mm/guest_walk.c
+++ b/xen/arch/x86/mm/guest_walk.c
@@ -59,7 +59,7 @@ const uint32_t gw_page_flags[] = {
static uint32_t mandatory_flags(struct vcpu *v, uint32_t pfec)
{
/* Don't demand not-NX if the CPU wouldn't enforce it. */
- if ( !guest_supports_nx(v) )
+ if ( !guest_nx_enabled(v) )
pfec &= ~PFEC_insn_fetch;
/* Don't demand R/W if the CPU wouldn't enforce it. */
@@ -272,7 +272,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
/* _PAGE_PSE_PAT not set: remove _PAGE_PAT from flags. */
flags &= ~_PAGE_PAT;
- if ( !guest_supports_1G_superpages(v) )
+ if ( !guest_can_use_l3_superpages(d) )
rc |= _PAGE_PSE | _PAGE_INVALID_BIT;
if ( gfn_x(start) & GUEST_L3_GFN_MASK & ~0x1 )
rc |= _PAGE_INVALID_BITS;
@@ -326,7 +326,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
}
rc |= ((gflags & mflags) ^ mflags);
- pse2M = (gflags & _PAGE_PSE) && guest_supports_superpages(v);
+ pse2M = (gflags & _PAGE_PSE) && guest_can_use_l2_superpages(v);
if ( pse2M )
{
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 63c7ab5..95e2f85 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -238,7 +238,7 @@ shadow_check_gwalk(struct vcpu *v, unsigned long va, walk_t
*gw, int version)
l2p = (guest_l2e_t *)v->arch.paging.shadow.guest_vtable;
mismatch |= (gw->l2e.l2 != l2p[guest_l2_table_offset(va)].l2);
#endif
- if ( !(guest_supports_superpages(v) &&
+ if ( !(guest_can_use_l2_superpages(v) &&
(guest_l2e_get_flags(gw->l2e) & _PAGE_PSE)) )
{
l1p = map_domain_page(gw->l1mfn);
@@ -310,7 +310,7 @@ gw_remove_write_accesses(struct vcpu *v, unsigned long va,
walk_t *gw)
rc |= GW_RMWR_FLUSHTLB;
#endif /* GUEST_PAGING_LEVELS >= 3 */
- if ( !(guest_supports_superpages(v) &&
+ if ( !(guest_can_use_l2_superpages(v) &&
(guest_l2e_get_flags(gw->l2e) & _PAGE_PSE))
#if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
&& !mfn_is_out_of_sync(gw->l1mfn)
@@ -591,7 +591,7 @@ _sh_propagate(struct vcpu *v,
//
pass_thru_flags = (_PAGE_ACCESSED | _PAGE_USER |
_PAGE_RW | _PAGE_PRESENT);
- if ( guest_supports_nx(v) )
+ if ( guest_nx_enabled(v) )
pass_thru_flags |= _PAGE_NX_BIT;
if ( level == 1 && !shadow_mode_refcounts(d) && mmio_mfn )
pass_thru_flags |= _PAGE_PAT | _PAGE_PCD | _PAGE_PWT;
@@ -660,7 +660,7 @@ _sh_propagate(struct vcpu *v,
if ( unlikely(((level == 1) ||
((level == 2) &&
(gflags & _PAGE_PSE) &&
- guest_supports_superpages(v)))
+ guest_can_use_l2_superpages(v)))
&& !(gflags & _PAGE_DIRTY)) )
sflags &= ~_PAGE_RW;
@@ -1846,7 +1846,7 @@ static shadow_l1e_t * shadow_get_and_create_l1e(struct
vcpu *v,
/* No l1 shadow installed: find and install it. */
if ( !(flags & _PAGE_PRESENT) )
return NULL; /* No guest page. */
- if ( guest_supports_superpages(v) && (flags & _PAGE_PSE) )
+ if ( guest_can_use_l2_superpages(v) && (flags & _PAGE_PSE) )
{
/* Splintering a superpage */
gfn_t l2gfn = guest_l2e_get_gfn(gw->l2e);
@@ -2251,7 +2251,7 @@ static int validate_gl2e(struct vcpu *v, void *new_ge,
mfn_t sl2mfn, void *se)
if ( guest_l2e_get_flags(new_gl2e) & _PAGE_PRESENT )
{
gfn_t gl1gfn = guest_l2e_get_gfn(new_gl2e);
- if ( guest_supports_superpages(v) &&
+ if ( guest_can_use_l2_superpages(v) &&
(guest_l2e_get_flags(new_gl2e) & _PAGE_PSE) )
{
// superpage -- need to look up the shadow L1 which holds the
diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-x86/guest_pt.h
index bedc771..e23e968 100644
--- a/xen/include/asm-x86/guest_pt.h
+++ b/xen/include/asm-x86/guest_pt.h
@@ -2,7 +2,7 @@
* xen/asm-x86/guest_pt.h
*
* Types and accessors for guest pagetable entries, as distinct from
- * Xen's pagetable types.
+ * Xen's pagetable types.
*
* Users must #define GUEST_PAGING_LEVELS to 2, 3 or 4 before including
* this file.
@@ -10,17 +10,17 @@
* Parts of this code are Copyright (c) 2006 by XenSource Inc.
* Parts of this code are Copyright (c) 2006 by Michael A Fetterman
* Parts based on earlier work by Michael A Fetterman, Ian Pratt et al.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
@@ -168,33 +168,43 @@ static inline guest_l4e_t guest_l4e_from_gfn(gfn_t gfn,
u32 flags)
/* Which pagetable features are supported on this vcpu? */
-static inline int
-guest_supports_superpages(struct vcpu *v)
+static inline bool guest_can_use_l2_superpages(const struct vcpu *v)
{
- /* The _PAGE_PSE bit must be honoured in HVM guests, whenever
- * CR4.PSE is set or the guest is in PAE or long mode.
- * It's also used in the dummy PT for vcpus with CR4.PG cleared. */
+ /*
+ * The L2 _PAGE_PSE bit must be honoured in HVM guests, whenever
+ * CR4.PSE is set or the guest is in PAE or long mode.
+ * It's also used in the dummy PT for vcpus with CR0.PG cleared.
+ */
return (is_pv_vcpu(v)
? opt_allow_superpage
- : (GUEST_PAGING_LEVELS != 2
+ : (GUEST_PAGING_LEVELS != 2
|| !hvm_paging_enabled(v)
|| (v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PSE)));
}
-static inline int
-guest_supports_1G_superpages(struct vcpu *v)
+static inline bool guest_can_use_l3_superpages(const struct domain *d)
{
- return (GUEST_PAGING_LEVELS >= 4 && hvm_pse1gb_supported(v->domain));
+ /*
+ * There are no control register settings for the hardware pagewalk on the
+ * subject of 1G superpages.
+ *
+ * Shadow pagetables don't support 1GB superpages at all, and will always
+ * treat L3 _PAGE_PSE as reserved.
+ *
+ * With HAP however, if the guest constructs a 1GB superpage on capable
+ * hardware, it will function irrespective of whether the feature is
+ * advertised. Xen's model of performing a pagewalk should match.
+ */
+ return GUEST_PAGING_LEVELS >= 4 && paging_mode_hap(d) && cpu_has_page1gb;
}
-static inline int
-guest_supports_nx(struct vcpu *v)
+static inline bool guest_nx_enabled(const struct vcpu *v)
{
- if ( GUEST_PAGING_LEVELS == 2 || !cpu_has_nx )
- return 0;
- if ( is_pv_vcpu(v) )
- return cpu_has_nx;
- return hvm_nx_enabled(v);
+ if ( GUEST_PAGING_LEVELS == 2 ) /* NX has no effect witout CR4.PAE. */
+ return false;
+
+ /* PV guests can't control EFER.NX, and inherits Xen's choice. */
+ return is_pv_vcpu(v) ? cpu_has_nx : hvm_nx_enabled(v);
}
@@ -258,11 +268,11 @@ static inline paddr_t guest_walk_to_gpa(const walk_t *gw)
return (gfn_x(gfn) << PAGE_SHIFT) | (gw->va & ~PAGE_MASK);
}
-/* Given a walk_t from a successful walk, return the page-order of the
+/* Given a walk_t from a successful walk, return the page-order of the
* page or superpage that the virtual address is in. */
static inline unsigned int guest_walk_to_page_order(const walk_t *gw)
{
- /* This is only valid for successful walks - otherwise the
+ /* This is only valid for successful walks - otherwise the
* PSE bits might be invalid. */
ASSERT(guest_l1e_get_flags(gw->l1e) & _PAGE_PRESENT);
#if GUEST_PAGING_LEVELS >= 3
@@ -275,28 +285,30 @@ static inline unsigned int guest_walk_to_page_order(const
walk_t *gw)
}
-/* Walk the guest pagetables, after the manner of a hardware walker.
+/*
+ * Walk the guest pagetables, after the manner of a hardware walker.
*
- * Inputs: a vcpu, a virtual address, a walk_t to fill, a
- * pointer to a pagefault code, the MFN of the guest's
- * top-level pagetable, and a mapping of the
+ * Inputs: a vcpu, a virtual address, a walk_t to fill, a
+ * pointer to a pagefault code, the MFN of the guest's
+ * top-level pagetable, and a mapping of the
* guest's top-level pagetable.
- *
+ *
* We walk the vcpu's guest pagetables, filling the walk_t with what we
* see and adding any Accessed and Dirty bits that are needed in the
* guest entries. Using the pagefault code, we check the permissions as
* we go. For the purposes of reading pagetables we treat all non-RAM
* memory as contining zeroes.
- *
- * Returns 0 for success, or the set of permission bits that we failed on
- * if the walk did not complete. */
+ *
+ * Returns 0 for success, or the set of permission bits that we failed on
+ * if the walk did not complete.
+ */
/* Macro-fu so you can call guest_walk_tables() and get the right one. */
#define GPT_RENAME2(_n, _l) _n ## _ ## _l ## _levels
#define GPT_RENAME(_n, _l) GPT_RENAME2(_n, _l)
#define guest_walk_tables GPT_RENAME(guest_walk_tables, GUEST_PAGING_LEVELS)
-extern uint32_t
+extern uint32_t
guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, unsigned long va,
walk_t *gw, uint32_t pfec, mfn_t top_mfn, void *top_map);
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index f9bb190..c854183 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -302,10 +302,6 @@ int hvm_girq_dest_2_vcpu_id(struct domain *d, uint8_t
dest, uint8_t dest_mode);
#define hap_has_1gb (!!(hvm_funcs.hap_capabilities & HVM_HAP_SUPERPAGE_1GB))
#define hap_has_2mb (!!(hvm_funcs.hap_capabilities & HVM_HAP_SUPERPAGE_2MB))
-/* Can the guest use 1GB superpages in its own pagetables? */
-#define hvm_pse1gb_supported(d) \
- (cpu_has_page1gb && paging_mode_hap(d))
-
#define hvm_long_mode_enabled(v) \
((v)->arch.hvm_vcpu.guest_efer & EFER_LMA)
--
generated by git-patchbot for /home/xen/git/xen.git#master
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |