Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 54061
b: refs/heads/master
c: 06465c5
h: refs/heads/master
i:
  54059: 503aafc
v: v3
  • Loading branch information
Avi Kivity committed May 3, 2007
1 parent d543a84 commit db2d806
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 46fc1477887c41c8e900f2c95485e222b9a54822
refs/heads/master: 06465c5a3aa9948a7b00af49cd22ed8f235cdb0f
5 changes: 5 additions & 0 deletions trunk/drivers/kvm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#define KVM_NUM_MMU_PAGES 256
#define KVM_MIN_FREE_MMU_PAGES 5
#define KVM_REFILL_PAGES 25
#define KVM_MAX_CPUID_ENTRIES 40

#define FX_IMAGE_SIZE 512
#define FX_IMAGE_ALIGN 16
Expand Down Expand Up @@ -286,6 +287,9 @@ struct kvm_vcpu {
u32 ar;
} tr, es, ds, fs, gs;
} rmode;

int cpuid_nent;
struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];
};

struct kvm_memory_slot {
Expand Down Expand Up @@ -446,6 +450,7 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value,

struct x86_emulate_ctxt;

void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address);
int emulate_clts(struct kvm_vcpu *vcpu);
int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr,
Expand Down
69 changes: 69 additions & 0 deletions trunk/drivers/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,43 @@ void save_msrs(struct vmx_msr_entry *e, int n)
}
EXPORT_SYMBOL_GPL(save_msrs);

void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
{
int i;
u32 function;
struct kvm_cpuid_entry *e, *best;

kvm_arch_ops->cache_regs(vcpu);
function = vcpu->regs[VCPU_REGS_RAX];
vcpu->regs[VCPU_REGS_RAX] = 0;
vcpu->regs[VCPU_REGS_RBX] = 0;
vcpu->regs[VCPU_REGS_RCX] = 0;
vcpu->regs[VCPU_REGS_RDX] = 0;
best = NULL;
for (i = 0; i < vcpu->cpuid_nent; ++i) {
e = &vcpu->cpuid_entries[i];
if (e->function == function) {
best = e;
break;
}
/*
* Both basic or both extended?
*/
if (((e->function ^ function) & 0x80000000) == 0)
if (!best || e->function > best->function)
best = e;
}
if (best) {
vcpu->regs[VCPU_REGS_RAX] = best->eax;
vcpu->regs[VCPU_REGS_RBX] = best->ebx;
vcpu->regs[VCPU_REGS_RCX] = best->ecx;
vcpu->regs[VCPU_REGS_RDX] = best->edx;
}
kvm_arch_ops->decache_regs(vcpu);
kvm_arch_ops->skip_emulated_instruction(vcpu);
}
EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);

static void complete_pio(struct kvm_vcpu *vcpu)
{
struct kvm_io *io = &vcpu->run->io;
Expand Down Expand Up @@ -2075,6 +2112,26 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
return r;
}

static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
struct kvm_cpuid *cpuid,
struct kvm_cpuid_entry __user *entries)
{
int r;

r = -E2BIG;
if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
goto out;
r = -EFAULT;
if (copy_from_user(&vcpu->cpuid_entries, entries,
cpuid->nent * sizeof(struct kvm_cpuid_entry)))
goto out;
vcpu->cpuid_nent = cpuid->nent;
return 0;

out:
return r;
}

static long kvm_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
Expand Down Expand Up @@ -2181,6 +2238,18 @@ static long kvm_vcpu_ioctl(struct file *filp,
case KVM_SET_MSRS:
r = msr_io(vcpu, argp, do_set_msr, 0);
break;
case KVM_SET_CPUID: {
struct kvm_cpuid __user *cpuid_arg = argp;
struct kvm_cpuid cpuid;

r = -EFAULT;
if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
goto out;
r = kvm_vcpu_ioctl_set_cpuid(vcpu, &cpuid, cpuid_arg->entries);
if (r)
goto out;
break;
}
default:
;
}
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1101,8 +1101,8 @@ static int task_switch_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_r
static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 2;
kvm_run->exit_reason = KVM_EXIT_CPUID;
return 0;
kvm_emulate_cpuid(vcpu);
return 1;
}

static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/kvm/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1585,8 +1585,8 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)

static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
kvm_run->exit_reason = KVM_EXIT_CPUID;
return 0;
kvm_emulate_cpuid(vcpu);
return 1;
}

static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
Expand Down
18 changes: 17 additions & 1 deletion trunk/include/linux/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ enum kvm_exit_reason {
KVM_EXIT_UNKNOWN = 0,
KVM_EXIT_EXCEPTION = 1,
KVM_EXIT_IO = 2,
KVM_EXIT_CPUID = 3,
KVM_EXIT_DEBUG = 4,
KVM_EXIT_HLT = 5,
KVM_EXIT_MMIO = 6,
Expand Down Expand Up @@ -210,6 +209,22 @@ struct kvm_dirty_log {
};
};

struct kvm_cpuid_entry {
__u32 function;
__u32 eax;
__u32 ebx;
__u32 ecx;
__u32 edx;
__u32 padding;
};

/* for KVM_SET_CPUID */
struct kvm_cpuid {
__u32 nent;
__u32 padding;
struct kvm_cpuid_entry entries[0];
};

#define KVMIO 0xAE

/*
Expand Down Expand Up @@ -243,5 +258,6 @@ struct kvm_dirty_log {
#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest)
#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs)
#define KVM_SET_MSRS _IOW(KVMIO, 14, struct kvm_msrs)
#define KVM_SET_CPUID _IOW(KVMIO, 17, struct kvm_cpuid)

#endif

0 comments on commit db2d806

Please sign in to comment.