aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Deegan <tim@xen.org>2011-09-08 15:13:06 +0100
committerTim Deegan <tim@xen.org>2011-09-08 15:13:06 +0100
commit84f8baf80791b3432808c59fdb46b65b98f8bce0 (patch)
treee4f4f615ef8438c0a746a87ebe073f18ea792283
parenta18dd4934f2d67616a0c5a20c8a571d05db57bfc (diff)
downloadxen-84f8baf80791b3432808c59fdb46b65b98f8bce0.tar.gz
xen-84f8baf80791b3432808c59fdb46b65b98f8bce0.tar.bz2
xen-84f8baf80791b3432808c59fdb46b65b98f8bce0.zip
x86/mm: adjust paging interface to return superpage sizes
to the caller of paging_ga_to_gfn_cr3() Signed-off-by: Christoph Egger <Christoph.Egger@amd.com> Signed-off-by: Tim Deegan <tim@xen.org> Committed-by: Tim Deegan <tim@xen.org>
-rw-r--r--xen/arch/x86/mm/hap/guest_walk.c7
-rw-r--r--xen/arch/x86/mm/hap/hap.c4
-rw-r--r--xen/arch/x86/mm/hap/nested_hap.c2
-rw-r--r--xen/arch/x86/mm/hap/private.h6
-rw-r--r--xen/arch/x86/mm/p2m.c2
-rw-r--r--xen/include/asm-x86/guest_pt.h18
-rw-r--r--xen/include/asm-x86/paging.h14
7 files changed, 40 insertions, 13 deletions
diff --git a/xen/arch/x86/mm/hap/guest_walk.c b/xen/arch/x86/mm/hap/guest_walk.c
index 24ff59c196..78ae032195 100644
--- a/xen/arch/x86/mm/hap/guest_walk.c
+++ b/xen/arch/x86/mm/hap/guest_walk.c
@@ -43,12 +43,12 @@ unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
struct vcpu *v, struct p2m_domain *p2m, unsigned long gva, uint32_t *pfec)
{
unsigned long cr3 = v->arch.hvm_vcpu.guest_cr[3];
- return hap_p2m_ga_to_gfn(GUEST_PAGING_LEVELS)(v, p2m, cr3, gva, pfec);
+ return hap_p2m_ga_to_gfn(GUEST_PAGING_LEVELS)(v, p2m, cr3, gva, pfec, NULL);
}
unsigned long hap_p2m_ga_to_gfn(GUEST_PAGING_LEVELS)(
struct vcpu *v, struct p2m_domain *p2m, unsigned long cr3,
- paddr_t ga, uint32_t *pfec)
+ paddr_t ga, uint32_t *pfec, unsigned int *page_order)
{
uint32_t missing;
mfn_t top_mfn;
@@ -107,6 +107,9 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAGING_LEVELS)(
return INVALID_GFN;
}
+ if ( page_order )
+ *page_order = guest_walk_to_page_order(&gw);
+
return gfn_x(gfn);
}
diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
index f90511ef04..9f6b990c2a 100644
--- a/xen/arch/x86/mm/hap/hap.c
+++ b/xen/arch/x86/mm/hap/hap.c
@@ -897,8 +897,10 @@ static unsigned long hap_gva_to_gfn_real_mode(
static unsigned long hap_p2m_ga_to_gfn_real_mode(
struct vcpu *v, struct p2m_domain *p2m, unsigned long cr3,
- paddr_t ga, uint32_t *pfec)
+ paddr_t ga, uint32_t *pfec, unsigned int *page_order)
{
+ if ( page_order )
+ *page_order = PAGE_ORDER_4K;
return (ga >> PAGE_SHIFT);
}
diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c
index 2bab9e71f2..d2c833f0f9 100644
--- a/xen/arch/x86/mm/hap/nested_hap.c
+++ b/xen/arch/x86/mm/hap/nested_hap.c
@@ -162,7 +162,7 @@ nestedhap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa)
nested_cr3 = nhvm_vcpu_hostcr3(v);
/* Walk the guest-supplied NPT table, just as if it were a pagetable */
- gfn = paging_ga_to_gfn_cr3(v, nested_cr3, L2_gpa, &pfec);
+ gfn = paging_ga_to_gfn_cr3(v, nested_cr3, L2_gpa, &pfec, NULL);
if ( gfn == INVALID_GFN )
return NESTEDHVM_PAGEFAULT_INJECT;
diff --git a/xen/arch/x86/mm/hap/private.h b/xen/arch/x86/mm/hap/private.h
index 6dcd128838..b5c0b6aafd 100644
--- a/xen/arch/x86/mm/hap/private.h
+++ b/xen/arch/x86/mm/hap/private.h
@@ -40,12 +40,12 @@ unsigned long hap_gva_to_gfn_4_levels(struct vcpu *v,
unsigned long hap_p2m_ga_to_gfn_2_levels(struct vcpu *v,
struct p2m_domain *p2m, unsigned long cr3,
- paddr_t ga, uint32_t *pfec);
+ paddr_t ga, uint32_t *pfec, unsigned int *page_order);
unsigned long hap_p2m_ga_to_gfn_3_levels(struct vcpu *v,
struct p2m_domain *p2m, unsigned long cr3,
- paddr_t ga, uint32_t *pfec);
+ paddr_t ga, uint32_t *pfec, unsigned int *page_order);
unsigned long hap_p2m_ga_to_gfn_4_levels(struct vcpu *v,
struct p2m_domain *p2m, unsigned long cr3,
- paddr_t ga, uint32_t *pfec);
+ paddr_t ga, uint32_t *pfec, unsigned int *page_order);
#endif /* __HAP_PRIVATE_H__ */
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index c3c8c87c37..c6cb98b2e5 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -1206,7 +1206,7 @@ unsigned long paging_gva_to_gfn(struct vcpu *v,
/* translate l2 guest gfn into l1 guest gfn */
return hostmode->p2m_ga_to_gfn(v, hostp2m, ncr3,
- gfn << PAGE_SHIFT, pfec);
+ gfn << PAGE_SHIFT, pfec, NULL);
}
return hostmode->gva_to_gfn(v, hostp2m, va, pfec);
diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-x86/guest_pt.h
index e3dd07a8d7..9a3b949bf1 100644
--- a/xen/include/asm-x86/guest_pt.h
+++ b/xen/include/asm-x86/guest_pt.h
@@ -272,6 +272,24 @@ guest_walk_to_gpa(walk_t *gw)
return guest_l1e_get_paddr(gw->l1e) + (gw->va & ~PAGE_MASK);
}
+/* 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(walk_t *gw)
+{
+ /* 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
+ if ( guest_l3e_get_flags(gw->l3e) & _PAGE_PSE )
+ return GUEST_L3_PAGETABLE_SHIFT - PAGE_SHIFT;
+#endif
+ if ( guest_l2e_get_flags(gw->l2e) & _PAGE_PSE )
+ return GUEST_L2_PAGETABLE_SHIFT - PAGE_SHIFT;
+ return GUEST_L1_PAGETABLE_SHIFT - PAGE_SHIFT;
+}
+
+
/* Walk the guest pagetables, after the manner of a hardware walker.
*
* Inputs: a vcpu, a virtual address, a walk_t to fill, a
diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h
index 0a32fe2b4e..c432a973ed 100644
--- a/xen/include/asm-x86/paging.h
+++ b/xen/include/asm-x86/paging.h
@@ -115,7 +115,8 @@ struct paging_mode {
unsigned long (*p2m_ga_to_gfn )(struct vcpu *v,
struct p2m_domain *p2m,
unsigned long cr3,
- paddr_t ga, uint32_t *pfec);
+ paddr_t ga, uint32_t *pfec,
+ unsigned int *page_order);
void (*update_cr3 )(struct vcpu *v, int do_locking);
void (*update_paging_modes )(struct vcpu *v);
void (*write_p2m_entry )(struct vcpu *v, unsigned long gfn,
@@ -270,15 +271,18 @@ unsigned long paging_gva_to_gfn(struct vcpu *v,
* to by nested HAP code, to walk the guest-supplied NPT tables as if
* they were pagetables.
* Use 'paddr_t' for the guest address so it won't overflow when
- * guest or nested guest is in 32bit PAE mode.
- */
+ * l1 or l2 guest is in 32bit PAE mode.
+ * If the GFN returned is not INVALID_GFN, *page_order gives
+ * the size of the superpage (if any) it was found in. */
static inline unsigned long paging_ga_to_gfn_cr3(struct vcpu *v,
unsigned long cr3,
paddr_t ga,
- uint32_t *pfec)
+ uint32_t *pfec,
+ unsigned int *page_order)
{
struct p2m_domain *p2m = v->domain->arch.p2m;
- return paging_get_hostmode(v)->p2m_ga_to_gfn(v, p2m, cr3, ga, pfec);
+ return paging_get_hostmode(v)->p2m_ga_to_gfn(v, p2m, cr3, ga, pfec,
+ page_order);
}
/* Update all the things that are derived from the guest's CR3.