From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Yang, Sheng" Subject: Re: [PATCH 6/6] kvm: qemu: Enable EPT support for real mode Date: Thu, 24 Apr 2008 14:59:09 +0800 Message-ID: <200804241459.09523.sheng.yang@intel.com> References: <200804181730.16318.sheng.yang@intel.com> <480DBB09.5070801@qumranet.com> Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_9+CEIO5iGAwKqrO" Cc: kvm-devel@lists.sourceforge.net To: Avi Kivity Return-path: In-Reply-To: <480DBB09.5070801@qumranet.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kvm-devel-bounces@lists.sourceforge.net Errors-To: kvm-devel-bounces@lists.sourceforge.net List-Id: kvm.vger.kernel.org --Boundary-00=_9+CEIO5iGAwKqrO Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On Tuesday 22 April 2008 18:16:41 Avi Kivity wrote: > Yang, Sheng wrote: > > From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001 > > From: Sheng Yang > > Date: Fri, 18 Apr 2008 17:15:39 +0800 > > Subject: [PATCH] kvm: qemu: Enable EPT support for real mode > > > > This patch build a identity page table on the last page of VGA bios, and > > use it as the guest page table in nonpaging mode for EPT. > > Doing this in qemu means older versions of qemu can't work with an > ept-enabled kernel. Also, placing the table in the vga bios might > conflict with video card assignment to a guest. > > Suggest placing this near the realmode tss (see vmx.c:init_rmode_tss()) > which serves a similar function. Something like this? (along with one page reserved in e820 table) I put the page it into 0xfffbc000 now. But I think the following implement = is=20 not very elegant... Too complex compared to the qemu one. BTW: The S/R and live migration problem was fixed. =46rom b1836738e82ed416c8fb43cffd85b3d17ab10260 Mon Sep 17 00:00:00 2001 =46rom: Sheng Yang Date: Thu, 24 Apr 2008 14:23:50 +0800 Subject: [PATCH] KVM: VMX: Perpare a identity page table for EPT in real mo= de Signed-off-by: Sheng Yang =2D-- arch/x86/kvm/vmx.c | 75=20 ++++++++++++++++++++++++++++++++++++++++++-- arch/x86/kvm/vmx.h | 3 ++ include/asm-x86/kvm_host.h | 3 ++ 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 588b9ea..b19b2b2 100644 =2D-- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -87,7 +87,7 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vc= pu) return container_of(vcpu, struct vcpu_vmx, vcpu); } =2Dstatic int init_rmode_tss(struct kvm *kvm); +static int init_rmode(struct kvm *kvm); static DEFINE_PER_CPU(struct vmcs *, vmxarea); static DEFINE_PER_CPU(struct vmcs *, current_vmcs); @@ -1345,7 +1345,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu) fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs); kvm_mmu_reset_context(vcpu); =2D init_rmode_tss(vcpu->kvm); + init_rmode(vcpu->kvm); } #ifdef CONFIG_X86_64 @@ -1707,6 +1707,37 @@ out: return ret; } +static int init_rmode_identity_map(struct kvm *kvm) +{ + int i, r, ret; + pfn_t identity_map_pfn; + u32 table[PT32_ENT_PER_PAGE]; + + if (kvm->arch.ept_identity_pagetable_done) + return 1; + ret =3D 0; + identity_map_pfn =3D VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT; + r =3D kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE); + if (r < 0) + goto out; + /* + * Set up identity-mapping pagetable for EPT in real mode, also verify + * the contain of page + * 0xe7 =3D _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | + * _PAGE_DIRTY | _PAGE_PSE + */ + for (i =3D 0; i < PT32_ENT_PER_PAGE; i++) + table[i] =3D (i << 22) + 0xe7; + r =3D kvm_write_guest_page(kvm, identity_map_pfn, + table, 0, PAGE_SIZE); + if (r < 0) + goto out; + kvm->arch.ept_identity_pagetable_done =3D true; + ret =3D 1; +out: + return ret; +} + static void seg_setup(int seg) { struct kvm_vmx_segment_field *sf =3D &kvm_vmx_segment_fields[seg]; @@ -1741,6 +1772,31 @@ out: return r; } +static int alloc_identity_pagetable(struct kvm *kvm) +{ + struct kvm_userspace_memory_region kvm_userspace_mem; + int r =3D 0; + + down_write(&kvm->slots_lock); + if (kvm->arch.ept_identity_pagetable) + goto out; + kvm_userspace_mem.slot =3D IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; + kvm_userspace_mem.flags =3D 0; + kvm_userspace_mem.guest_phys_addr =3D VMX_EPT_IDENTITY_PAGETABLE_ADDR; + kvm_userspace_mem.memory_size =3D PAGE_SIZE; + r =3D __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0); + if (r) + goto out; + + down_read(¤t->mm->mmap_sem); + kvm->arch.ept_identity_pagetable =3D gfn_to_page(kvm, + VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT); + up_read(¤t->mm->mmap_sem); +out: + up_write(&kvm->slots_lock); + return r; +} + static void allocate_vpid(struct vcpu_vmx *vmx) { int vpid; @@ -1904,6 +1960,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) return 0; } +static int init_rmode(struct kvm *kvm) +{ + if (!init_rmode_tss(kvm)) + return 0; + if (!init_rmode_identity_map(kvm)) + return 0; + return 1; +} + static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); @@ -1911,7 +1976,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) int ret; down_read(&vcpu->kvm->slots_lock); =2D if (!init_rmode_tss(vmx->vcpu.kvm)) { + if (!init_rmode(vmx->vcpu.kvm)) { ret =3D -ENOMEM; goto out; } @@ -2967,6 +3032,10 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm=20 *kvm, unsigned int id) if (alloc_apic_access_page(kvm) !=3D 0) goto free_vmcs; + if (vm_need_ept()) + if (alloc_identity_pagetable(kvm) !=3D 0) + goto free_vmcs; + return &vmx->vcpu; free_vmcs: diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h index 8f662e3..469a107 100644 =2D-- a/arch/x86/kvm/vmx.h +++ b/arch/x86/kvm/vmx.h @@ -340,6 +340,7 @@ enum vmcs_field { #define MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED 0x4 #define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9 +#define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT 10 #define VMX_NR_VPIDS (1 << 16) #define VMX_VPID_EXTENT_SINGLE_CONTEXT 1 @@ -362,4 +363,6 @@ enum vmcs_field { #define VMX_EPT_FAKE_ACCESSED_MASK (1ul << 62) #define VMX_EPT_FAKE_DIRTY_MASK (1ul << 63) +#define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul + #endif diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 003bc0e..69afbab 100644 =2D-- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -314,6 +314,9 @@ struct kvm_arch{ struct page *apic_access_page; gpa_t wall_clock; + + struct page *ept_identity_pagetable; + bool ept_identity_pagetable_done; }; struct kvm_vm_stat { =2D- 1.5.4.5 --Boundary-00=_9+CEIO5iGAwKqrO Content-Type: text/x-diff; charset="iso-8859-1"; name="0001-KVM-VMX-Perpare-a-identity-page-table-for-EPT-in-r.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-KVM-VMX-Perpare-a-identity-page-table-for-EPT-in-r.patch" =46rom b1836738e82ed416c8fb43cffd85b3d17ab10260 Mon Sep 17 00:00:00 2001 =46rom: Sheng Yang Date: Thu, 24 Apr 2008 14:23:50 +0800 Subject: [PATCH] KVM: VMX: Perpare a identity page table for EPT in real mo= de Signed-off-by: Sheng Yang =2D-- arch/x86/kvm/vmx.c | 75 ++++++++++++++++++++++++++++++++++++++++= ++-- arch/x86/kvm/vmx.h | 3 ++ include/asm-x86/kvm_host.h | 3 ++ 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 588b9ea..b19b2b2 100644 =2D-- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -87,7 +87,7 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vc= pu) return container_of(vcpu, struct vcpu_vmx, vcpu); } =20 =2Dstatic int init_rmode_tss(struct kvm *kvm); +static int init_rmode(struct kvm *kvm); =20 static DEFINE_PER_CPU(struct vmcs *, vmxarea); static DEFINE_PER_CPU(struct vmcs *, current_vmcs); @@ -1345,7 +1345,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu) fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs); =20 kvm_mmu_reset_context(vcpu); =2D init_rmode_tss(vcpu->kvm); + init_rmode(vcpu->kvm); } =20 #ifdef CONFIG_X86_64 @@ -1707,6 +1707,37 @@ out: return ret; } =20 +static int init_rmode_identity_map(struct kvm *kvm) +{ + int i, r, ret; + pfn_t identity_map_pfn; + u32 table[PT32_ENT_PER_PAGE]; + + if (kvm->arch.ept_identity_pagetable_done) + return 1; + ret =3D 0; + identity_map_pfn =3D VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT; + r =3D kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE); + if (r < 0) + goto out; + /* + * Set up identity-mapping pagetable for EPT in real mode, also verify + * the contain of page + * 0xe7 =3D _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | + * _PAGE_DIRTY | _PAGE_PSE + */ + for (i =3D 0; i < PT32_ENT_PER_PAGE; i++) + table[i] =3D (i << 22) + 0xe7; + r =3D kvm_write_guest_page(kvm, identity_map_pfn, + table, 0, PAGE_SIZE); + if (r < 0) + goto out; + kvm->arch.ept_identity_pagetable_done =3D true; + ret =3D 1; +out: + return ret; +} + static void seg_setup(int seg) { struct kvm_vmx_segment_field *sf =3D &kvm_vmx_segment_fields[seg]; @@ -1741,6 +1772,31 @@ out: return r; } =20 +static int alloc_identity_pagetable(struct kvm *kvm) +{ + struct kvm_userspace_memory_region kvm_userspace_mem; + int r =3D 0; + + down_write(&kvm->slots_lock); + if (kvm->arch.ept_identity_pagetable) + goto out; + kvm_userspace_mem.slot =3D IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; + kvm_userspace_mem.flags =3D 0; + kvm_userspace_mem.guest_phys_addr =3D VMX_EPT_IDENTITY_PAGETABLE_ADDR; + kvm_userspace_mem.memory_size =3D PAGE_SIZE; + r =3D __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0); + if (r) + goto out; + + down_read(¤t->mm->mmap_sem); + kvm->arch.ept_identity_pagetable =3D gfn_to_page(kvm, + VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT); + up_read(¤t->mm->mmap_sem); +out: + up_write(&kvm->slots_lock); + return r; +} + static void allocate_vpid(struct vcpu_vmx *vmx) { int vpid; @@ -1904,6 +1960,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) return 0; } =20 +static int init_rmode(struct kvm *kvm) +{ + if (!init_rmode_tss(kvm)) + return 0; + if (!init_rmode_identity_map(kvm)) + return 0; + return 1; +} + static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx =3D to_vmx(vcpu); @@ -1911,7 +1976,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) int ret; =20 down_read(&vcpu->kvm->slots_lock); =2D if (!init_rmode_tss(vmx->vcpu.kvm)) { + if (!init_rmode(vmx->vcpu.kvm)) { ret =3D -ENOMEM; goto out; } @@ -2967,6 +3032,10 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *= kvm, unsigned int id) if (alloc_apic_access_page(kvm) !=3D 0) goto free_vmcs; =20 + if (vm_need_ept()) + if (alloc_identity_pagetable(kvm) !=3D 0) + goto free_vmcs; + return &vmx->vcpu; =20 free_vmcs: diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h index 8f662e3..469a107 100644 =2D-- a/arch/x86/kvm/vmx.h +++ b/arch/x86/kvm/vmx.h @@ -340,6 +340,7 @@ enum vmcs_field { #define MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED 0x4 =20 #define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9 +#define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT 10 =20 #define VMX_NR_VPIDS (1 << 16) #define VMX_VPID_EXTENT_SINGLE_CONTEXT 1 @@ -362,4 +363,6 @@ enum vmcs_field { #define VMX_EPT_FAKE_ACCESSED_MASK (1ul << 62) #define VMX_EPT_FAKE_DIRTY_MASK (1ul << 63) =20 +#define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul + #endif diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 003bc0e..69afbab 100644 =2D-- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -314,6 +314,9 @@ struct kvm_arch{ struct page *apic_access_page; =20 gpa_t wall_clock; + + struct page *ept_identity_pagetable; + bool ept_identity_pagetable_done; }; =20 struct kvm_vm_stat { =2D-=20 1.5.4.5 --Boundary-00=_9+CEIO5iGAwKqrO Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone --Boundary-00=_9+CEIO5iGAwKqrO Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel --Boundary-00=_9+CEIO5iGAwKqrO--