diff options
| -rw-r--r-- | arch/x86/kvm/mmu.c | 136 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 18 | ||||
| -rw-r--r-- | include/asm-x86/kvm_host.h | 4 | ||||
| -rw-r--r-- | include/asm-x86/kvm_para.h | 29 | ||||
| -rw-r--r-- | include/linux/kvm.h | 1 | ||||
| -rw-r--r-- | include/linux/kvm_para.h | 5 |
6 files changed, 190 insertions, 3 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 414405b6ec13..072e9422c914 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/swap.h> | 29 | #include <linux/swap.h> |
| 30 | #include <linux/hugetlb.h> | 30 | #include <linux/hugetlb.h> |
| 31 | #include <linux/compiler.h> | ||
| 31 | 32 | ||
| 32 | #include <asm/page.h> | 33 | #include <asm/page.h> |
| 33 | #include <asm/cmpxchg.h> | 34 | #include <asm/cmpxchg.h> |
| @@ -40,7 +41,7 @@ | |||
| 40 | * 2. while doing 1. it walks guest-physical to host-physical | 41 | * 2. while doing 1. it walks guest-physical to host-physical |
| 41 | * If the hardware supports that we don't need to do shadow paging. | 42 | * If the hardware supports that we don't need to do shadow paging. |
| 42 | */ | 43 | */ |
| 43 | static bool tdp_enabled = false; | 44 | bool tdp_enabled = false; |
| 44 | 45 | ||
| 45 | #undef MMU_DEBUG | 46 | #undef MMU_DEBUG |
| 46 | 47 | ||
| @@ -167,6 +168,13 @@ static int dbg = 1; | |||
| 167 | #define ACC_USER_MASK PT_USER_MASK | 168 | #define ACC_USER_MASK PT_USER_MASK |
| 168 | #define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK) | 169 | #define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK) |
| 169 | 170 | ||
| 171 | struct kvm_pv_mmu_op_buffer { | ||
| 172 | void *ptr; | ||
| 173 | unsigned len; | ||
| 174 | unsigned processed; | ||
| 175 | char buf[512] __aligned(sizeof(long)); | ||
| 176 | }; | ||
| 177 | |||
| 170 | struct kvm_rmap_desc { | 178 | struct kvm_rmap_desc { |
| 171 | u64 *shadow_ptes[RMAP_EXT]; | 179 | u64 *shadow_ptes[RMAP_EXT]; |
| 172 | struct kvm_rmap_desc *more; | 180 | struct kvm_rmap_desc *more; |
| @@ -2003,6 +2011,132 @@ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm) | |||
| 2003 | return nr_mmu_pages; | 2011 | return nr_mmu_pages; |
| 2004 | } | 2012 | } |
| 2005 | 2013 | ||
| 2014 | static void *pv_mmu_peek_buffer(struct kvm_pv_mmu_op_buffer *buffer, | ||
| 2015 | unsigned len) | ||
| 2016 | { | ||
| 2017 | if (len > buffer->len) | ||
| 2018 | return NULL; | ||
| 2019 | return buffer->ptr; | ||
| 2020 | } | ||
| 2021 | |||
| 2022 | static void *pv_mmu_read_buffer(struct kvm_pv_mmu_op_buffer *buffer, | ||
| 2023 | unsigned len) | ||
| 2024 | { | ||
| 2025 | void *ret; | ||
| 2026 | |||
| 2027 | ret = pv_mmu_peek_buffer(buffer, len); | ||
| 2028 | if (!ret) | ||
| 2029 | return ret; | ||
| 2030 | buffer->ptr += len; | ||
| 2031 | buffer->len -= len; | ||
| 2032 | buffer->processed += len; | ||
| 2033 | return ret; | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | static int kvm_pv_mmu_write(struct kvm_vcpu *vcpu, | ||
| 2037 | gpa_t addr, gpa_t value) | ||
| 2038 | { | ||
| 2039 | int bytes = 8; | ||
| 2040 | int r; | ||
| 2041 | |||
| 2042 | if (!is_long_mode(vcpu) && !is_pae(vcpu)) | ||
| 2043 | bytes = 4; | ||
| 2044 | |||
| 2045 | r = mmu_topup_memory_caches(vcpu); | ||
| 2046 | if (r) | ||
| 2047 | return r; | ||
| 2048 | |||
| 2049 | if (!__emulator_write_phys(vcpu, addr, &value, bytes)) | ||
| 2050 | return -EFAULT; | ||
| 2051 | |||
| 2052 | return 1; | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | static int kvm_pv_mmu_flush_tlb(struct kvm_vcpu *vcpu) | ||
| 2056 | { | ||
| 2057 | kvm_x86_ops->tlb_flush(vcpu); | ||
| 2058 | return 1; | ||
| 2059 | } | ||
| 2060 | |||
| 2061 | static int kvm_pv_mmu_release_pt(struct kvm_vcpu *vcpu, gpa_t addr) | ||
| 2062 | { | ||
| 2063 | spin_lock(&vcpu->kvm->mmu_lock); | ||
| 2064 | mmu_unshadow(vcpu->kvm, addr >> PAGE_SHIFT); | ||
| 2065 | spin_unlock(&vcpu->kvm->mmu_lock); | ||
| 2066 | return 1; | ||
| 2067 | } | ||
| 2068 | |||
| 2069 | static int kvm_pv_mmu_op_one(struct kvm_vcpu *vcpu, | ||
| 2070 | struct kvm_pv_mmu_op_buffer *buffer) | ||
| 2071 | { | ||
| 2072 | struct kvm_mmu_op_header *header; | ||
| 2073 | |||
| 2074 | header = pv_mmu_peek_buffer(buffer, sizeof *header); | ||
| 2075 | if (!header) | ||
| 2076 | return 0; | ||
| 2077 | switch (header->op) { | ||
| 2078 | case KVM_MMU_OP_WRITE_PTE: { | ||
| 2079 | struct kvm_mmu_op_write_pte *wpte; | ||
| 2080 | |||
| 2081 | wpte = pv_mmu_read_buffer(buffer, sizeof *wpte); | ||
| 2082 | if (!wpte) | ||
| 2083 | return 0; | ||
| 2084 | return kvm_pv_mmu_write(vcpu, wpte->pte_phys, | ||
| 2085 | wpte->pte_val); | ||
| 2086 | } | ||
| 2087 | case KVM_MMU_OP_FLUSH_TLB: { | ||
| 2088 | struct kvm_mmu_op_flush_tlb *ftlb; | ||
| 2089 | |||
| 2090 | ftlb = pv_mmu_read_buffer(buffer, sizeof *ftlb); | ||
| 2091 | if (!ftlb) | ||
| 2092 | return 0; | ||
| 2093 | return kvm_pv_mmu_flush_tlb(vcpu); | ||
| 2094 | } | ||
| 2095 | case KVM_MMU_OP_RELEASE_PT: { | ||
| 2096 | struct kvm_mmu_op_release_pt *rpt; | ||
| 2097 | |||
| 2098 | rpt = pv_mmu_read_buffer(buffer, sizeof *rpt); | ||
| 2099 | if (!rpt) | ||
| 2100 | return 0; | ||
| 2101 | return kvm_pv_mmu_release_pt(vcpu, rpt->pt_phys); | ||
| 2102 | } | ||
| 2103 | default: return 0; | ||
| 2104 | } | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes, | ||
| 2108 | gpa_t addr, unsigned long *ret) | ||
| 2109 | { | ||
| 2110 | int r; | ||
| 2111 | struct kvm_pv_mmu_op_buffer buffer; | ||
| 2112 | |||
| 2113 | down_read(&vcpu->kvm->slots_lock); | ||
| 2114 | down_read(¤t->mm->mmap_sem); | ||
| 2115 | |||
| 2116 | buffer.ptr = buffer.buf; | ||
| 2117 | buffer.len = min_t(unsigned long, bytes, sizeof buffer.buf); | ||
| 2118 | buffer.processed = 0; | ||
| 2119 | |||
| 2120 | r = kvm_read_guest(vcpu->kvm, addr, buffer.buf, buffer.len); | ||
| 2121 | if (r) | ||
| 2122 | goto out; | ||
| 2123 | |||
| 2124 | while (buffer.len) { | ||
| 2125 | r = kvm_pv_mmu_op_one(vcpu, &buffer); | ||
| 2126 | if (r < 0) | ||
| 2127 | goto out; | ||
| 2128 | if (r == 0) | ||
| 2129 | break; | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | r = 1; | ||
| 2133 | out: | ||
| 2134 | *ret = buffer.processed; | ||
| 2135 | up_read(¤t->mm->mmap_sem); | ||
| 2136 | up_read(&vcpu->kvm->slots_lock); | ||
| 2137 | return r; | ||
| 2138 | } | ||
| 2139 | |||
| 2006 | #ifdef AUDIT | 2140 | #ifdef AUDIT |
| 2007 | 2141 | ||
| 2008 | static const char *audit_msg; | 2142 | static const char *audit_msg; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 03ba402c476a..63afca1c295f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -832,6 +832,9 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
| 832 | case KVM_CAP_NR_MEMSLOTS: | 832 | case KVM_CAP_NR_MEMSLOTS: |
| 833 | r = KVM_MEMORY_SLOTS; | 833 | r = KVM_MEMORY_SLOTS; |
| 834 | break; | 834 | break; |
| 835 | case KVM_CAP_PV_MMU: | ||
| 836 | r = !tdp_enabled; | ||
| 837 | break; | ||
| 835 | default: | 838 | default: |
| 836 | r = 0; | 839 | r = 0; |
| 837 | break; | 840 | break; |
| @@ -2452,9 +2455,19 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu) | |||
| 2452 | } | 2455 | } |
| 2453 | EXPORT_SYMBOL_GPL(kvm_emulate_halt); | 2456 | EXPORT_SYMBOL_GPL(kvm_emulate_halt); |
| 2454 | 2457 | ||
| 2458 | static inline gpa_t hc_gpa(struct kvm_vcpu *vcpu, unsigned long a0, | ||
| 2459 | unsigned long a1) | ||
| 2460 | { | ||
| 2461 | if (is_long_mode(vcpu)) | ||
| 2462 | return a0; | ||
| 2463 | else | ||
| 2464 | return a0 | ((gpa_t)a1 << 32); | ||
| 2465 | } | ||
| 2466 | |||
| 2455 | int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) | 2467 | int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) |
| 2456 | { | 2468 | { |
| 2457 | unsigned long nr, a0, a1, a2, a3, ret; | 2469 | unsigned long nr, a0, a1, a2, a3, ret; |
| 2470 | int r = 1; | ||
| 2458 | 2471 | ||
| 2459 | kvm_x86_ops->cache_regs(vcpu); | 2472 | kvm_x86_ops->cache_regs(vcpu); |
| 2460 | 2473 | ||
| @@ -2476,6 +2489,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) | |||
| 2476 | case KVM_HC_VAPIC_POLL_IRQ: | 2489 | case KVM_HC_VAPIC_POLL_IRQ: |
| 2477 | ret = 0; | 2490 | ret = 0; |
| 2478 | break; | 2491 | break; |
| 2492 | case KVM_HC_MMU_OP: | ||
| 2493 | r = kvm_pv_mmu_op(vcpu, a0, hc_gpa(vcpu, a1, a2), &ret); | ||
| 2494 | break; | ||
| 2479 | default: | 2495 | default: |
| 2480 | ret = -KVM_ENOSYS; | 2496 | ret = -KVM_ENOSYS; |
| 2481 | break; | 2497 | break; |
| @@ -2483,7 +2499,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) | |||
| 2483 | vcpu->arch.regs[VCPU_REGS_RAX] = ret; | 2499 | vcpu->arch.regs[VCPU_REGS_RAX] = ret; |
| 2484 | kvm_x86_ops->decache_regs(vcpu); | 2500 | kvm_x86_ops->decache_regs(vcpu); |
| 2485 | ++vcpu->stat.hypercalls; | 2501 | ++vcpu->stat.hypercalls; |
| 2486 | return 0; | 2502 | return r; |
| 2487 | } | 2503 | } |
| 2488 | EXPORT_SYMBOL_GPL(kvm_emulate_hypercall); | 2504 | EXPORT_SYMBOL_GPL(kvm_emulate_hypercall); |
| 2489 | 2505 | ||
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 99d31f5ed9ff..772ba95f0a0e 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h | |||
| @@ -434,6 +434,10 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3); | |||
| 434 | 434 | ||
| 435 | int __emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, | 435 | int __emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, |
| 436 | const void *val, int bytes); | 436 | const void *val, int bytes); |
| 437 | int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes, | ||
| 438 | gpa_t addr, unsigned long *ret); | ||
| 439 | |||
| 440 | extern bool tdp_enabled; | ||
| 437 | 441 | ||
| 438 | enum emulation_result { | 442 | enum emulation_result { |
| 439 | EMULATE_DONE, /* no further processing */ | 443 | EMULATE_DONE, /* no further processing */ |
diff --git a/include/asm-x86/kvm_para.h b/include/asm-x86/kvm_para.h index ed5df3a54aab..509845942070 100644 --- a/include/asm-x86/kvm_para.h +++ b/include/asm-x86/kvm_para.h | |||
| @@ -12,10 +12,39 @@ | |||
| 12 | #define KVM_CPUID_FEATURES 0x40000001 | 12 | #define KVM_CPUID_FEATURES 0x40000001 |
| 13 | #define KVM_FEATURE_CLOCKSOURCE 0 | 13 | #define KVM_FEATURE_CLOCKSOURCE 0 |
| 14 | #define KVM_FEATURE_NOP_IO_DELAY 1 | 14 | #define KVM_FEATURE_NOP_IO_DELAY 1 |
| 15 | #define KVM_FEATURE_MMU_OP 2 | ||
| 15 | 16 | ||
| 16 | #define MSR_KVM_WALL_CLOCK 0x11 | 17 | #define MSR_KVM_WALL_CLOCK 0x11 |
| 17 | #define MSR_KVM_SYSTEM_TIME 0x12 | 18 | #define MSR_KVM_SYSTEM_TIME 0x12 |
| 18 | 19 | ||
| 20 | #define KVM_MAX_MMU_OP_BATCH 32 | ||
| 21 | |||
| 22 | /* Operations for KVM_HC_MMU_OP */ | ||
| 23 | #define KVM_MMU_OP_WRITE_PTE 1 | ||
| 24 | #define KVM_MMU_OP_FLUSH_TLB 2 | ||
| 25 | #define KVM_MMU_OP_RELEASE_PT 3 | ||
| 26 | |||
| 27 | /* Payload for KVM_HC_MMU_OP */ | ||
| 28 | struct kvm_mmu_op_header { | ||
| 29 | __u32 op; | ||
| 30 | __u32 pad; | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct kvm_mmu_op_write_pte { | ||
| 34 | struct kvm_mmu_op_header header; | ||
| 35 | __u64 pte_phys; | ||
| 36 | __u64 pte_val; | ||
| 37 | }; | ||
| 38 | |||
| 39 | struct kvm_mmu_op_flush_tlb { | ||
| 40 | struct kvm_mmu_op_header header; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct kvm_mmu_op_release_pt { | ||
| 44 | struct kvm_mmu_op_header header; | ||
| 45 | __u64 pt_phys; | ||
| 46 | }; | ||
| 47 | |||
| 19 | #ifdef __KERNEL__ | 48 | #ifdef __KERNEL__ |
| 20 | #include <asm/processor.h> | 49 | #include <asm/processor.h> |
| 21 | 50 | ||
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 76f09474be98..c1b502a50a01 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
| @@ -238,6 +238,7 @@ struct kvm_vapic_addr { | |||
| 238 | #define KVM_CAP_NR_MEMSLOTS 10 /* returns max memory slots per vm */ | 238 | #define KVM_CAP_NR_MEMSLOTS 10 /* returns max memory slots per vm */ |
| 239 | #define KVM_CAP_PIT 11 | 239 | #define KVM_CAP_PIT 11 |
| 240 | #define KVM_CAP_NOP_IO_DELAY 12 | 240 | #define KVM_CAP_NOP_IO_DELAY 12 |
| 241 | #define KVM_CAP_PV_MMU 13 | ||
| 241 | 242 | ||
| 242 | /* | 243 | /* |
| 243 | * ioctls for VM fds | 244 | * ioctls for VM fds |
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h index 9c462c91a6b1..3ddce03766ca 100644 --- a/include/linux/kvm_para.h +++ b/include/linux/kvm_para.h | |||
| @@ -11,8 +11,11 @@ | |||
| 11 | 11 | ||
| 12 | /* Return values for hypercalls */ | 12 | /* Return values for hypercalls */ |
| 13 | #define KVM_ENOSYS 1000 | 13 | #define KVM_ENOSYS 1000 |
| 14 | #define KVM_EFAULT EFAULT | ||
| 15 | #define KVM_E2BIG E2BIG | ||
| 14 | 16 | ||
| 15 | #define KVM_HC_VAPIC_POLL_IRQ 1 | 17 | #define KVM_HC_VAPIC_POLL_IRQ 1 |
| 18 | #define KVM_HC_MMU_OP 2 | ||
| 16 | 19 | ||
| 17 | /* | 20 | /* |
| 18 | * hypercalls use architecture specific | 21 | * hypercalls use architecture specific |
