aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/kvm.h5
-rw-r--r--drivers/kvm/kvm_main.c69
-rw-r--r--drivers/kvm/svm.c4
-rw-r--r--drivers/kvm/vmx.c4
-rw-r--r--include/linux/kvm.h18
5 files changed, 95 insertions, 5 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 59cbc5b1d905..be3a0e7ecae4 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -55,6 +55,7 @@
55#define KVM_NUM_MMU_PAGES 256 55#define KVM_NUM_MMU_PAGES 256
56#define KVM_MIN_FREE_MMU_PAGES 5 56#define KVM_MIN_FREE_MMU_PAGES 5
57#define KVM_REFILL_PAGES 25 57#define KVM_REFILL_PAGES 25
58#define KVM_MAX_CPUID_ENTRIES 40
58 59
59#define FX_IMAGE_SIZE 512 60#define FX_IMAGE_SIZE 512
60#define FX_IMAGE_ALIGN 16 61#define FX_IMAGE_ALIGN 16
@@ -286,6 +287,9 @@ struct kvm_vcpu {
286 u32 ar; 287 u32 ar;
287 } tr, es, ds, fs, gs; 288 } tr, es, ds, fs, gs;
288 } rmode; 289 } rmode;
290
291 int cpuid_nent;
292 struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];
289}; 293};
290 294
291struct kvm_memory_slot { 295struct kvm_memory_slot {
@@ -446,6 +450,7 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,
446 450
447struct x86_emulate_ctxt; 451struct x86_emulate_ctxt;
448 452
453void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
449int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address); 454int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address);
450int emulate_clts(struct kvm_vcpu *vcpu); 455int emulate_clts(struct kvm_vcpu *vcpu);
451int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr, 456int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr,
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index ff8bcfee76e5..caec54fbf07f 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -1504,6 +1504,43 @@ void save_msrs(struct vmx_msr_entry *e, int n)
1504} 1504}
1505EXPORT_SYMBOL_GPL(save_msrs); 1505EXPORT_SYMBOL_GPL(save_msrs);
1506 1506
1507void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
1508{
1509 int i;
1510 u32 function;
1511 struct kvm_cpuid_entry *e, *best;
1512
1513 kvm_arch_ops->cache_regs(vcpu);
1514 function = vcpu->regs[VCPU_REGS_RAX];
1515 vcpu->regs[VCPU_REGS_RAX] = 0;
1516 vcpu->regs[VCPU_REGS_RBX] = 0;
1517 vcpu->regs[VCPU_REGS_RCX] = 0;
1518 vcpu->regs[VCPU_REGS_RDX] = 0;
1519 best = NULL;
1520 for (i = 0; i < vcpu->cpuid_nent; ++i) {
1521 e = &vcpu->cpuid_entries[i];
1522 if (e->function == function) {
1523 best = e;
1524 break;
1525 }
1526 /*
1527 * Both basic or both extended?
1528 */
1529 if (((e->function ^ function) & 0x80000000) == 0)
1530 if (!best || e->function > best->function)
1531 best = e;
1532 }
1533 if (best) {
1534 vcpu->regs[VCPU_REGS_RAX] = best->eax;
1535 vcpu->regs[VCPU_REGS_RBX] = best->ebx;
1536 vcpu->regs[VCPU_REGS_RCX] = best->ecx;
1537 vcpu->regs[VCPU_REGS_RDX] = best->edx;
1538 }
1539 kvm_arch_ops->decache_regs(vcpu);
1540 kvm_arch_ops->skip_emulated_instruction(vcpu);
1541}
1542EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
1543
1507static void complete_pio(struct kvm_vcpu *vcpu) 1544static void complete_pio(struct kvm_vcpu *vcpu)
1508{ 1545{
1509 struct kvm_io *io = &vcpu->run->io; 1546 struct kvm_io *io = &vcpu->run->io;
@@ -2075,6 +2112,26 @@ out:
2075 return r; 2112 return r;
2076} 2113}
2077 2114
2115static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
2116 struct kvm_cpuid *cpuid,
2117 struct kvm_cpuid_entry __user *entries)
2118{
2119 int r;
2120
2121 r = -E2BIG;
2122 if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
2123 goto out;
2124 r = -EFAULT;
2125 if (copy_from_user(&vcpu->cpuid_entries, entries,
2126 cpuid->nent * sizeof(struct kvm_cpuid_entry)))
2127 goto out;
2128 vcpu->cpuid_nent = cpuid->nent;
2129 return 0;
2130
2131out:
2132 return r;
2133}
2134
2078static long kvm_vcpu_ioctl(struct file *filp, 2135static long kvm_vcpu_ioctl(struct file *filp,
2079 unsigned int ioctl, unsigned long arg) 2136 unsigned int ioctl, unsigned long arg)
2080{ 2137{
@@ -2181,6 +2238,18 @@ static long kvm_vcpu_ioctl(struct file *filp,
2181 case KVM_SET_MSRS: 2238 case KVM_SET_MSRS:
2182 r = msr_io(vcpu, argp, do_set_msr, 0); 2239 r = msr_io(vcpu, argp, do_set_msr, 0);
2183 break; 2240 break;
2241 case KVM_SET_CPUID: {
2242 struct kvm_cpuid __user *cpuid_arg = argp;
2243 struct kvm_cpuid cpuid;
2244
2245 r = -EFAULT;
2246 if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
2247 goto out;
2248 r = kvm_vcpu_ioctl_set_cpuid(vcpu, &cpuid, cpuid_arg->entries);
2249 if (r)
2250 goto out;
2251 break;
2252 }
2184 default: 2253 default:
2185 ; 2254 ;
2186 } 2255 }
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index c35b8c83bf3f..d4b2936479d9 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -1101,8 +1101,8 @@ static int task_switch_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_r
1101static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1101static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1102{ 1102{
1103 vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2; 1103 vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
1104 kvm_run->exit_reason = KVM_EXIT_CPUID; 1104 kvm_emulate_cpuid(vcpu);
1105 return 0; 1105 return 1;
1106} 1106}
1107 1107
1108static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1108static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 4d5f40fcb651..71410a65bb90 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1585,8 +1585,8 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1585 1585
1586static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1586static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1587{ 1587{
1588 kvm_run->exit_reason = KVM_EXIT_CPUID; 1588 kvm_emulate_cpuid(vcpu);
1589 return 0; 1589 return 1;
1590} 1590}
1591 1591
1592static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1592static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 19aeb3385188..15e23bc06e8b 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -41,7 +41,6 @@ enum kvm_exit_reason {
41 KVM_EXIT_UNKNOWN = 0, 41 KVM_EXIT_UNKNOWN = 0,
42 KVM_EXIT_EXCEPTION = 1, 42 KVM_EXIT_EXCEPTION = 1,
43 KVM_EXIT_IO = 2, 43 KVM_EXIT_IO = 2,
44 KVM_EXIT_CPUID = 3,
45 KVM_EXIT_DEBUG = 4, 44 KVM_EXIT_DEBUG = 4,
46 KVM_EXIT_HLT = 5, 45 KVM_EXIT_HLT = 5,
47 KVM_EXIT_MMIO = 6, 46 KVM_EXIT_MMIO = 6,
@@ -210,6 +209,22 @@ struct kvm_dirty_log {
210 }; 209 };
211}; 210};
212 211
212struct kvm_cpuid_entry {
213 __u32 function;
214 __u32 eax;
215 __u32 ebx;
216 __u32 ecx;
217 __u32 edx;
218 __u32 padding;
219};
220
221/* for KVM_SET_CPUID */
222struct kvm_cpuid {
223 __u32 nent;
224 __u32 padding;
225 struct kvm_cpuid_entry entries[0];
226};
227
213#define KVMIO 0xAE 228#define KVMIO 0xAE
214 229
215/* 230/*
@@ -243,5 +258,6 @@ struct kvm_dirty_log {
243#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest) 258#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest)
244#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs) 259#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs)
245#define KVM_SET_MSRS _IOW(KVMIO, 14, struct kvm_msrs) 260#define KVM_SET_MSRS _IOW(KVMIO, 14, struct kvm_msrs)
261#define KVM_SET_CPUID _IOW(KVMIO, 17, struct kvm_cpuid)
246 262
247#endif 263#endif