diff options
author | Sheng Yang <sheng@linux.intel.com> | 2009-07-20 22:42:48 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-09-10 01:33:16 -0400 |
commit | b927a3cec081a605142f5b7e90b730611bee28b1 (patch) | |
tree | ed7609e83e89c0830d568aa8304200cdb0c58736 | |
parent | b792c344dfd57ee2cf737440e4a9b4a5bc39d1db (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.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 15 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 19 | ||||
-rw-r--r-- | include/linux/kvm.h | 2 |
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); |
2202 | out: | 2203 | out: |
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 | ||
1910 | static 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 | |||
1909 | static int kvm_vm_ioctl_set_nr_mmu_pages(struct kvm *kvm, | 1917 | static 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) |