Skip to contentSkip to conversation

kvm: qemu: Enable EPT support for real mode

PATCH In review Yang, Sheng 2 participants 8 messages Apr 18, 2008 – Apr 24, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 6/6 kvm: qemu: Enable EPT support for real mode

From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
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.

---
 qemu/hw/pc.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
qemu/hw/pc.c +0 -0
index ae87ab9..dcb98c6 100644
@@ -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

From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
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.

---
 qemu/hw/pc.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
qemu/hw/pc.c +14 -0
index ae87ab9..dcb98c6 100644
@@ -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);
Signature · 1 line
1.5.4.5

-------------------------------------------------------------------------
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

_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

#1 lore raw
Quoted 9 lines · Sheng

From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
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.

Signature · 8 lines
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
#2 lore raw
Quoted 9 lines · On Tuesday 22 April 2008 18:16:41 Avi Kivity wrote:
Quoted 7 lines · Sheng

From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
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.

Quoted 6 lines

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 <[email protected]>
Date: Thu, 24 Apr 2008 14:23:50 +0800
Subject: [PATCH] KVM: VMX: Perpare a identity page table for EPT in real mode

---
 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(-)
arch/x86/kvm/vmx.c +68 -3
index 588b9ea..b19b2b2 100644
@@ -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(&current->mm->mmap_sem);
+	kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
+			VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT);
+	up_read(&current->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:

arch/x86/kvm/vmx.h +3 -0
index 8f662e3..469a107 100644
@@ -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
include/asm-x86/kvm_host.h +3 -0
index 003bc0e..69afbab 100644
@@ -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

From b1836738e82ed416c8fb43cffd85b3d17ab10260 Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
Date: Thu, 24 Apr 2008 14:23:50 +0800
Subject: [PATCH] KVM: VMX: Perpare a identity page table for EPT in real mode

---
 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(-)
arch/x86/kvm/vmx.c +72 -3

117 lines not on this page · raw message

arch/x86/kvm/vmx.h +3 -0
index 8f662e3..469a107 100644
@@ -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
include/asm-x86/kvm_host.h +3 -0
index 003bc0e..69afbab 100644
@@ -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 {
Signature · 1 line
1.5.4.5

-------------------------------------------------------------------------
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

_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

#3 lore raw
Quoted 20 lines · Sheng
Quoted 10 lines · On Tuesday 22 April 2008 18:16:41 Avi Kivity wrote:
Quoted 8 lines · Sheng

From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
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.

Quoted 7 lines

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.

Quoted 8 lines

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.

arch/x86/kvm/vmx.c out: · line 1714

Quoted 7 lines
arch/x86/kvm/vmx.c +5 -0
+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.

arch/x86/kvm/vmx.c out: · line 1725

Quoted 12 lines
arch/x86/kvm/vmx.c +11 -0
+
+	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/

arch/x86/kvm/vmx.c out: · line 1730

Quoted 6 lines
arch/x86/kvm/vmx.c +5 -0
+	 * 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.

Quoted 15 lines
arch/x86/kvm/vmx.c +14 -0
+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)

arch/x86/kvm/vmx.c out: · line 1798

Quoted 10 lines
arch/x86/kvm/vmx.c +10 -0
+		goto out;
+
+	down_read(&current->mm->mmap_sem);
+	kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
+			VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT);
+	up_read(&current->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?

Quoted 65 lines
arch/x86/kvm/vmx.c +15 -1
+
 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:

arch/x86/kvm/vmx.h +3 -0
index 8f662e3..469a107 100644
@@ -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
include/asm-x86/kvm_host.h +0 -0
index 003bc0e..69afbab 100644

include/asm-x86/kvm_host.h struct kvm_arch{ · line 319

Quoted 6 lines
include/asm-x86/kvm_host.h +3 -0
@@ -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?

Signature · 8 lines
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
#4 lore raw
Quoted 27 lines · On Thursday 24 April 2008 15:15:30 Avi Kivity wrote:
Quoted 17 lines · Sheng
Quoted 9 lines · On Tuesday 22 April 2008 18:16:41 Avi Kivity wrote:
Quoted 7 lines · Sheng

From 73c33765f3d879001818cd0719038c78a0c65561 Mon Sep 17 00:00:00 2001
From: Sheng Yang <[email protected]>
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.

Quoted 6 lines

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.

Quoted 6 lines

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.

Quoted 9 lines

arch/x86/kvm/vmx.c out: · line 1714

Quoted 5 lines
arch/x86/kvm/vmx.c +5 -0
+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...

Quoted 14 lines

arch/x86/kvm/vmx.c out: · line 1725

Quoted 11 lines
arch/x86/kvm/vmx.c +11 -0
+
+	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/

Quoted 9 lines

arch/x86/kvm/vmx.c out: · line 1730

Quoted 5 lines
arch/x86/kvm/vmx.c +5 -0
+	 * 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.

Quoted 18 lines
Quoted 18 lines
arch/x86/kvm/vmx.c +18 -0
+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(&current->mm->mmap_sem);
+	kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
Quoted 8 lines

arch/x86/kvm/vmx.c out: · line 1798

Quoted 6 lines
arch/x86/kvm/vmx.c +6 -0
+			VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT);
+	up_read(&current->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.

Quoted 67 lines
Quoted 67 lines
arch/x86/kvm/vmx.c +15 -1
+
 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:

arch/x86/kvm/vmx.h +3 -0
index 8f662e3..469a107 100644
@@ -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
include/asm-x86/kvm_host.h +0 -0
index 003bc0e..69afbab 100644
@@ -314,6 +314,9 @@ struct kvm_arch{
 	struct page *apic_access_page;
 
Quoted 7 lines

include/asm-x86/kvm_host.h struct kvm_arch{ · line 319

Quoted 4 lines
include/asm-x86/kvm_host.h +3 -0
 	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

#5 lore raw
Quoted 10 lines · Sheng
Quoted 3 lines

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.

Signature · 8 lines
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
#6 lore raw
Quoted 11 lines · On Thursday 24 April 2008 15:37:53 Avi Kivity wrote:
Quoted 9 lines · Sheng
Quoted 2 lines

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...

Quoted 3 lines

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...

Signature · 8 lines
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
#7 lore raw
Quoted 14 lines · Sheng
Quoted 12 lines · On Thursday 24 April 2008 15:37:53 Avi Kivity wrote:
Quoted 10 lines · Sheng
Quoted 3 lines

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...

Quoted 9 lines
Quoted 4 lines

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.

Signature · 8 lines
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