diff options
-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) |