[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] hap: Merge the guest-walking functions into one.
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |