diff options
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 69 |
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 | } |
1505 | EXPORT_SYMBOL_GPL(save_msrs); | 1505 | EXPORT_SYMBOL_GPL(save_msrs); |
1506 | 1506 | ||
1507 | void 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 | } | ||
1542 | EXPORT_SYMBOL_GPL(kvm_emulate_cpuid); | ||
1543 | |||
1507 | static void complete_pio(struct kvm_vcpu *vcpu) | 1544 | static 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 | ||
2115 | static 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 | |||
2131 | out: | ||
2132 | return r; | ||
2133 | } | ||
2134 | |||
2078 | static long kvm_vcpu_ioctl(struct file *filp, | 2135 | static 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 | } |