* [PATCH 6/6] kvm: qemu: Enable EPT support for real mode @ 2008-04-18 9:30 Yang, Sheng 2008-04-22 10:16 ` Avi Kivity 0 siblings, 1 reply; 8+ messages in thread From: Yang, Sheng @ 2008-04-18 9:30 UTC (permalink / raw) To: kvm-devel [-- Attachment #1: Type: text/plain, Size: 1592 bytes --] From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001 From: Sheng Yang <sheng.yang@intel.com> 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. Signed-off-by: Sheng Yang <sheng.yang@intel.com> --- qemu/hw/pc.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c index ae87ab9..dcb98c6 100644 --- a/qemu/hw/pc.c +++ b/qemu/hw/pc.c @@ -780,6 +780,9 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, int index; BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BlockDriverState *fd[MAX_FD]; +#ifdef USE_KVM + uint32_t *table_items; +#endif if (ram_size >= 0xe0000000 ) { above_4g_mem_size = ram_size - 0xe0000000; @@ -857,6 +860,17 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, exit(1); } +#ifdef USE_KVM + if (kvm_allowed) { + /* set up identity map for EPT at the last page of VGA BIOS region. + * 0xe7 = _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | + * _PAGE_DIRTY | _PAGE_PSE */ + table_items = (void *)(phys_ram_base + vga_bios_offset + 0xf000); + for (i = 0; i < 1024; i++) + table_items[i] = (i << 22) + 0xe7; + } +#endif + /* above 4giga memory allocation */ if (above_4g_mem_size > 0) { ram_addr = qemu_ram_alloc(above_4g_mem_size); -- 1.5.4.5 [-- Attachment #2: 0001-kvm-qemu-Enable-EPT-support-for-real-mode.patch --] [-- Type: text/x-diff, Size: 1590 bytes --] From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001 From: Sheng Yang <sheng.yang@intel.com> 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. Signed-off-by: Sheng Yang <sheng.yang@intel.com> --- qemu/hw/pc.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c index ae87ab9..dcb98c6 100644 --- a/qemu/hw/pc.c +++ b/qemu/hw/pc.c @@ -780,6 +780,9 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, int index; BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BlockDriverState *fd[MAX_FD]; +#ifdef USE_KVM + uint32_t *table_items; +#endif if (ram_size >= 0xe0000000 ) { above_4g_mem_size = ram_size - 0xe0000000; @@ -857,6 +860,17 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, exit(1); } +#ifdef USE_KVM + if (kvm_allowed) { + /* set up identity map for EPT at the last page of VGA BIOS region. + * 0xe7 = _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | + * _PAGE_DIRTY | _PAGE_PSE */ + table_items = (void *)(phys_ram_base + vga_bios_offset + 0xf000); + for (i = 0; i < 1024; i++) + table_items[i] = (i << 22) + 0xe7; + } +#endif + /* above 4giga memory allocation */ if (above_4g_mem_size > 0) { ram_addr = qemu_ram_alloc(above_4g_mem_size); -- 1.5.4.5 [-- Attachment #3: Type: text/plain, Size: 320 bytes --] ------------------------------------------------------------------------- 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 [-- Attachment #4: Type: text/plain, Size: 158 bytes --] _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 6/6] kvm: qemu: Enable EPT support for real mode 2008-04-18 9:30 [PATCH 6/6] kvm: qemu: Enable EPT support for real mode Yang, Sheng @ 2008-04-22 10:16 ` Avi Kivity 2008-04-24 6:59 ` Yang, Sheng 0 siblings, 1 reply; 8+ messages in thread From: Avi Kivity @ 2008-04-22 10:16 UTC (permalink / raw) To: Yang, Sheng; +Cc: kvm-devel Yang, Sheng wrote: > From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001 > From: Sheng Yang <sheng.yang@intel.com> > 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. -- error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- 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 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 6/6] kvm: qemu: Enable EPT support for real mode 2008-04-22 10:16 ` Avi Kivity @ 2008-04-24 6:59 ` Yang, Sheng 2008-04-24 7:15 ` Avi Kivity 0 siblings, 1 reply; 8+ messages in thread From: Yang, Sheng @ 2008-04-24 6:59 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel [-- Attachment #1: Type: text/plain, Size: 6016 bytes --] 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 <sheng.yang@intel.com> > > 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 not very elegant... Too complex compared to the qemu one. BTW: The S/R and live migration problem was fixed. From b1836738e82ed416c8fb43cffd85b3d17ab10260 Mon Sep 17 00:00:00 2001 From: Sheng Yang <sheng.yang@intel.com> Date: Thu, 24 Apr 2008 14:23:50 +0800 Subject: [PATCH] KVM: VMX: Perpare a identity page table for EPT in real mode Signed-off-by: Sheng Yang <sheng.yang@intel.com> --- 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 --- 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 *vcpu) return container_of(vcpu, struct vcpu_vmx, vcpu); } -static 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); - 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 = 0; + identity_map_pfn = VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT; + r = 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 = _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | + * _PAGE_DIRTY | _PAGE_PSE + */ + for (i = 0; i < PT32_ENT_PER_PAGE; i++) + table[i] = (i << 22) + 0xe7; + r = kvm_write_guest_page(kvm, identity_map_pfn, + table, 0, PAGE_SIZE); + if (r < 0) + goto out; + kvm->arch.ept_identity_pagetable_done = true; + ret = 1; +out: + return ret; +} + static void seg_setup(int seg) { struct kvm_vmx_segment_field *sf = &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 = 0; + + down_write(&kvm->slots_lock); + if (kvm->arch.ept_identity_pagetable) + goto out; + kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; + kvm_userspace_mem.flags = 0; + kvm_userspace_mem.guest_phys_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR; + kvm_userspace_mem.memory_size = PAGE_SIZE; + r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0); + if (r) + goto out; + + down_read(¤t->mm->mmap_sem); + kvm->arch.ept_identity_pagetable = 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 = to_vmx(vcpu); @@ -1911,7 +1976,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) int ret; down_read(&vcpu->kvm->slots_lock); - if (!init_rmode_tss(vmx->vcpu.kvm)) { + if (!init_rmode(vmx->vcpu.kvm)) { ret = -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) != 0) goto free_vmcs; + if (vm_need_ept()) + if (alloc_identity_pagetable(kvm) != 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 --- 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 --- 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 { -- 1.5.4.5 [-- Attachment #2: 0001-KVM-VMX-Perpare-a-identity-page-table-for-EPT-in-r.patch --] [-- Type: text/x-diff, Size: 5005 bytes --] From b1836738e82ed416c8fb43cffd85b3d17ab10260 Mon Sep 17 00:00:00 2001 From: Sheng Yang <sheng.yang@intel.com> Date: Thu, 24 Apr 2008 14:23:50 +0800 Subject: [PATCH] KVM: VMX: Perpare a identity page table for EPT in real mode Signed-off-by: Sheng Yang <sheng.yang@intel.com> --- 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 --- 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 *vcpu) return container_of(vcpu, struct vcpu_vmx, vcpu); } -static 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); - 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 = 0; + identity_map_pfn = VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT; + r = 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 = _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | + * _PAGE_DIRTY | _PAGE_PSE + */ + for (i = 0; i < PT32_ENT_PER_PAGE; i++) + table[i] = (i << 22) + 0xe7; + r = kvm_write_guest_page(kvm, identity_map_pfn, + table, 0, PAGE_SIZE); + if (r < 0) + goto out; + kvm->arch.ept_identity_pagetable_done = true; + ret = 1; +out: + return ret; +} + static void seg_setup(int seg) { struct kvm_vmx_segment_field *sf = &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 = 0; + + down_write(&kvm->slots_lock); + if (kvm->arch.ept_identity_pagetable) + goto out; + kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; + kvm_userspace_mem.flags = 0; + kvm_userspace_mem.guest_phys_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR; + kvm_userspace_mem.memory_size = PAGE_SIZE; + r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0); + if (r) + goto out; + + down_read(¤t->mm->mmap_sem); + kvm->arch.ept_identity_pagetable = 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 = to_vmx(vcpu); @@ -1911,7 +1976,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) int ret; down_read(&vcpu->kvm->slots_lock); - if (!init_rmode_tss(vmx->vcpu.kvm)) { + if (!init_rmode(vmx->vcpu.kvm)) { ret = -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) != 0) goto free_vmcs; + if (vm_need_ept()) + if (alloc_identity_pagetable(kvm) != 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 --- 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 --- 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 { -- 1.5.4.5 [-- Attachment #3: Type: text/plain, Size: 320 bytes --] ------------------------------------------------------------------------- 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 [-- Attachment #4: Type: text/plain, Size: 158 bytes --] _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 6/6] kvm: qemu: Enable EPT support for real mode 2008-04-24 6:59 ` Yang, Sheng @ 2008-04-24 7:15 ` Avi Kivity 2008-04-24 7:29 ` Yang, Sheng 0 siblings, 1 reply; 8+ messages in thread From: Avi Kivity @ 2008-04-24 7:15 UTC (permalink / raw) To: Yang, Sheng; +Cc: kvm-devel Yang, Sheng wrote: > 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 <sheng.yang@intel.com> >>> 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 > not very elegant... Too complex compared to the qemu one. > > BTW: The S/R and live migration problem was fixed. > > Ah, good. > > +static int init_rmode_identity_map(struct kvm *kvm) > +{ > + int i, r, ret; > + pfn_t identity_map_pfn; > + u32 table[PT32_ENT_PER_PAGE]; > That's 4KB. On i386 with 4K stacks, this may cause a stack overflow. Even with 8K stacks you're on thin ice here, with the temperature rapidly rising. > + > + if (kvm->arch.ept_identity_pagetable_done) > + return 1; > + ret = 0; > + identity_map_pfn = VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT; > + r = 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 > s/contain/contents/ > + * 0xe7 = _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | > + * _PAGE_DIRTY | _PAGE_PSE > + */ > + for (i = 0; i < PT32_ENT_PER_PAGE; i++) > + table[i] = (i << 22) + 0xe7; > Instead of the comment, you can put the identifiers into the code instead of 0xe7. And, to avoid the stack overflow, simply use kvm_write_guest() here. > +static int alloc_identity_pagetable(struct kvm *kvm) > +{ > + struct kvm_userspace_memory_region kvm_userspace_mem; > + int r = 0; > + > + down_write(&kvm->slots_lock); > + if (kvm->arch.ept_identity_pagetable) > + goto out; > + kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; > + kvm_userspace_mem.flags = 0; > + kvm_userspace_mem.guest_phys_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR; > + kvm_userspace_mem.memory_size = PAGE_SIZE; > + r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0); > + if (r) > + goto out; > + > + down_read(¤t->mm->mmap_sem); > + kvm->arch.ept_identity_pagetable = 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; > +} > There's already a memslot for the tss, no? Why not expand it by a page? > + > 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 = to_vmx(vcpu); > @@ -1911,7 +1976,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) > int ret; > > down_read(&vcpu->kvm->slots_lock); > - if (!init_rmode_tss(vmx->vcpu.kvm)) { > + if (!init_rmode(vmx->vcpu.kvm)) { > ret = -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) != 0) > goto free_vmcs; > > + if (vm_need_ept()) > + if (alloc_identity_pagetable(kvm) != 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 > --- 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 > --- 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; Why not use ept_identity_pagetable != NULL to encode ept_identity_pagetable_done? -- error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- 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 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 6/6] kvm: qemu: Enable EPT support for real mode 2008-04-24 7:15 ` Avi Kivity @ 2008-04-24 7:29 ` Yang, Sheng 2008-04-24 7:37 ` Avi Kivity 0 siblings, 1 reply; 8+ messages in thread From: Yang, Sheng @ 2008-04-24 7:29 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel On Thursday 24 April 2008 15:15:30 Avi Kivity wrote: > Yang, Sheng wrote: > > 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 <sheng.yang@intel.com> > >>> 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 not very elegant... Too complex compared to the qemu one. > > > > BTW: The S/R and live migration problem was fixed. > > Ah, good. > > > +static int init_rmode_identity_map(struct kvm *kvm) > > +{ > > + int i, r, ret; > > + pfn_t identity_map_pfn; > > + u32 table[PT32_ENT_PER_PAGE]; > > That's 4KB. On i386 with 4K stacks, this may cause a stack overflow. > Even with 8K stacks you're on thin ice here, with the temperature > rapidly rising. Oops... I forgot that... > > + > > + if (kvm->arch.ept_identity_pagetable_done) > > + return 1; > > + ret = 0; > > + identity_map_pfn = VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT; > > + r = 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 > > s/contain/contents/ > > > + * 0xe7 = _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | > > + * _PAGE_DIRTY | _PAGE_PSE > > + */ > > + for (i = 0; i < PT32_ENT_PER_PAGE; i++) > > + table[i] = (i << 22) + 0xe7; > > Instead of the comment, you can put the identifiers into the code > instead of 0xe7. And, to avoid the stack overflow, simply use > kvm_write_guest() here. OK. > > +static int alloc_identity_pagetable(struct kvm *kvm) > > +{ > > + struct kvm_userspace_memory_region kvm_userspace_mem; > > + int r = 0; > > + > > + down_write(&kvm->slots_lock); > > + if (kvm->arch.ept_identity_pagetable) > > + goto out; > > + kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; > > + kvm_userspace_mem.flags = 0; > > + kvm_userspace_mem.guest_phys_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR; > > + kvm_userspace_mem.memory_size = PAGE_SIZE; > > + r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0); > > + if (r) > > + goto out; > > + > > + down_read(¤t->mm->mmap_sem); > > + kvm->arch.ept_identity_pagetable = 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; > > +} > > There's already a memslot for the tss, no? Why not expand it by a page? Agree. > > + > > 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 = to_vmx(vcpu); > > @@ -1911,7 +1976,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) > > int ret; > > > > down_read(&vcpu->kvm->slots_lock); > > - if (!init_rmode_tss(vmx->vcpu.kvm)) { > > + if (!init_rmode(vmx->vcpu.kvm)) { > > ret = -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) != 0) > > goto free_vmcs; > > > > + if (vm_need_ept()) > > + if (alloc_identity_pagetable(kvm) != 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 > > --- 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 > > --- 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; > > Why not use ept_identity_pagetable != NULL to encode > ept_identity_pagetable_done? ept_identity_pagetable_done was used to indicate if the pagetable was setted up, and ept_identity_pagetable was used to indicate if the page used for pagetable was allocated... I don't want to run alloc_identity_pagetable() again and again and again... Another method is read several bits at the front of page to tell if the pagetable was setted up, but somehow tricky... ------------------------------------------------------------------------- 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 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 6/6] kvm: qemu: Enable EPT support for real mode 2008-04-24 7:29 ` Yang, Sheng @ 2008-04-24 7:37 ` Avi Kivity 2008-04-24 7:57 ` Yang, Sheng 0 siblings, 1 reply; 8+ messages in thread From: Avi Kivity @ 2008-04-24 7:37 UTC (permalink / raw) To: Yang, Sheng; +Cc: kvm-devel Yang, Sheng wrote: >> Why not use ept_identity_pagetable != NULL to encode >> ept_identity_pagetable_done? >> > > ept_identity_pagetable_done was used to indicate if the pagetable was setted > up, and ept_identity_pagetable was used to indicate if the page used for > pagetable was allocated... I don't want to run alloc_identity_pagetable() > again and again and again... Another method is read several bits at the front > of page to tell if the pagetable was setted up, but somehow tricky... > No, better to avoid tricks. But rmode_tss is only allocated once, so if you unify the allocations, the identity table will also only be allocated once. -- error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- 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 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 6/6] kvm: qemu: Enable EPT support for real mode 2008-04-24 7:37 ` Avi Kivity @ 2008-04-24 7:57 ` Yang, Sheng 2008-04-24 7:59 ` Avi Kivity 0 siblings, 1 reply; 8+ messages in thread From: Yang, Sheng @ 2008-04-24 7:57 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel On Thursday 24 April 2008 15:37:53 Avi Kivity wrote: > Yang, Sheng wrote: > >> Why not use ept_identity_pagetable != NULL to encode > >> ept_identity_pagetable_done? > > > > ept_identity_pagetable_done was used to indicate if the pagetable was > > setted up, and ept_identity_pagetable was used to indicate if the page > > used for pagetable was allocated... I don't want to run > > alloc_identity_pagetable() again and again and again... Another method is > > read several bits at the front of page to tell if the pagetable was > > setted up, but somehow tricky... > > No, better to avoid tricks. But rmode_tss is only allocated once, so if > you unify the allocations, the identity table will also only be > allocated once. But set_tss_addr() is a x86_ops, if the identity mapping allocation using the same approach, another null function should be added into SVM side, but this thing is VMX specific one... -- Thanks Yang, Sheng ------------------------------------------------------------------------- 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 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 6/6] kvm: qemu: Enable EPT support for real mode 2008-04-24 7:57 ` Yang, Sheng @ 2008-04-24 7:59 ` Avi Kivity 0 siblings, 0 replies; 8+ messages in thread From: Avi Kivity @ 2008-04-24 7:59 UTC (permalink / raw) To: Yang, Sheng; +Cc: kvm-devel Yang, Sheng wrote: > On Thursday 24 April 2008 15:37:53 Avi Kivity wrote: > >> Yang, Sheng wrote: >> >>>> Why not use ept_identity_pagetable != NULL to encode >>>> ept_identity_pagetable_done? >>>> >>> ept_identity_pagetable_done was used to indicate if the pagetable was >>> setted up, and ept_identity_pagetable was used to indicate if the page >>> used for pagetable was allocated... I don't want to run >>> alloc_identity_pagetable() again and again and again... Another method is >>> read several bits at the front of page to tell if the pagetable was >>> setted up, but somehow tricky... >>> >> No, better to avoid tricks. But rmode_tss is only allocated once, so if >> you unify the allocations, the identity table will also only be >> allocated once. >> > > But set_tss_addr() is a x86_ops, if the identity mapping allocation using the > same approach, another null function should be added into SVM side, but this > thing is VMX specific one... > We could rename set_tss_addr() to mean set_tss_and_ept_identity_pt_addr(), but it looks like the ioctl expects just three pages... so let's keep the flag for now. -- error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- 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 ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-04-24 7:59 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-04-18 9:30 [PATCH 6/6] kvm: qemu: Enable EPT support for real mode Yang, Sheng 2008-04-22 10:16 ` Avi Kivity 2008-04-24 6:59 ` Yang, Sheng 2008-04-24 7:15 ` Avi Kivity 2008-04-24 7:29 ` Yang, Sheng 2008-04-24 7:37 ` Avi Kivity 2008-04-24 7:57 ` Yang, Sheng 2008-04-24 7:59 ` Avi Kivity
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox