aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r--arch/x86/kvm/mmu.c136
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 */
43static bool tdp_enabled = false; 44bool 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
171struct kvm_pv_mmu_op_buffer {
172 void *ptr;
173 unsigned len;
174 unsigned processed;
175 char buf[512] __aligned(sizeof(long));
176};
177
170struct kvm_rmap_desc { 178struct 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
2014static 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
2022static 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
2036static 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
2055static int kvm_pv_mmu_flush_tlb(struct kvm_vcpu *vcpu)
2056{
2057 kvm_x86_ops->tlb_flush(vcpu);
2058 return 1;
2059}
2060
2061static 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
2069static 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
2107int 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(&current->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;
2133out:
2134 *ret = buffer.processed;
2135 up_read(&current->mm->mmap_sem);
2136 up_read(&vcpu->kvm->slots_lock);
2137 return r;
2138}
2139
2006#ifdef AUDIT 2140#ifdef AUDIT
2007 2141
2008static const char *audit_msg; 2142static const char *audit_msg;