aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2009-07-20 22:42:48 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:33:16 -0400
commitb927a3cec081a605142f5b7e90b730611bee28b1 (patch)
treeed7609e83e89c0830d568aa8304200cdb0c58736
parentb792c344dfd57ee2cf737440e4a9b4a5bc39d1db (diff)
KVM: VMX: Introduce KVM_SET_IDENTITY_MAP_ADDR ioctl
Now KVM allow guest to modify guest's physical address of EPT's identity mapping page. (change from v1, discard unnecessary check, change ioctl to accept parameter address rather than value) Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/kvm/vmx.c15
-rw-r--r--arch/x86/kvm/x86.c19
-rw-r--r--include/linux/kvm.h2
4 files changed, 32 insertions, 5 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 08732d7b6d98..e210b218df44 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -411,6 +411,7 @@ struct kvm_arch{
411 411
412 struct page *ept_identity_pagetable; 412 struct page *ept_identity_pagetable;
413 bool ept_identity_pagetable_done; 413 bool ept_identity_pagetable_done;
414 gpa_t ept_identity_map_addr;
414 415
415 unsigned long irq_sources_bitmap; 416 unsigned long irq_sources_bitmap;
416 unsigned long irq_states[KVM_IOAPIC_NUM_PINS]; 417 unsigned long irq_states[KVM_IOAPIC_NUM_PINS];
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index c6256b98f078..686e1abb6816 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1719,7 +1719,7 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
1719 eptp = construct_eptp(cr3); 1719 eptp = construct_eptp(cr3);
1720 vmcs_write64(EPT_POINTER, eptp); 1720 vmcs_write64(EPT_POINTER, eptp);
1721 guest_cr3 = is_paging(vcpu) ? vcpu->arch.cr3 : 1721 guest_cr3 = is_paging(vcpu) ? vcpu->arch.cr3 :
1722 VMX_EPT_IDENTITY_PAGETABLE_ADDR; 1722 vcpu->kvm->arch.ept_identity_map_addr;
1723 } 1723 }
1724 1724
1725 vmx_flush_tlb(vcpu); 1725 vmx_flush_tlb(vcpu);
@@ -2122,7 +2122,7 @@ static int init_rmode_identity_map(struct kvm *kvm)
2122 if (likely(kvm->arch.ept_identity_pagetable_done)) 2122 if (likely(kvm->arch.ept_identity_pagetable_done))
2123 return 1; 2123 return 1;
2124 ret = 0; 2124 ret = 0;
2125 identity_map_pfn = VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT; 2125 identity_map_pfn = kvm->arch.ept_identity_map_addr >> PAGE_SHIFT;
2126 r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE); 2126 r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE);
2127 if (r < 0) 2127 if (r < 0)
2128 goto out; 2128 goto out;
@@ -2191,14 +2191,15 @@ static int alloc_identity_pagetable(struct kvm *kvm)
2191 goto out; 2191 goto out;
2192 kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; 2192 kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
2193 kvm_userspace_mem.flags = 0; 2193 kvm_userspace_mem.flags = 0;
2194 kvm_userspace_mem.guest_phys_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR; 2194 kvm_userspace_mem.guest_phys_addr =
2195 kvm->arch.ept_identity_map_addr;
2195 kvm_userspace_mem.memory_size = PAGE_SIZE; 2196 kvm_userspace_mem.memory_size = PAGE_SIZE;
2196 r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0); 2197 r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0);
2197 if (r) 2198 if (r)
2198 goto out; 2199 goto out;
2199 2200
2200 kvm->arch.ept_identity_pagetable = gfn_to_page(kvm, 2201 kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
2201 VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT); 2202 kvm->arch.ept_identity_map_addr >> PAGE_SHIFT);
2202out: 2203out:
2203 up_write(&kvm->slots_lock); 2204 up_write(&kvm->slots_lock);
2204 return r; 2205 return r;
@@ -3814,9 +3815,13 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
3814 if (alloc_apic_access_page(kvm) != 0) 3815 if (alloc_apic_access_page(kvm) != 0)
3815 goto free_vmcs; 3816 goto free_vmcs;
3816 3817
3817 if (enable_ept) 3818 if (enable_ept) {
3819 if (!kvm->arch.ept_identity_map_addr)
3820 kvm->arch.ept_identity_map_addr =
3821 VMX_EPT_IDENTITY_PAGETABLE_ADDR;
3818 if (alloc_identity_pagetable(kvm) != 0) 3822 if (alloc_identity_pagetable(kvm) != 0)
3819 goto free_vmcs; 3823 goto free_vmcs;
3824 }
3820 3825
3821 return &vmx->vcpu; 3826 return &vmx->vcpu;
3822 3827
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c7ec0c921c01..f4cb1baaa04b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1206,6 +1206,7 @@ int kvm_dev_ioctl_check_extension(long ext)
1206 case KVM_CAP_IOEVENTFD: 1206 case KVM_CAP_IOEVENTFD:
1207 case KVM_CAP_PIT2: 1207 case KVM_CAP_PIT2:
1208 case KVM_CAP_PIT_STATE2: 1208 case KVM_CAP_PIT_STATE2:
1209 case KVM_CAP_SET_IDENTITY_MAP_ADDR:
1209 r = 1; 1210 r = 1;
1210 break; 1211 break;
1211 case KVM_CAP_COALESCED_MMIO: 1212 case KVM_CAP_COALESCED_MMIO:
@@ -1906,6 +1907,13 @@ static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
1906 return ret; 1907 return ret;
1907} 1908}
1908 1909
1910static int kvm_vm_ioctl_set_identity_map_addr(struct kvm *kvm,
1911 u64 ident_addr)
1912{
1913 kvm->arch.ept_identity_map_addr = ident_addr;
1914 return 0;
1915}
1916
1909static int kvm_vm_ioctl_set_nr_mmu_pages(struct kvm *kvm, 1917static int kvm_vm_ioctl_set_nr_mmu_pages(struct kvm *kvm,
1910 u32 kvm_nr_mmu_pages) 1918 u32 kvm_nr_mmu_pages)
1911{ 1919{
@@ -2173,6 +2181,17 @@ long kvm_arch_vm_ioctl(struct file *filp,
2173 if (r < 0) 2181 if (r < 0)
2174 goto out; 2182 goto out;
2175 break; 2183 break;
2184 case KVM_SET_IDENTITY_MAP_ADDR: {
2185 u64 ident_addr;
2186
2187 r = -EFAULT;
2188 if (copy_from_user(&ident_addr, argp, sizeof ident_addr))
2189 goto out;
2190 r = kvm_vm_ioctl_set_identity_map_addr(kvm, ident_addr);
2191 if (r < 0)
2192 goto out;
2193 break;
2194 }
2176 case KVM_SET_MEMORY_REGION: { 2195 case KVM_SET_MEMORY_REGION: {
2177 struct kvm_memory_region kvm_mem; 2196 struct kvm_memory_region kvm_mem;
2178 struct kvm_userspace_memory_region kvm_userspace_mem; 2197 struct kvm_userspace_memory_region kvm_userspace_mem;
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 230a91aa61c9..f8f8900fc5ec 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -435,6 +435,7 @@ struct kvm_ioeventfd {
435#define KVM_CAP_PIT_STATE2 35 435#define KVM_CAP_PIT_STATE2 35
436#endif 436#endif
437#define KVM_CAP_IOEVENTFD 36 437#define KVM_CAP_IOEVENTFD 36
438#define KVM_CAP_SET_IDENTITY_MAP_ADDR 37
438 439
439#ifdef KVM_CAP_IRQ_ROUTING 440#ifdef KVM_CAP_IRQ_ROUTING
440 441
@@ -512,6 +513,7 @@ struct kvm_irqfd {
512#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46,\ 513#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46,\
513 struct kvm_userspace_memory_region) 514 struct kvm_userspace_memory_region)
514#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) 515#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
516#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
515/* Device model IOC */ 517/* Device model IOC */
516#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) 518#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
517#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level) 519#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)