ia64/xen-unstable
changeset 15611:45b97e0f2dc8
hap: Merge the guest-walking functions into one.
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Tue Jul 17 14:09:45 2007 +0100 (2007-07-17) |
parents | ee7a5ddc1847 |
children | 4721e9d836dd |
files | xen/arch/x86/mm/hap/Makefile xen/arch/x86/mm/hap/guest_walk.c xen/arch/x86/mm/hap/hap.c xen/arch/x86/mm/hap/private.h xen/arch/x86/mm/hap/support.c |
line diff
1.1 --- a/xen/arch/x86/mm/hap/Makefile Tue Jul 17 10:36:33 2007 +0100 1.2 +++ b/xen/arch/x86/mm/hap/Makefile Tue Jul 17 14:09:45 2007 +0100 1.3 @@ -1,2 +1,10 @@ 1.4 obj-y += hap.o 1.5 -obj-y += support.o 1.6 +obj-y += guest_walk_2level.o 1.7 +obj-y += guest_walk_3level.o 1.8 +obj-y += guest_walk_4level.o 1.9 + 1.10 +guest_levels = $(subst level,,$(filter %level,$(subst ., ,$(subst _, ,$(1))))) 1.11 +guest_walk_defns = -DGUEST_PAGING_LEVELS=$(call guest_levels,$(1)) 1.12 + 1.13 +guest_walk_%level.o: guest_walk.c $(HDRS) Makefile 1.14 + $(CC) $(CFLAGS) $(call guest_walk_defns,$(@F)) -c $< -o $@
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/xen/arch/x86/mm/hap/guest_walk.c Tue Jul 17 14:09:45 2007 +0100 2.3 @@ -0,0 +1,181 @@ 2.4 +/* 2.5 + * arch/x86/mm/hap/guest_walk.c 2.6 + * 2.7 + * Guest page table walker 2.8 + * Copyright (c) 2007, AMD Corporation (Wei Huang) 2.9 + * Copyright (c) 2007, XenSource Inc. 2.10 + * 2.11 + * This program is free software; you can redistribute it and/or modify it 2.12 + * under the terms and conditions of the GNU General Public License, 2.13 + * version 2, as published by the Free Software Foundation. 2.14 + * 2.15 + * This program is distributed in the hope it will be useful, but WITHOUT 2.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.17 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 2.18 + * more details. 2.19 + * 2.20 + * You should have received a copy of the GNU General Public License along with 2.21 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 2.22 + * Place - Suite 330, Boston, MA 02111-1307 USA. 2.23 + */ 2.24 + 2.25 +#include <xen/config.h> 2.26 +#include <xen/types.h> 2.27 +#include <xen/mm.h> 2.28 +#include <xen/domain_page.h> 2.29 +#include <asm/page.h> 2.30 +#include <xen/event.h> 2.31 +#include <xen/sched.h> 2.32 +#include <asm/hvm/svm/vmcb.h> 2.33 +#include <asm/domain.h> 2.34 +#include <asm/shadow.h> 2.35 +#include <asm/hap.h> 2.36 + 2.37 +#include "private.h" 2.38 + 2.39 +#define _hap_gva_to_gfn(levels) hap_gva_to_gfn_##levels##level 2.40 +#define hap_gva_to_gfn(levels) _hap_gva_to_gfn(levels) 2.41 + 2.42 +#if GUEST_PAGING_LEVELS > CONFIG_PAGING_LEVELS 2.43 + 2.44 +unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)( 2.45 + struct vcpu *v, unsigned long gva) 2.46 +{ 2.47 + gdprintk(XENLOG_ERR, 2.48 + "Guest paging level is greater than host paging level!\n"); 2.49 + domain_crash(v->domain); 2.50 + return INVALID_GFN; 2.51 +} 2.52 + 2.53 +#else 2.54 + 2.55 +#if GUEST_PAGING_LEVELS == 2 2.56 +#include "../page-guest32.h" 2.57 +#define l1_pgentry_t l1_pgentry_32_t 2.58 +#define l2_pgentry_t l2_pgentry_32_t 2.59 +#undef l2e_get_flags 2.60 +#define l2e_get_flags(x) l2e_get_flags_32(x) 2.61 +#undef l1e_get_flags 2.62 +#define l1e_get_flags(x) l1e_get_flags_32(x) 2.63 +#endif 2.64 + 2.65 +unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)( 2.66 + struct vcpu *v, unsigned long gva) 2.67 +{ 2.68 + unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3); 2.69 + int mode = GUEST_PAGING_LEVELS; 2.70 + int lev, index; 2.71 + paddr_t gpa = 0; 2.72 + unsigned long gpfn, mfn; 2.73 + int success = 1; 2.74 + 2.75 + l1_pgentry_t *l1e; 2.76 + l2_pgentry_t *l2e; 2.77 +#if GUEST_PAGING_LEVELS >= 3 2.78 + l3_pgentry_t *l3e; 2.79 +#endif 2.80 +#if GUEST_PAGING_LEVELS >= 4 2.81 + l4_pgentry_t *l4e; 2.82 +#endif 2.83 + 2.84 + gpfn = (gcr3 >> PAGE_SHIFT); 2.85 + for ( lev = mode; lev >= 1; lev-- ) 2.86 + { 2.87 + mfn = get_mfn_from_gpfn(gpfn); 2.88 + if ( mfn == INVALID_MFN ) 2.89 + { 2.90 + HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 2.91 + lev); 2.92 + success = 0; 2.93 + break; 2.94 + } 2.95 + index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1); 2.96 + 2.97 +#if GUEST_PAGING_LEVELS >= 4 2.98 + if ( lev == 4 ) 2.99 + { 2.100 + l4e = map_domain_page(mfn); 2.101 + if ( !(l4e_get_flags(l4e[index]) & _PAGE_PRESENT) ) 2.102 + { 2.103 + HAP_PRINTK("Level 4 entry not present at index = %d\n", index); 2.104 + success = 0; 2.105 + } 2.106 + gpfn = l4e_get_pfn(l4e[index]); 2.107 + unmap_domain_page(l4e); 2.108 + } 2.109 +#endif 2.110 + 2.111 +#if GUEST_PAGING_LEVELS >= 3 2.112 + if ( lev == 3 ) 2.113 + { 2.114 + l3e = map_domain_page(mfn); 2.115 +#if GUEST_PAGING_LEVELS == 3 2.116 + index += ((gcr3 >> 5) & 127) * 4; 2.117 +#endif 2.118 + if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) 2.119 + { 2.120 + HAP_PRINTK("Level 3 entry not present at index = %d\n", index); 2.121 + success = 0; 2.122 + } 2.123 + gpfn = l3e_get_pfn(l3e[index]); 2.124 + unmap_domain_page(l3e); 2.125 + } 2.126 +#endif 2.127 + 2.128 + if ( lev == 2 ) 2.129 + { 2.130 + l2e = map_domain_page(mfn); 2.131 + if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) 2.132 + { 2.133 + HAP_PRINTK("Level 2 entry not present at index = %d\n", index); 2.134 + success = 0; 2.135 + } 2.136 + 2.137 + if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) 2.138 + { 2.139 + paddr_t mask = ((paddr_t)1 << PT_SHIFT[mode][2]) - 1; 2.140 + HAP_PRINTK("guest page table is PSE\n"); 2.141 + gpa = (l2e_get_intpte(l2e[index]) & ~mask) + (gva & mask); 2.142 + unmap_domain_page(l2e); 2.143 + break; /* last level page table, jump out from here */ 2.144 + } 2.145 + 2.146 + gpfn = l2e_get_pfn(l2e[index]); 2.147 + unmap_domain_page(l2e); 2.148 + } 2.149 + 2.150 + if ( lev == 1 ) 2.151 + { 2.152 + l1e = map_domain_page(mfn); 2.153 + if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) 2.154 + { 2.155 + HAP_PRINTK("Level 1 entry not present at index = %d\n", index); 2.156 + success = 0; 2.157 + } 2.158 + gpfn = l1e_get_pfn(l1e[index]); 2.159 + gpa = (l1e_get_intpte(l1e[index]) & PAGE_MASK) + (gva &~PAGE_MASK); 2.160 + unmap_domain_page(l1e); 2.161 + } 2.162 + 2.163 + if ( success != 1 ) /* error happened, jump out */ 2.164 + break; 2.165 + } 2.166 + 2.167 + gpa &= PADDR_MASK; 2.168 + HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa); 2.169 + 2.170 + return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT)); 2.171 +} 2.172 + 2.173 +#endif 2.174 + 2.175 +/* 2.176 + * Local variables: 2.177 + * mode: C 2.178 + * c-set-style: "BSD" 2.179 + * c-basic-offset: 4 2.180 + * tab-width: 4 2.181 + * indent-tabs-mode: nil 2.182 + * End: 2.183 + */ 2.184 +
3.1 --- a/xen/arch/x86/mm/hap/hap.c Tue Jul 17 10:36:33 2007 +0100 3.2 +++ b/xen/arch/x86/mm/hap/hap.c Tue Jul 17 14:09:45 2007 +0100 3.3 @@ -290,8 +290,8 @@ void hap_install_xen_entries_in_l2h(stru 3.4 l2e_from_pfn( 3.5 mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)), 3.6 __PAGE_HYPERVISOR); 3.7 - 3.8 - for ( i = 0; i < HAP_L3_PAGETABLE_ENTRIES; i++ ) 3.9 + 3.10 + for ( i = 0; i < 4; i++ ) 3.11 sl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] = 3.12 l2e_empty(); 3.13 3.14 @@ -564,6 +564,7 @@ void hap_vcpu_init(struct vcpu *v) 3.15 { 3.16 v->arch.paging.mode = &hap_paging_real_mode; 3.17 } 3.18 + 3.19 /************************************************/ 3.20 /* HAP PAGING MODE FUNCTIONS */ 3.21 /************************************************/ 3.22 @@ -571,8 +572,8 @@ void hap_vcpu_init(struct vcpu *v) 3.23 * HAP guests can handle page faults (in the guest page tables) without 3.24 * needing any action from Xen, so we should not be intercepting them. 3.25 */ 3.26 -int hap_page_fault(struct vcpu *v, unsigned long va, 3.27 - struct cpu_user_regs *regs) 3.28 +static int hap_page_fault(struct vcpu *v, unsigned long va, 3.29 + struct cpu_user_regs *regs) 3.30 { 3.31 HAP_ERROR("Intercepted a guest #PF (%u:%u) with HAP enabled.\n", 3.32 v->domain->domain_id, v->vcpu_id); 3.33 @@ -584,7 +585,7 @@ int hap_page_fault(struct vcpu *v, unsig 3.34 * HAP guests can handle invlpg without needing any action from Xen, so 3.35 * should not be intercepting it. 3.36 */ 3.37 -int hap_invlpg(struct vcpu *v, unsigned long va) 3.38 +static int hap_invlpg(struct vcpu *v, unsigned long va) 3.39 { 3.40 HAP_ERROR("Intercepted a guest INVLPG (%u:%u) with HAP enabled.\n", 3.41 v->domain->domain_id, v->vcpu_id); 3.42 @@ -596,11 +597,11 @@ int hap_invlpg(struct vcpu *v, unsigned 3.43 * HAP guests do not need to take any action on CR3 writes (they are still 3.44 * intercepted, so that Xen's copy of the guest's CR3 can be kept in sync.) 3.45 */ 3.46 -void hap_update_cr3(struct vcpu *v, int do_locking) 3.47 +static void hap_update_cr3(struct vcpu *v, int do_locking) 3.48 { 3.49 } 3.50 3.51 -void hap_update_paging_modes(struct vcpu *v) 3.52 +static void hap_update_paging_modes(struct vcpu *v) 3.53 { 3.54 struct domain *d; 3.55 3.56 @@ -678,7 +679,7 @@ static void p2m_install_entry_in_monitor 3.57 } 3.58 #endif 3.59 3.60 -void 3.61 +static void 3.62 hap_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p, 3.63 mfn_t table_mfn, l1_pgentry_t new, unsigned int level) 3.64 { 3.65 @@ -696,6 +697,12 @@ hap_write_p2m_entry(struct vcpu *v, unsi 3.66 hap_unlock(v->domain); 3.67 } 3.68 3.69 +static unsigned long hap_gva_to_gfn_real_mode( 3.70 + struct vcpu *v, unsigned long gva) 3.71 +{ 3.72 + return ((paddr_t)gva >> PAGE_SHIFT); 3.73 +} 3.74 + 3.75 /* Entry points into this mode of the hap code. */ 3.76 struct paging_mode hap_paging_real_mode = { 3.77 .page_fault = hap_page_fault, 3.78 @@ -710,7 +717,7 @@ struct paging_mode hap_paging_real_mode 3.79 struct paging_mode hap_paging_protected_mode = { 3.80 .page_fault = hap_page_fault, 3.81 .invlpg = hap_invlpg, 3.82 - .gva_to_gfn = hap_gva_to_gfn_protected_mode, 3.83 + .gva_to_gfn = hap_gva_to_gfn_2level, 3.84 .update_cr3 = hap_update_cr3, 3.85 .update_paging_modes = hap_update_paging_modes, 3.86 .write_p2m_entry = hap_write_p2m_entry, 3.87 @@ -720,7 +727,7 @@ struct paging_mode hap_paging_protected_ 3.88 struct paging_mode hap_paging_pae_mode = { 3.89 .page_fault = hap_page_fault, 3.90 .invlpg = hap_invlpg, 3.91 - .gva_to_gfn = hap_gva_to_gfn_pae_mode, 3.92 + .gva_to_gfn = hap_gva_to_gfn_3level, 3.93 .update_cr3 = hap_update_cr3, 3.94 .update_paging_modes = hap_update_paging_modes, 3.95 .write_p2m_entry = hap_write_p2m_entry, 3.96 @@ -730,7 +737,7 @@ struct paging_mode hap_paging_pae_mode = 3.97 struct paging_mode hap_paging_long_mode = { 3.98 .page_fault = hap_page_fault, 3.99 .invlpg = hap_invlpg, 3.100 - .gva_to_gfn = hap_gva_to_gfn_long_mode, 3.101 + .gva_to_gfn = hap_gva_to_gfn_4level, 3.102 .update_cr3 = hap_update_cr3, 3.103 .update_paging_modes = hap_update_paging_modes, 3.104 .write_p2m_entry = hap_write_p2m_entry,
4.1 --- a/xen/arch/x86/mm/hap/private.h Tue Jul 17 10:36:33 2007 +0100 4.2 +++ b/xen/arch/x86/mm/hap/private.h Tue Jul 17 14:09:45 2007 +0100 4.3 @@ -26,10 +26,10 @@ 4.4 /********************************************/ 4.5 /* GUEST TRANSLATION FUNCS */ 4.6 /********************************************/ 4.7 -unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva); 4.8 -unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva); 4.9 -unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva); 4.10 -unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva); 4.11 +unsigned long hap_gva_to_gfn_2level(struct vcpu *v, unsigned long gva); 4.12 +unsigned long hap_gva_to_gfn_3level(struct vcpu *v, unsigned long gva); 4.13 +unsigned long hap_gva_to_gfn_4level(struct vcpu *v, unsigned long gva); 4.14 + 4.15 /********************************************/ 4.16 /* MISC DEFINITIONS */ 4.17 /********************************************/ 4.18 @@ -62,51 +62,4 @@ static const int PT_ENTRIES[][5] = 4.19 { 0, 512, 512, 512, 512} /* 4 */ 4.20 }; 4.21 4.22 -/********************************************/ 4.23 -/* PAGING DEFINITION FOR GUEST */ 4.24 -/********************************************/ 4.25 -#define PHYSICAL_PAGE_4K_SIZE (1UL << 12) 4.26 -#define PHYSICAL_PAGE_2M_SIZE (1UL << 21) 4.27 -#define PHYSICAL_PAGE_4M_SIZE (1UL << 22) 4.28 -#define PHYSICAL_PAGE_4K_MASK ( ~(PHYSICAL_PAGE_4K_SIZE - 1) ) 4.29 -#define PHYSICAL_PAGE_2M_MASK ( ~(PHYSICAL_PAGE_2M_SIZE - 1) ) 4.30 -#define PHYSICAL_PAGE_4M_MASK ( ~(PHYSICAL_PAGE_4M_SIZE - 1) ) 4.31 - 4.32 -/* long mode physical address mask */ 4.33 -#define PHYSICAL_ADDR_BITS_LM 52 4.34 -#define PHYSICAL_ADDR_MASK_LM ((1UL << PHYSICAL_ADDR_BITS_LM)-1) 4.35 -#define PHYSICAL_ADDR_2M_MASK_LM (PHYSICAL_PAGE_2M_MASK & PHYSICAL_ADDR_MASK_LM) 4.36 -#define PHYSICAL_ADDR_4K_MASK_LM (PHYSICAL_PAGE_4K_MASK & PHYSICAL_ADDR_MASK_LM) 4.37 - 4.38 -#define PAGE_NX_BIT (1ULL << 63) 4.39 -/************************************************/ 4.40 -/* PAGETABLE RELATED VARIABLES */ 4.41 -/************************************************/ 4.42 -#if CONFIG_PAGING_LEVELS == 2 4.43 -#define HAP_L1_PAGETABLE_ENTRIES 1024 4.44 -#define HAP_L2_PAGETABLE_ENTRIES 1024 4.45 -#define HAP_L1_PAGETABLE_SHIFT 12 4.46 -#define HAP_L2_PAGETABLE_SHIFT 22 4.47 -#endif 4.48 - 4.49 -#if CONFIG_PAGING_LEVELS == 3 4.50 -#define HAP_L1_PAGETABLE_ENTRIES 512 4.51 -#define HAP_L2_PAGETABLE_ENTRIES 512 4.52 -#define HAP_L3_PAGETABLE_ENTRIES 4 4.53 -#define HAP_L1_PAGETABLE_SHIFT 12 4.54 -#define HAP_L2_PAGETABLE_SHIFT 21 4.55 -#define HAP_L3_PAGETABLE_SHIFT 30 4.56 -#endif 4.57 - 4.58 -#if CONFIG_PAGING_LEVELS == 4 4.59 -#define HAP_L1_PAGETABLE_ENTRIES 512 4.60 -#define HAP_L2_PAGETABLE_ENTRIES 512 4.61 -#define HAP_L3_PAGETABLE_ENTRIES 512 4.62 -#define HAP_L4_PAGETABLE_ENTRIES 512 4.63 -#define HAP_L1_PAGETABLE_SHIFT 12 4.64 -#define HAP_L2_PAGETABLE_SHIFT 21 4.65 -#define HAP_L3_PAGETABLE_SHIFT 30 4.66 -#define HAP_L4_PAGETABLE_SHIFT 39 4.67 -#endif 4.68 - 4.69 #endif /* __SVM_NPT_H__ */
5.1 --- a/xen/arch/x86/mm/hap/support.c Tue Jul 17 10:36:33 2007 +0100 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,340 +0,0 @@ 5.4 -/* 5.5 - * arch/x86/mm/hap/support.c 5.6 - * 5.7 - * guest page table walker 5.8 - * Copyright (c) 2007, AMD Corporation (Wei Huang) 5.9 - * 5.10 - * This program is free software; you can redistribute it and/or modify it 5.11 - * under the terms and conditions of the GNU General Public License, 5.12 - * version 2, as published by the Free Software Foundation. 5.13 - * 5.14 - * This program is distributed in the hope it will be useful, but WITHOUT 5.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 5.17 - * more details. 5.18 - * 5.19 - * You should have received a copy of the GNU General Public License along with 5.20 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 5.21 - * Place - Suite 330, Boston, MA 02111-1307 USA. 5.22 - * 5.23 - */ 5.24 - 5.25 -#include <xen/config.h> 5.26 -#include <xen/types.h> 5.27 -#include <xen/mm.h> 5.28 -#include <xen/domain_page.h> 5.29 -#include <asm/page.h> 5.30 -#include <xen/event.h> 5.31 -#include <xen/sched.h> 5.32 -#include <asm/hvm/svm/vmcb.h> 5.33 -#include <asm/domain.h> 5.34 -#include <asm/shadow.h> 5.35 -#include <asm/hap.h> 5.36 - 5.37 -#include "private.h" 5.38 -#include "../page-guest32.h" 5.39 - 5.40 -/*******************************************/ 5.41 -/* Platform Specific Functions */ 5.42 -/*******************************************/ 5.43 - 5.44 -/* Translate guest virtual address to guest physical address. Specifically 5.45 - * for real mode guest. 5.46 - */ 5.47 -unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva) 5.48 -{ 5.49 - return ((paddr_t)gva >> PAGE_SHIFT); 5.50 -} 5.51 - 5.52 -/* Translate guest virtual address to guest physical address. Specifically 5.53 - * for protected guest. 5.54 - */ 5.55 -unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva) 5.56 -{ 5.57 - unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3); 5.58 - int mode = 2; /* two-level guest */ 5.59 - int lev, index; 5.60 - paddr_t gpa = 0; 5.61 - unsigned long gpfn, mfn; 5.62 - int success = 1; 5.63 - l2_pgentry_32_t *l2e; /* guest page entry size is 32-bit */ 5.64 - l1_pgentry_32_t *l1e; 5.65 - 5.66 - gpfn = (gcr3 >> PAGE_SHIFT); 5.67 - for ( lev = mode; lev >= 1; lev-- ) 5.68 - { 5.69 - mfn = get_mfn_from_gpfn(gpfn); 5.70 - if ( mfn == INVALID_MFN ) 5.71 - { 5.72 - HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 5.73 - lev); 5.74 - success = 0; 5.75 - break; 5.76 - } 5.77 - index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1); 5.78 - 5.79 - if ( lev == 2 ) 5.80 - { 5.81 - l2e = map_domain_page(mfn); 5.82 - HAP_PRINTK("l2 page table entry is %ulx at index = %d\n", 5.83 - l2e[index].l2, index); 5.84 - if ( !(l2e_get_flags_32(l2e[index]) & _PAGE_PRESENT) ) 5.85 - { 5.86 - HAP_PRINTK("Level 2 entry not present at index = %d\n", index); 5.87 - success = 0; 5.88 - } 5.89 - 5.90 - if ( l2e_get_flags_32(l2e[index]) & _PAGE_PSE ) 5.91 - { 5.92 - HAP_PRINTK("guest page table is PSE\n"); 5.93 - if ( l2e_get_intpte(l2e[index]) & 0x001FE000UL ) /*[13:20] */ 5.94 - { 5.95 - printk("guest physical memory size is too large!\n"); 5.96 - domain_crash(v->domain); 5.97 - } 5.98 - gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_4M_MASK) + 5.99 - (gva & ~PHYSICAL_PAGE_4M_MASK); 5.100 - unmap_domain_page(l2e); 5.101 - break; /* last level page table, return from here */ 5.102 - } 5.103 - 5.104 - gpfn = l2e_get_pfn(l2e[index]); 5.105 - unmap_domain_page(l2e); 5.106 - } 5.107 - 5.108 - if ( lev == 1 ) 5.109 - { 5.110 - l1e = map_domain_page(mfn); 5.111 - HAP_PRINTK("l1 page table entry is %ulx at index = %d\n", 5.112 - l1e[index].l1, index); 5.113 - if ( !(l1e_get_flags_32(l1e[index]) & _PAGE_PRESENT) ) 5.114 - { 5.115 - HAP_PRINTK("Level 1 entry not present at index = %d\n", index); 5.116 - success = 0; 5.117 - } 5.118 - gpfn = l1e_get_pfn(l1e[index]); 5.119 - gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) + 5.120 - (gva & ~PHYSICAL_PAGE_4K_MASK); 5.121 - unmap_domain_page(l1e); 5.122 - } 5.123 - 5.124 - if ( !success ) /* error happened, jump out */ 5.125 - break; 5.126 - } 5.127 - 5.128 - HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa); 5.129 - 5.130 - return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT)); 5.131 -} 5.132 - 5.133 - 5.134 - 5.135 -/* Translate guest virtual address to guest physical address. Specifically 5.136 - * for PAE mode guest. 5.137 - */ 5.138 -unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva) 5.139 -{ 5.140 -#if CONFIG_PAGING_LEVELS >= 3 5.141 - unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3); 5.142 - int mode = 3; /* three-level guest */ 5.143 - int lev, index; 5.144 - paddr_t gpa = 0; 5.145 - unsigned long gpfn, mfn; 5.146 - int success = 1; 5.147 - l1_pgentry_t *l1e; 5.148 - l2_pgentry_t *l2e; 5.149 - l3_pgentry_t *l3e; 5.150 - 5.151 - gpfn = (gcr3 >> PAGE_SHIFT); 5.152 - for ( lev = mode; lev >= 1; lev-- ) 5.153 - { 5.154 - mfn = get_mfn_from_gpfn(gpfn); 5.155 - if ( mfn == INVALID_MFN ) 5.156 - { 5.157 - HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 5.158 - lev); 5.159 - success = 0; 5.160 - break; 5.161 - } 5.162 - index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1); 5.163 - 5.164 - if ( lev == 3 ) 5.165 - { 5.166 - l3e = map_domain_page(mfn); 5.167 - index += ((gcr3 >> 5) & 127) * 4; 5.168 - if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) 5.169 - { 5.170 - HAP_PRINTK("Level 3 entry not present at index = %d\n", index); 5.171 - success = 0; 5.172 - } 5.173 - gpfn = l3e_get_pfn(l3e[index]); 5.174 - unmap_domain_page(l3e); 5.175 - } 5.176 - 5.177 - if ( lev == 2 ) 5.178 - { 5.179 - l2e = map_domain_page(mfn); 5.180 - if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) 5.181 - { 5.182 - HAP_PRINTK("Level 2 entry not present at index = %d\n", index); 5.183 - success = 0; 5.184 - } 5.185 - 5.186 - if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) 5.187 - { 5.188 - HAP_PRINTK("guest page table is PSE\n"); 5.189 - gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_2M_MASK) + 5.190 - (gva & ~PHYSICAL_PAGE_2M_MASK); 5.191 - unmap_domain_page(l2e); 5.192 - break; /* last level page table, jump out from here */ 5.193 - } 5.194 - 5.195 - gpfn = l2e_get_pfn(l2e[index]); 5.196 - unmap_domain_page(l2e); 5.197 - } 5.198 - 5.199 - if ( lev == 1 ) 5.200 - { 5.201 - l1e = map_domain_page(mfn); 5.202 - if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) 5.203 - { 5.204 - HAP_PRINTK("Level 1 entry not present at index = %d\n", index); 5.205 - success = 0; 5.206 - } 5.207 - gpfn = l1e_get_pfn(l1e[index]); 5.208 - gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) + 5.209 - (gva & ~PHYSICAL_PAGE_4K_MASK); 5.210 - unmap_domain_page(l1e); 5.211 - } 5.212 - 5.213 - if ( success != 1 ) /* error happened, jump out */ 5.214 - break; 5.215 - } 5.216 - 5.217 - gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */ 5.218 - HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa); 5.219 - 5.220 - return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT)); 5.221 -#else 5.222 - printk("guest paging level (3) is greater than host paging level!\n"); 5.223 - domain_crash(v->domain); 5.224 - return INVALID_GFN; 5.225 -#endif 5.226 -} 5.227 - 5.228 - 5.229 -/* Translate guest virtual address to guest physical address. Specifically 5.230 - * for long mode guest. 5.231 - */ 5.232 -unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva) 5.233 -{ 5.234 -#if CONFIG_PAGING_LEVELS == 4 5.235 - unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3); 5.236 - int mode = 4; /* four-level guest */ 5.237 - int lev, index; 5.238 - paddr_t gpa = 0; 5.239 - unsigned long gpfn, mfn; 5.240 - int success = 1; 5.241 - l4_pgentry_t *l4e; 5.242 - l3_pgentry_t *l3e; 5.243 - l2_pgentry_t *l2e; 5.244 - l1_pgentry_t *l1e; 5.245 - 5.246 - gpfn = (gcr3 >> PAGE_SHIFT); 5.247 - for ( lev = mode; lev >= 1; lev-- ) 5.248 - { 5.249 - mfn = get_mfn_from_gpfn(gpfn); 5.250 - if ( mfn == INVALID_MFN ) 5.251 - { 5.252 - HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 5.253 - lev); 5.254 - success = 0; 5.255 - break; 5.256 - } 5.257 - index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1); 5.258 - 5.259 - if ( lev == 4 ) 5.260 - { 5.261 - l4e = map_domain_page(mfn); 5.262 - if ( !(l4e_get_flags(l4e[index]) & _PAGE_PRESENT) ) 5.263 - { 5.264 - HAP_PRINTK("Level 4 entry not present at index = %d\n", index); 5.265 - success = 0; 5.266 - } 5.267 - gpfn = l4e_get_pfn(l4e[index]); 5.268 - unmap_domain_page(l4e); 5.269 - } 5.270 - 5.271 - if ( lev == 3 ) 5.272 - { 5.273 - l3e = map_domain_page(mfn); 5.274 - if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) 5.275 - { 5.276 - HAP_PRINTK("Level 3 entry not present at index = %d\n", index); 5.277 - success = 0; 5.278 - } 5.279 - gpfn = l3e_get_pfn(l3e[index]); 5.280 - unmap_domain_page(l3e); 5.281 - } 5.282 - 5.283 - if ( lev == 2 ) 5.284 - { 5.285 - l2e = map_domain_page(mfn); 5.286 - if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) 5.287 - { 5.288 - HAP_PRINTK("Level 2 entry not present at index = %d\n", index); 5.289 - success = 0; 5.290 - } 5.291 - 5.292 - if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) 5.293 - { 5.294 - HAP_PRINTK("guest page table is PSE\n"); 5.295 - gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_ADDR_2M_MASK_LM) 5.296 - + (gva & ~PHYSICAL_PAGE_2M_MASK); 5.297 - unmap_domain_page(l2e); 5.298 - break; /* last level page table, jump out from here */ 5.299 - } 5.300 - 5.301 - gpfn = l2e_get_pfn(l2e[index]); 5.302 - unmap_domain_page(l2e); 5.303 - } 5.304 - 5.305 - if ( lev == 1 ) 5.306 - { 5.307 - l1e = map_domain_page(mfn); 5.308 - if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) 5.309 - { 5.310 - HAP_PRINTK("Level 1 entry not present at index = %d\n", index); 5.311 - success = 0; 5.312 - } 5.313 - gpfn = l1e_get_pfn(l1e[index]); 5.314 - gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_ADDR_4K_MASK_LM) + 5.315 - (gva & ~PHYSICAL_PAGE_4K_MASK); 5.316 - unmap_domain_page(l1e); 5.317 - } 5.318 - 5.319 - if ( success != 1 ) /* error happened, jump out */ 5.320 - break; 5.321 - } 5.322 - 5.323 - gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */ 5.324 - HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa); 5.325 - 5.326 - return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT)); 5.327 -#else 5.328 - printk("guest paging level (4) is greater than host paging level!\n"); 5.329 - domain_crash(v->domain); 5.330 - return INVALID_GFN; 5.331 -#endif 5.332 -} 5.333 - 5.334 -/* 5.335 - * Local variables: 5.336 - * mode: C 5.337 - * c-set-style: "BSD" 5.338 - * c-basic-offset: 4 5.339 - * tab-width: 4 5.340 - * indent-tabs-mode: nil 5.341 - * End: 5.342 - */ 5.343 -