Skip to content
This repository has been archived by the owner on Jan 28, 2023. It is now read-only.

Add set_cpuid ioctl #271

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/include/hax_core_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ int hax_vm_core_open(struct vm_t *vm);
/* Corresponding hax_get_vm with refer == 1 */
int hax_put_vm(struct vm_t *vm);
int hax_vm_set_qemuversion(struct vm_t *vm, struct hax_qemu_version *ver);
int hax_vm_set_cpuid(struct vm_t *vm, struct hax_cpuid *cpuid_data);

struct vm_t * hax_create_vm(int *vm_id);
int hax_teardown_vm(struct vm_t *vm);
Expand Down
1 change: 1 addition & 0 deletions core/include/vcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,5 +288,6 @@ static inline bool valid_vcpu_id(int vcpu_id)

bool vcpu_is_panic(struct vcpu_t *vcpu);
void vcpu_set_panic(struct vcpu_t *vcpu);
bool is_cpuid_supported(struct hax_cpuid *cpuid_data);

#endif // HAX_CORE_VCPU_H_
2 changes: 2 additions & 0 deletions core/include/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct vm_t {
uint64_t spare_ramsize;
uint ram_entry_num;
struct hax_vcpu_mem *ram_entry;
struct hax_cpuid *cpuid_data;
};

struct hva_entry {
Expand Down Expand Up @@ -128,6 +129,7 @@ int _hax_teardown_vm(struct vm_t *vm);
void hax_teardown_vcpus(struct vm_t *vm);
int hax_destroy_host_interface(void);
int hax_vm_set_qemuversion(struct vm_t *vm, struct hax_qemu_version *ver);
//int hax_vm_set_cpuid(struct vm_t *vm, struct hax_cpuid *cpuid_data);

uint64_t vm_get_eptp(struct vm_t *vm);

Expand Down
88 changes: 79 additions & 9 deletions core/vcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2506,22 +2506,92 @@ static int exit_cpuid(struct vcpu_t *vcpu, struct hax_tunnel *htun)
return HAX_RESUME;
}

bool is_cpuid_supported(struct hax_cpuid *cpuid_data)
{
uint32_t cpuid_i;
for (cpuid_i = 0; cpuid_i < cpuid_data->nent; cpuid_i++) {
switch (cpuid_data->entries[cpuid_i].function) {
case 0: {
if (cpuid_data->entries[cpuid_i].eax > 0xa) {
hax_log(HAX_LOGE, "Unsupported cpuid level %d\n",
cpuid_data->entries[cpuid_i].eax);
return false;
}
break;
}
case 0x80000000: {
if (cpuid_data->entries[cpuid_i].eax > 0x80000008) {
hax_log(HAX_LOGE, "Unsupported cpuid xlevel %d\n",
cpuid_data->entries[cpuid_i].eax);
return false;
}
break;
}
case 1: {
// Disallow to clear these feature bits, since MSR handling
// code is written as if these are supported.
uint32_t nonDisabledFlags = FEATURE(MCE) | FEATURE(APIC) |
FEATURE(MTRR) | FEATURE(PAT);
if ((cpuid_data->entries[cpuid_i].edx & nonDisabledFlags) !=
nonDisabledFlags) {
hax_log(HAX_LOGE, "MCE/APIC/MTRR/PAT disabling in cpuid "
"not supported\n");
return false;
}
break;
}
}
}
return true;
}

static int get_vm_cpuid(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
{
uint32_t cpuid_i;
struct hax_cpuid_entry *cpuid_entry;
struct vcpu_state_t *state = vcpu->state;

cpuid_entry = &vcpu->vm->cpuid_data->entries[0];
for (cpuid_i = 0; cpuid_i < vcpu->vm->cpuid_data->nent;
cpuid_i++) {
if (cpuid_entry[cpuid_i].function == a &&
(!(cpuid_entry[cpuid_i].flags & HAX_CPUID_FLAG_SIGNIFCANT_INDEX) ||
cpuid_entry[cpuid_i].index == c)) {

state->_eax = cpuid_entry[cpuid_i].eax;
state->_ecx = cpuid_entry[cpuid_i].ecx;
state->_edx = cpuid_entry[cpuid_i].edx;
state->_ebx = cpuid_entry[cpuid_i].ebx;
return 1;
}
}

state->_eax = 0;
state->_ecx = 0;
state->_edx = 0;
state->_ebx = 0;
return 0;
}

static void handle_cpuid(struct vcpu_t *vcpu, struct hax_tunnel *htun)
{
struct vcpu_state_t *state = vcpu->state;
uint32_t a = state->_eax, c = state->_ecx;
cpuid_args_t args;

args.eax = state->_eax;
args.ecx = state->_ecx;
asm_cpuid(&args);
state->_eax = args.eax;
state->_ecx = args.ecx;
state->_edx = args.edx;
state->_ebx = args.ebx;

handle_cpuid_virtual(vcpu, a, c);
if(vcpu->vm->cpuid_data) {
get_vm_cpuid(vcpu, a, c);
} else {
args.eax = state->_eax;
args.ecx = state->_ecx;
asm_cpuid(&args);
state->_eax = args.eax;
state->_ecx = args.ecx;
state->_edx = args.edx;
state->_ebx = args.ebx;

handle_cpuid_virtual(vcpu, a, c);
}
hax_log(HAX_LOGD, "CPUID %08x %08x: %08x %08x %08x %08x\n", a, c,
state->_eax, state->_ebx, state->_ecx, state->_edx);
htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason;
Expand Down
29 changes: 29 additions & 0 deletions core/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,35 @@ int hax_vm_set_qemuversion(struct vm_t *vm, struct hax_qemu_version *ver)
return 0;
}

int hax_vm_set_cpuid(struct vm_t *vm, struct hax_cpuid *cpuid_data)
{
uint32_t size;

if (vm->cpuid_data) {
size = sizeof(struct hax_cpuid) +
sizeof(struct hax_cpuid_entry) * vm->cpuid_data->nent;

hax_vfree(vm->cpuid_data, size);
vm->cpuid_data = 0;
}

if (!is_cpuid_supported(cpuid_data)) {
hax_log(HAX_LOGE, "%s: is_cpuid_supported failed\n", __func__);
return -EINVAL;
}
size = sizeof(struct hax_cpuid) +
sizeof(struct hax_cpuid_entry) * cpuid_data->nent;

vm->cpuid_data = hax_vmalloc(size, HAX_MEM_NONPAGE);
if (!vm->cpuid_data) {
hax_log(HAX_LOGE, "%s: Not enough memory for cpuid_data\n", __func__);
return -ENOMEM;
}

memcpy(vm->cpuid_data, cpuid_data, size);
return 0;
}

uint64_t vm_get_eptp(struct vm_t *vm)
{
return vm->ept_tree.eptp.value;
Expand Down
1 change: 1 addition & 0 deletions include/darwin/hax_interface_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@

/* API 2.0 */
#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION _IOW(0, 0x84, struct hax_qemu_version)
#define HAX_VM_IOCTL_SET_CPUID _IOW(0, 0x88, struct hax_cpuid)

#define HAX_IOCTL_VCPU_DEBUG _IOW(0, 0xc9, struct hax_debug_t)

Expand Down
28 changes: 28 additions & 0 deletions include/hax_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,32 @@ struct hax_debug_t {
uint64_t dr[8];
} PACKED;

#define HAX_CPUID_FLAG_SIGNIFCANT_INDEX (1 << 0)

struct hax_cpuid_entry {
uint32_t function;
uint32_t index;
uint32_t flags;
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t padding[3];
} PACKED;

struct hax_cpuid {
uint32_t nent;
uint32_t padding;
struct hax_cpuid_entry entries[0];
} PACKED;

#define HAX_MAX_CPUID_ENTRIES 50

#ifndef HAX_PLATFORM_WINDOWS
struct hax_cpuid_data {
struct hax_cpuid cpuid;
struct hax_cpuid_entry entries[HAX_MAX_CPUID_ENTRIES];
} PACKED;
#endif

#endif // HAX_INTERFACE_H_
1 change: 1 addition & 0 deletions include/linux/hax_interface_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@

/* API 2.0 */
#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION _IOW(0, 0x84, struct hax_qemu_version)
#define HAX_VM_IOCTL_SET_CPUID _IOW(0, 0x88, struct hax_cpuid)

#define HAX_IOCTL_VCPU_DEBUG _IOW(0, 0xc9, struct hax_debug_t)

Expand Down
1 change: 1 addition & 0 deletions include/netbsd/hax_interface_netbsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@

/* API 2.0 */
#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION _IOW(0, 0x84, struct hax_qemu_version)
#define HAX_VM_IOCTL_SET_CPUID _IOW(0, 0x88, struct hax_cpuid)

#define HAX_IOCTL_VCPU_DEBUG _IOW(0, 0xc9, struct hax_debug_t)

Expand Down
27 changes: 27 additions & 0 deletions platforms/darwin/com_intel_hax_ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,33 @@ static int hax_vm_ioctl(dev_t dev, ulong cmd, caddr_t data, int flag,
ret = hax_vm_set_qemuversion(cvm, info);
break;
}
case HAX_VM_IOCTL_SET_CPUID: {
struct hax_cpuid_data info;
uint32_t size;

if (copyin(&info, data, sizeof(struct hax_cpuid))) {
ret = -EFAULT;
break;
}

if (info.cpuid.nent > HAX_MAX_CPUID_ENTRIES) {
ret = -E2BIG;
break;
}

size = sizeof(struct hax_cpuid) +
sizeof(struct hax_cpuid_entry) * info.cpuid.nent;

if (copyin(&info, data, size)) {
ret = -EFAULT;
break;
}

if (hax_vm_set_cpuid(cvm, &(info.cpuid))) {
ret = EFAULT;
}
break;
}
default: {
handle_unknown_ioctl(dev, cmd, p);
ret = -ENOSYS;
Expand Down
27 changes: 27 additions & 0 deletions platforms/linux/components.c
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,33 @@ static long hax_vm_ioctl(struct file *filp, unsigned int cmd,
ret = hax_vm_set_qemuversion(cvm, &info);
break;
}
case HAX_VM_IOCTL_SET_CPUID: {
struct hax_cpuid_data info;
uint32_t size;

if (copy_from_user(&info, argp, sizeof(struct hax_cpuid))) {
ret = -EFAULT;
break;
}

if (info.cpuid.nent > HAX_MAX_CPUID_ENTRIES) {
ret = -E2BIG;
break;
}

size = sizeof(struct hax_cpuid) +
sizeof(struct hax_cpuid_entry) * info.cpuid.nent;

if (copy_from_user(&info, argp, size)) {
ret = -EFAULT;
break;
}

if (hax_vm_set_cpuid(cvm, &info)) {
ret = EFAULT;
}
break;
}
default:
// TODO: Print information about the process that sent the ioctl.
hax_log(HAX_LOGE, "Unknown VM IOCTL 0x%lx\n", cmd);
Expand Down
27 changes: 27 additions & 0 deletions platforms/netbsd/hax_entry_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,33 @@ int hax_vm_ioctl(dev_t self __unused, u_long cmd, void *data, int flag,
ret = hax_vm_set_qemuversion(cvm, info);
break;
}
case HAX_VM_IOCTL_SET_CPUID: {
struct hax_cpuid_data info;
uint32_t size;

if (copyin(&info, data, sizeof(struct hax_cpuid))) {
ret = -EFAULT;
break;
}

if (info.cpuid.nent > HAX_MAX_CPUID_ENTRIES) {
ret = -E2BIG;
break;
}

size = sizeof(struct hax_cpuid) +
sizeof(struct hax_cpuid_entry) * info.cpuid.nent;

if (copyin(&info, data, size)) {
ret = -EFAULT;
break;
}

if (hax_vm_set_cpuid(cvm, &info)) {
ret = EFAULT;
}
break;
}
default:
// TODO: Print information about the process that sent the ioctl.
hax_log(HAX_LOGE, "Unknown VM IOCTL %#lx, pid=%d ('%s')\n", cmd,
Expand Down
24 changes: 24 additions & 0 deletions platforms/windows/hax_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,30 @@ NTSTATUS HaxVmControl(PDEVICE_OBJECT DeviceObject, struct hax_vm_windows *ext,
hax_vm_set_qemuversion(cvm, info);
break;
}
case HAX_VM_IOCTL_SET_CPUID: {
struct hax_cpuid *info;
uint32_t size;

if (inBufLength < sizeof(struct hax_cpuid)) {
ret = STATUS_INVALID_PARAMETER;
goto done;
}

info = (struct hax_cpuid *)inBuf;
size = sizeof(struct hax_cpuid) +
sizeof(struct hax_cpuid_entry) * info->nent;

if (inBufLength < size || info->nent > HAX_MAX_CPUID_ENTRIES) {
ret = -E2BIG;
goto done;
}

if (hax_vm_set_cpuid(cvm, info)) {
ret = STATUS_UNSUCCESSFUL;
goto done;
}
break;
}
default:
ret = STATUS_INVALID_PARAMETER;
break;
Expand Down
2 changes: 2 additions & 0 deletions platforms/windows/hax_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ extern PDRIVER_OBJECT HaxDriverObject;
/* API version 2.0 */
#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION \
CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define HAX_VM_IOCTL_SET_CPUID \
CTL_CODE(HAX_DEVICE_TYPE, 0x917, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define HAX_IOCTL_VCPU_DEBUG \
CTL_CODE(HAX_DEVICE_TYPE, 0x916, METHOD_BUFFERED, FILE_ANY_ACCESS)
Expand Down