diff options
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r-- | arch/x86/kvm/mmu.c | 136 |
1 files changed, 135 insertions, 1 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; |