# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1184677785 -3600
# Node ID 45b97e0f2dc817b903bca37a507c8586cddc2919
# Parent ee7a5ddc184728e2a82078e382eb21e5c54505df
hap: Merge the guest-walking functions into one.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/mm/hap/support.c | 340 ---------------------------------------
xen/arch/x86/mm/hap/Makefile | 10 +
xen/arch/x86/mm/hap/guest_walk.c | 181 ++++++++++++++++++++
xen/arch/x86/mm/hap/hap.c | 35 ++--
xen/arch/x86/mm/hap/private.h | 55 ------
5 files changed, 215 insertions(+), 406 deletions(-)
diff -r ee7a5ddc1847 -r 45b97e0f2dc8 xen/arch/x86/mm/hap/Makefile
--- a/xen/arch/x86/mm/hap/Makefile Tue Jul 17 10:36:33 2007 +0100
+++ b/xen/arch/x86/mm/hap/Makefile Tue Jul 17 14:09:45 2007 +0100
@@ -1,2 +1,10 @@ obj-y += hap.o
obj-y += hap.o
-obj-y += support.o
+obj-y += guest_walk_2level.o
+obj-y += guest_walk_3level.o
+obj-y += guest_walk_4level.o
+
+guest_levels = $(subst level,,$(filter %level,$(subst ., ,$(subst _, ,$(1)))))
+guest_walk_defns = -DGUEST_PAGING_LEVELS=$(call guest_levels,$(1))
+
+guest_walk_%level.o: guest_walk.c $(HDRS) Makefile
+ $(CC) $(CFLAGS) $(call guest_walk_defns,$(@F)) -c $< -o $@
diff -r ee7a5ddc1847 -r 45b97e0f2dc8 xen/arch/x86/mm/hap/guest_walk.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/guest_walk.c Tue Jul 17 14:09:45 2007 +0100
@@ -0,0 +1,181 @@
+/*
+ * arch/x86/mm/hap/guest_walk.c
+ *
+ * Guest page table walker
+ * Copyright (c) 2007, AMD Corporation (Wei Huang)
+ * Copyright (c) 2007, XenSource Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/domain_page.h>
+#include <asm/page.h>
+#include <xen/event.h>
+#include <xen/sched.h>
+#include <asm/hvm/svm/vmcb.h>
+#include <asm/domain.h>
+#include <asm/shadow.h>
+#include <asm/hap.h>
+
+#include "private.h"
+
+#define _hap_gva_to_gfn(levels) hap_gva_to_gfn_##levels##level
+#define hap_gva_to_gfn(levels) _hap_gva_to_gfn(levels)
+
+#if GUEST_PAGING_LEVELS > CONFIG_PAGING_LEVELS
+
+unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
+ struct vcpu *v, unsigned long gva)
+{
+ gdprintk(XENLOG_ERR,
+ "Guest paging level is greater than host paging level!\n");
+ domain_crash(v->domain);
+ return INVALID_GFN;
+}
+
+#else
+
+#if GUEST_PAGING_LEVELS == 2
+#include "../page-guest32.h"
+#define l1_pgentry_t l1_pgentry_32_t
+#define l2_pgentry_t l2_pgentry_32_t
+#undef l2e_get_flags
+#define l2e_get_flags(x) l2e_get_flags_32(x)
+#undef l1e_get_flags
+#define l1e_get_flags(x) l1e_get_flags_32(x)
+#endif
+
+unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
+ struct vcpu *v, unsigned long gva)
+{
+ unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
+ int mode = GUEST_PAGING_LEVELS;
+ int lev, index;
+ paddr_t gpa = 0;
+ unsigned long gpfn, mfn;
+ int success = 1;
+
+ l1_pgentry_t *l1e;
+ l2_pgentry_t *l2e;
+#if GUEST_PAGING_LEVELS >= 3
+ l3_pgentry_t *l3e;
+#endif
+#if GUEST_PAGING_LEVELS >= 4
+ l4_pgentry_t *l4e;
+#endif
+
+ gpfn = (gcr3 >> PAGE_SHIFT);
+ for ( lev = mode; lev >= 1; lev-- )
+ {
+ mfn = get_mfn_from_gpfn(gpfn);
+ if ( mfn == INVALID_MFN )
+ {
+ HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva,
+ lev);
+ success = 0;
+ break;
+ }
+ index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
+
+#if GUEST_PAGING_LEVELS >= 4
+ if ( lev == 4 )
+ {
+ l4e = map_domain_page(mfn);
+ if ( !(l4e_get_flags(l4e[index]) & _PAGE_PRESENT) )
+ {
+ HAP_PRINTK("Level 4 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l4e_get_pfn(l4e[index]);
+ unmap_domain_page(l4e);
+ }
+#endif
+
+#if GUEST_PAGING_LEVELS >= 3
+ if ( lev == 3 )
+ {
+ l3e = map_domain_page(mfn);
+#if GUEST_PAGING_LEVELS == 3
+ index += ((gcr3 >> 5) & 127) * 4;
+#endif
+ if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) )
+ {
+ HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l3e_get_pfn(l3e[index]);
+ unmap_domain_page(l3e);
+ }
+#endif
+
+ if ( lev == 2 )
+ {
+ l2e = map_domain_page(mfn);
+ if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) )
+ {
+ HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
+ success = 0;
+ }
+
+ if ( l2e_get_flags(l2e[index]) & _PAGE_PSE )
+ {
+ paddr_t mask = ((paddr_t)1 << PT_SHIFT[mode][2]) - 1;
+ HAP_PRINTK("guest page table is PSE\n");
+ gpa = (l2e_get_intpte(l2e[index]) & ~mask) + (gva & mask);
+ unmap_domain_page(l2e);
+ break; /* last level page table, jump out from here */
+ }
+
+ gpfn = l2e_get_pfn(l2e[index]);
+ unmap_domain_page(l2e);
+ }
+
+ if ( lev == 1 )
+ {
+ l1e = map_domain_page(mfn);
+ if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) )
+ {
+ HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l1e_get_pfn(l1e[index]);
+ gpa = (l1e_get_intpte(l1e[index]) & PAGE_MASK) + (gva &~PAGE_MASK);
+ unmap_domain_page(l1e);
+ }
+
+ if ( success != 1 ) /* error happened, jump out */
+ break;
+ }
+
+ gpa &= PADDR_MASK;
+ HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
+
+ return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT));
+}
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r ee7a5ddc1847 -r 45b97e0f2dc8 xen/arch/x86/mm/hap/hap.c
--- a/xen/arch/x86/mm/hap/hap.c Tue Jul 17 10:36:33 2007 +0100
+++ b/xen/arch/x86/mm/hap/hap.c Tue Jul 17 14:09:45 2007 +0100
@@ -290,8 +290,8 @@ void hap_install_xen_entries_in_l2h(stru
l2e_from_pfn(
mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
__PAGE_HYPERVISOR);
-
- for ( i = 0; i < HAP_L3_PAGETABLE_ENTRIES; i++ )
+
+ for ( i = 0; i < 4; i++ )
sl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
l2e_empty();
@@ -564,6 +564,7 @@ void hap_vcpu_init(struct vcpu *v)
{
v->arch.paging.mode = &hap_paging_real_mode;
}
+
/************************************************/
/* HAP PAGING MODE FUNCTIONS */
/************************************************/
@@ -571,8 +572,8 @@ void hap_vcpu_init(struct vcpu *v)
* HAP guests can handle page faults (in the guest page tables) without
* needing any action from Xen, so we should not be intercepting them.
*/
-int hap_page_fault(struct vcpu *v, unsigned long va,
- struct cpu_user_regs *regs)
+static int hap_page_fault(struct vcpu *v, unsigned long va,
+ struct cpu_user_regs *regs)
{
HAP_ERROR("Intercepted a guest #PF (%u:%u) with HAP enabled.\n",
v->domain->domain_id, v->vcpu_id);
@@ -584,7 +585,7 @@ int hap_page_fault(struct vcpu *v, unsig
* HAP guests can handle invlpg without needing any action from Xen, so
* should not be intercepting it.
*/
-int hap_invlpg(struct vcpu *v, unsigned long va)
+static int hap_invlpg(struct vcpu *v, unsigned long va)
{
HAP_ERROR("Intercepted a guest INVLPG (%u:%u) with HAP enabled.\n",
v->domain->domain_id, v->vcpu_id);
@@ -596,11 +597,11 @@ int hap_invlpg(struct vcpu *v, unsigned
* HAP guests do not need to take any action on CR3 writes (they are still
* intercepted, so that Xen's copy of the guest's CR3 can be kept in sync.)
*/
-void hap_update_cr3(struct vcpu *v, int do_locking)
-{
-}
-
-void hap_update_paging_modes(struct vcpu *v)
+static void hap_update_cr3(struct vcpu *v, int do_locking)
+{
+}
+
+static void hap_update_paging_modes(struct vcpu *v)
{
struct domain *d;
@@ -678,7 +679,7 @@ static void p2m_install_entry_in_monitor
}
#endif
-void
+static void
hap_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p,
mfn_t table_mfn, l1_pgentry_t new, unsigned int level)
{
@@ -696,6 +697,12 @@ hap_write_p2m_entry(struct vcpu *v, unsi
hap_unlock(v->domain);
}
+static unsigned long hap_gva_to_gfn_real_mode(
+ struct vcpu *v, unsigned long gva)
+{
+ return ((paddr_t)gva >> PAGE_SHIFT);
+}
+
/* Entry points into this mode of the hap code. */
struct paging_mode hap_paging_real_mode = {
.page_fault = hap_page_fault,
@@ -710,7 +717,7 @@ struct paging_mode hap_paging_protected_
struct paging_mode hap_paging_protected_mode = {
.page_fault = hap_page_fault,
.invlpg = hap_invlpg,
- .gva_to_gfn = hap_gva_to_gfn_protected_mode,
+ .gva_to_gfn = hap_gva_to_gfn_2level,
.update_cr3 = hap_update_cr3,
.update_paging_modes = hap_update_paging_modes,
.write_p2m_entry = hap_write_p2m_entry,
@@ -720,7 +727,7 @@ struct paging_mode hap_paging_pae_mode =
struct paging_mode hap_paging_pae_mode = {
.page_fault = hap_page_fault,
.invlpg = hap_invlpg,
- .gva_to_gfn = hap_gva_to_gfn_pae_mode,
+ .gva_to_gfn = hap_gva_to_gfn_3level,
.update_cr3 = hap_update_cr3,
.update_paging_modes = hap_update_paging_modes,
.write_p2m_entry = hap_write_p2m_entry,
@@ -730,7 +737,7 @@ struct paging_mode hap_paging_long_mode
struct paging_mode hap_paging_long_mode = {
.page_fault = hap_page_fault,
.invlpg = hap_invlpg,
- .gva_to_gfn = hap_gva_to_gfn_long_mode,
+ .gva_to_gfn = hap_gva_to_gfn_4level,
.update_cr3 = hap_update_cr3,
.update_paging_modes = hap_update_paging_modes,
.write_p2m_entry = hap_write_p2m_entry,
diff -r ee7a5ddc1847 -r 45b97e0f2dc8 xen/arch/x86/mm/hap/private.h
--- a/xen/arch/x86/mm/hap/private.h Tue Jul 17 10:36:33 2007 +0100
+++ b/xen/arch/x86/mm/hap/private.h Tue Jul 17 14:09:45 2007 +0100
@@ -26,10 +26,10 @@
/********************************************/
/* GUEST TRANSLATION FUNCS */
/********************************************/
-unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva);
-unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva);
-unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva);
-unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_2level(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_3level(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_4level(struct vcpu *v, unsigned long gva);
+
/********************************************/
/* MISC DEFINITIONS */
/********************************************/
@@ -62,51 +62,4 @@ static const int PT_ENTRIES[][5] =
{ 0, 512, 512, 512, 512} /* 4 */
};
-/********************************************/
-/* PAGING DEFINITION FOR GUEST */
-/********************************************/
-#define PHYSICAL_PAGE_4K_SIZE (1UL << 12)
-#define PHYSICAL_PAGE_2M_SIZE (1UL << 21)
-#define PHYSICAL_PAGE_4M_SIZE (1UL << 22)
-#define PHYSICAL_PAGE_4K_MASK ( ~(PHYSICAL_PAGE_4K_SIZE - 1) )
-#define PHYSICAL_PAGE_2M_MASK ( ~(PHYSICAL_PAGE_2M_SIZE - 1) )
-#define PHYSICAL_PAGE_4M_MASK ( ~(PHYSICAL_PAGE_4M_SIZE - 1) )
-
-/* long mode physical address mask */
-#define PHYSICAL_ADDR_BITS_LM 52
-#define PHYSICAL_ADDR_MASK_LM ((1UL << PHYSICAL_ADDR_BITS_LM)-1)
-#define PHYSICAL_ADDR_2M_MASK_LM (PHYSICAL_PAGE_2M_MASK &
PHYSICAL_ADDR_MASK_LM)
-#define PHYSICAL_ADDR_4K_MASK_LM (PHYSICAL_PAGE_4K_MASK &
PHYSICAL_ADDR_MASK_LM)
-
-#define PAGE_NX_BIT (1ULL << 63)
-/************************************************/
-/* PAGETABLE RELATED VARIABLES */
-/************************************************/
-#if CONFIG_PAGING_LEVELS == 2
-#define HAP_L1_PAGETABLE_ENTRIES 1024
-#define HAP_L2_PAGETABLE_ENTRIES 1024
-#define HAP_L1_PAGETABLE_SHIFT 12
-#define HAP_L2_PAGETABLE_SHIFT 22
-#endif
-
-#if CONFIG_PAGING_LEVELS == 3
-#define HAP_L1_PAGETABLE_ENTRIES 512
-#define HAP_L2_PAGETABLE_ENTRIES 512
-#define HAP_L3_PAGETABLE_ENTRIES 4
-#define HAP_L1_PAGETABLE_SHIFT 12
-#define HAP_L2_PAGETABLE_SHIFT 21
-#define HAP_L3_PAGETABLE_SHIFT 30
-#endif
-
-#if CONFIG_PAGING_LEVELS == 4
-#define HAP_L1_PAGETABLE_ENTRIES 512
-#define HAP_L2_PAGETABLE_ENTRIES 512
-#define HAP_L3_PAGETABLE_ENTRIES 512
-#define HAP_L4_PAGETABLE_ENTRIES 512
-#define HAP_L1_PAGETABLE_SHIFT 12
-#define HAP_L2_PAGETABLE_SHIFT 21
-#define HAP_L3_PAGETABLE_SHIFT 30
-#define HAP_L4_PAGETABLE_SHIFT 39
-#endif
-
#endif /* __SVM_NPT_H__ */
diff -r ee7a5ddc1847 -r 45b97e0f2dc8 xen/arch/x86/mm/hap/support.c
--- a/xen/arch/x86/mm/hap/support.c Tue Jul 17 10:36:33 2007 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-/*
- * arch/x86/mm/hap/support.c
- *
- * guest page table walker
- * Copyright (c) 2007, AMD Corporation (Wei Huang)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/mm.h>
-#include <xen/domain_page.h>
-#include <asm/page.h>
-#include <xen/event.h>
-#include <xen/sched.h>
-#include <asm/hvm/svm/vmcb.h>
-#include <asm/domain.h>
-#include <asm/shadow.h>
-#include <asm/hap.h>
-
-#include "private.h"
-#include "../page-guest32.h"
-
-/*******************************************/
-/* Platform Specific Functions */
-/*******************************************/
-
-/* Translate guest virtual address to guest physical address. Specifically
- * for real mode guest.
- */
-unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva)
-{
- return ((paddr_t)gva >> PAGE_SHIFT);
-}
-
-/* Translate guest virtual address to guest physical address. Specifically
- * for protected guest.
- */
-unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva)
-{
- unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
- int mode = 2; /* two-level guest */
- int lev, index;
- paddr_t gpa = 0;
- unsigned long gpfn, mfn;
- int success = 1;
- l2_pgentry_32_t *l2e; /* guest page entry size is 32-bit */
- l1_pgentry_32_t *l1e;
-
- gpfn = (gcr3 >> PAGE_SHIFT);
- for ( lev = mode; lev >= 1; lev-- )
- {
- mfn = get_mfn_from_gpfn(gpfn);
- if ( mfn == INVALID_MFN )
- {
- HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva,
- lev);
- success = 0;
- break;
- }
- index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
-
- if ( lev == 2 )
- {
- l2e = map_domain_page(mfn);
- HAP_PRINTK("l2 page table entry is %ulx at index = %d\n",
- l2e[index].l2, index);
- if ( !(l2e_get_flags_32(l2e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
- success = 0;
- }
-
- if ( l2e_get_flags_32(l2e[index]) & _PAGE_PSE )
- {
- HAP_PRINTK("guest page table is PSE\n");
- if ( l2e_get_intpte(l2e[index]) & 0x001FE000UL ) /*[13:20] */
- {
- printk("guest physical memory size is too large!\n");
- domain_crash(v->domain);
- }
- gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_4M_MASK) +
- (gva & ~PHYSICAL_PAGE_4M_MASK);
- unmap_domain_page(l2e);
- break; /* last level page table, return from here */
- }
-
- gpfn = l2e_get_pfn(l2e[index]);
- unmap_domain_page(l2e);
- }
-
- if ( lev == 1 )
- {
- l1e = map_domain_page(mfn);
- HAP_PRINTK("l1 page table entry is %ulx at index = %d\n",
- l1e[index].l1, index);
- if ( !(l1e_get_flags_32(l1e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
- success = 0;
- }
- gpfn = l1e_get_pfn(l1e[index]);
- gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) +
- (gva & ~PHYSICAL_PAGE_4K_MASK);
- unmap_domain_page(l1e);
- }
-
- if ( !success ) /* error happened, jump out */
- break;
- }
-
- HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
-
- return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT));
-}
-
-
-
-/* Translate guest virtual address to guest physical address. Specifically
- * for PAE mode guest.
- */
-unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva)
-{
-#if CONFIG_PAGING_LEVELS >= 3
- unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
- int mode = 3; /* three-level guest */
- int lev, index;
- paddr_t gpa = 0;
- unsigned long gpfn, mfn;
- int success = 1;
- l1_pgentry_t *l1e;
- l2_pgentry_t *l2e;
- l3_pgentry_t *l3e;
-
- gpfn = (gcr3 >> PAGE_SHIFT);
- for ( lev = mode; lev >= 1; lev-- )
- {
- mfn = get_mfn_from_gpfn(gpfn);
- if ( mfn == INVALID_MFN )
- {
- HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva,
- lev);
- success = 0;
- break;
- }
- index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
-
- if ( lev == 3 )
- {
- l3e = map_domain_page(mfn);
- index += ((gcr3 >> 5) & 127) * 4;
- if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
- success = 0;
- }
- gpfn = l3e_get_pfn(l3e[index]);
- unmap_domain_page(l3e);
- }
-
- if ( lev == 2 )
- {
- l2e = map_domain_page(mfn);
- if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
- success = 0;
- }
-
- if ( l2e_get_flags(l2e[index]) & _PAGE_PSE )
- {
- HAP_PRINTK("guest page table is PSE\n");
- gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_2M_MASK) +
- (gva & ~PHYSICAL_PAGE_2M_MASK);
- unmap_domain_page(l2e);
- break; /* last level page table, jump out from here */
- }
-
- gpfn = l2e_get_pfn(l2e[index]);
- unmap_domain_page(l2e);
- }
-
- if ( lev == 1 )
- {
- l1e = map_domain_page(mfn);
- if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
- success = 0;
- }
- gpfn = l1e_get_pfn(l1e[index]);
- gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) +
- (gva & ~PHYSICAL_PAGE_4K_MASK);
- unmap_domain_page(l1e);
- }
-
- if ( success != 1 ) /* error happened, jump out */
- break;
- }
-
- gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */
- HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
-
- return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT));
-#else
- printk("guest paging level (3) is greater than host paging level!\n");
- domain_crash(v->domain);
- return INVALID_GFN;
-#endif
-}
-
-
-/* Translate guest virtual address to guest physical address. Specifically
- * for long mode guest.
- */
-unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva)
-{
-#if CONFIG_PAGING_LEVELS == 4
- unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
- int mode = 4; /* four-level guest */
- int lev, index;
- paddr_t gpa = 0;
- unsigned long gpfn, mfn;
- int success = 1;
- l4_pgentry_t *l4e;
- l3_pgentry_t *l3e;
- l2_pgentry_t *l2e;
- l1_pgentry_t *l1e;
-
- gpfn = (gcr3 >> PAGE_SHIFT);
- for ( lev = mode; lev >= 1; lev-- )
- {
- mfn = get_mfn_from_gpfn(gpfn);
- if ( mfn == INVALID_MFN )
- {
- HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva,
- lev);
- success = 0;
- break;
- }
- index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
-
- if ( lev == 4 )
- {
- l4e = map_domain_page(mfn);
- if ( !(l4e_get_flags(l4e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 4 entry not present at index = %d\n", index);
- success = 0;
- }
- gpfn = l4e_get_pfn(l4e[index]);
- unmap_domain_page(l4e);
- }
-
- if ( lev == 3 )
- {
- l3e = map_domain_page(mfn);
- if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
- success = 0;
- }
- gpfn = l3e_get_pfn(l3e[index]);
- unmap_domain_page(l3e);
- }
-
- if ( lev == 2 )
- {
- l2e = map_domain_page(mfn);
- if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
- success = 0;
- }
-
- if ( l2e_get_flags(l2e[index]) & _PAGE_PSE )
- {
- HAP_PRINTK("guest page table is PSE\n");
- gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_ADDR_2M_MASK_LM)
- + (gva & ~PHYSICAL_PAGE_2M_MASK);
- unmap_domain_page(l2e);
- break; /* last level page table, jump out from here */
- }
-
- gpfn = l2e_get_pfn(l2e[index]);
- unmap_domain_page(l2e);
- }
-
- if ( lev == 1 )
- {
- l1e = map_domain_page(mfn);
- if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) )
- {
- HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
- success = 0;
- }
- gpfn = l1e_get_pfn(l1e[index]);
- gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_ADDR_4K_MASK_LM) +
- (gva & ~PHYSICAL_PAGE_4K_MASK);
- unmap_domain_page(l1e);
- }
-
- if ( success != 1 ) /* error happened, jump out */
- break;
- }
-
- gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */
- HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
-
- return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT));
-#else
- printk("guest paging level (4) is greater than host paging level!\n");
- domain_crash(v->domain);
- return INVALID_GFN;
-#endif
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
-
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|