aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r--drivers/kvm/kvm_main.c69
1 files changed, 69 insertions, 0 deletions
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 }