aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSheng Yang <sheng.yang@intel.com>2008-04-25 09:44:52 -0400
committerAvi Kivity <avi@qumranet.com>2008-05-04 07:44:41 -0400
commitb7ebfb0509692cd923e31650f81ed4d79c9a3e59 (patch)
treedef19d1472976c479287bc00384706e1e9fca461
parent0d15029895051904e31925ec63525cc3a637f7de (diff)
KVM: VMX: Prepare an identity page table for EPT in real mode
[aliguory: plug leak] Signed-off-by: Sheng Yang <sheng.yang@intel.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--arch/x86/kvm/vmx.c79
-rw-r--r--arch/x86/kvm/vmx.h3
-rw-r--r--arch/x86/kvm/x86.c2
-rw-r--r--include/asm-x86/kvm_host.h3
4 files changed, 84 insertions, 3 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 98e4f2b036de..de5f6150f2f7 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)
87 return container_of(vcpu, struct vcpu_vmx, vcpu); 87 return container_of(vcpu, struct vcpu_vmx, vcpu);
88} 88}
89 89
90static int init_rmode_tss(struct kvm *kvm); 90static int init_rmode(struct kvm *kvm);
91 91
92static DEFINE_PER_CPU(struct vmcs *, vmxarea); 92static DEFINE_PER_CPU(struct vmcs *, vmxarea);
93static DEFINE_PER_CPU(struct vmcs *, current_vmcs); 93static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
@@ -1304,7 +1304,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
1304 fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs); 1304 fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs);
1305 1305
1306 kvm_mmu_reset_context(vcpu); 1306 kvm_mmu_reset_context(vcpu);
1307 init_rmode_tss(vcpu->kvm); 1307 init_rmode(vcpu->kvm);
1308} 1308}
1309 1309
1310#ifdef CONFIG_X86_64 1310#ifdef CONFIG_X86_64
@@ -1578,6 +1578,41 @@ out:
1578 return ret; 1578 return ret;
1579} 1579}
1580 1580
1581static int init_rmode_identity_map(struct kvm *kvm)
1582{
1583 int i, r, ret;
1584 pfn_t identity_map_pfn;
1585 u32 tmp;
1586
1587 if (!vm_need_ept())
1588 return 1;
1589 if (unlikely(!kvm->arch.ept_identity_pagetable)) {
1590 printk(KERN_ERR "EPT: identity-mapping pagetable "
1591 "haven't been allocated!\n");
1592 return 0;
1593 }
1594 if (likely(kvm->arch.ept_identity_pagetable_done))
1595 return 1;
1596 ret = 0;
1597 identity_map_pfn = VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT;
1598 r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE);
1599 if (r < 0)
1600 goto out;
1601 /* Set up identity-mapping pagetable for EPT in real mode */
1602 for (i = 0; i < PT32_ENT_PER_PAGE; i++) {
1603 tmp = (i << 22) + (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |
1604 _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE);
1605 r = kvm_write_guest_page(kvm, identity_map_pfn,
1606 &tmp, i * sizeof(tmp), sizeof(tmp));
1607 if (r < 0)
1608 goto out;
1609 }
1610 kvm->arch.ept_identity_pagetable_done = true;
1611 ret = 1;
1612out:
1613 return ret;
1614}
1615
1581static void seg_setup(int seg) 1616static void seg_setup(int seg)
1582{ 1617{
1583 struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; 1618 struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -1612,6 +1647,31 @@ out:
1612 return r; 1647 return r;
1613} 1648}
1614 1649
1650static int alloc_identity_pagetable(struct kvm *kvm)
1651{
1652 struct kvm_userspace_memory_region kvm_userspace_mem;
1653 int r = 0;
1654
1655 down_write(&kvm->slots_lock);
1656 if (kvm->arch.ept_identity_pagetable)
1657 goto out;
1658 kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
1659 kvm_userspace_mem.flags = 0;
1660 kvm_userspace_mem.guest_phys_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR;
1661 kvm_userspace_mem.memory_size = PAGE_SIZE;
1662 r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0);
1663 if (r)
1664 goto out;
1665
1666 down_read(&current->mm->mmap_sem);
1667 kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
1668 VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT);
1669 up_read(&current->mm->mmap_sem);
1670out:
1671 up_write(&kvm->slots_lock);
1672 return r;
1673}
1674
1615static void allocate_vpid(struct vcpu_vmx *vmx) 1675static void allocate_vpid(struct vcpu_vmx *vmx)
1616{ 1676{
1617 int vpid; 1677 int vpid;
@@ -1775,6 +1835,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1775 return 0; 1835 return 0;
1776} 1836}
1777 1837
1838static int init_rmode(struct kvm *kvm)
1839{
1840 if (!init_rmode_tss(kvm))
1841 return 0;
1842 if (!init_rmode_identity_map(kvm))
1843 return 0;
1844 return 1;
1845}
1846
1778static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) 1847static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
1779{ 1848{
1780 struct vcpu_vmx *vmx = to_vmx(vcpu); 1849 struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -1782,7 +1851,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
1782 int ret; 1851 int ret;
1783 1852
1784 down_read(&vcpu->kvm->slots_lock); 1853 down_read(&vcpu->kvm->slots_lock);
1785 if (!init_rmode_tss(vmx->vcpu.kvm)) { 1854 if (!init_rmode(vmx->vcpu.kvm)) {
1786 ret = -ENOMEM; 1855 ret = -ENOMEM;
1787 goto out; 1856 goto out;
1788 } 1857 }
@@ -2759,6 +2828,10 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
2759 if (alloc_apic_access_page(kvm) != 0) 2828 if (alloc_apic_access_page(kvm) != 0)
2760 goto free_vmcs; 2829 goto free_vmcs;
2761 2830
2831 if (vm_need_ept())
2832 if (alloc_identity_pagetable(kvm) != 0)
2833 goto free_vmcs;
2834
2762 return &vmx->vcpu; 2835 return &vmx->vcpu;
2763 2836
2764free_vmcs: 2837free_vmcs:
diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h
index 093b085daf6a..f97eccc754e8 100644
--- a/arch/x86/kvm/vmx.h
+++ b/arch/x86/kvm/vmx.h
@@ -340,6 +340,7 @@ enum vmcs_field {
340#define MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED 0x4 340#define MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED 0x4
341 341
342#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9 342#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9
343#define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT 10
343 344
344#define VMX_NR_VPIDS (1 << 16) 345#define VMX_NR_VPIDS (1 << 16)
345#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1 346#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1
@@ -353,4 +354,6 @@ enum vmcs_field {
353#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26) 354#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)
354#define VMX_EPT_DEFAULT_GAW 3 355#define VMX_EPT_DEFAULT_GAW 3
355 356
357#define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul
358
356#endif 359#endif
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0735efbfa712..1842a86f7c33 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3909,6 +3909,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
3909 kvm_free_physmem(kvm); 3909 kvm_free_physmem(kvm);
3910 if (kvm->arch.apic_access_page) 3910 if (kvm->arch.apic_access_page)
3911 put_page(kvm->arch.apic_access_page); 3911 put_page(kvm->arch.apic_access_page);
3912 if (kvm->arch.ept_identity_pagetable)
3913 put_page(kvm->arch.ept_identity_pagetable);
3912 kfree(kvm); 3914 kfree(kvm);
3913} 3915}
3914 3916
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
index d1dedda958ff..e24afaa64a4d 100644
--- a/include/asm-x86/kvm_host.h
+++ b/include/asm-x86/kvm_host.h
@@ -314,6 +314,9 @@ struct kvm_arch{
314 struct page *apic_access_page; 314 struct page *apic_access_page;
315 315
316 gpa_t wall_clock; 316 gpa_t wall_clock;
317
318 struct page *ept_identity_pagetable;
319 bool ept_identity_pagetable_done;
317}; 320};
318 321
319struct kvm_vm_stat { 322struct kvm_vm_stat {