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

MacOS support #288

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/cpuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ enum {
#define FEAT(bit) \
FEATURE_KEY_LEAF(4, 0x80000001, CPUID_REG_ECX, bit)
X86_FEATURE_LAHF = FEAT(0), /* 0x00000001 LAHF/SAHF Instructions */
X86_FEATURE_LZCNT = FEAT(5), /* 0x00000020 LZCNT Instruction */
X86_FEATURE_PREFETCHW = FEAT(8), /* 0x00000100 PREFETCH/PREFETCHW instructions */
#undef FEAT

Expand Down
5 changes: 5 additions & 0 deletions core/include/ia32_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ enum {
IA32_EBC_HARD_POWERON = 0x2a,
IA32_EBC_SOFT_POWERON = 0x2b,
IA32_EBC_FREQUENCY_ID = 0x2c,
IA32_CORE_THREAD_COUNT = 0x35,
IA32_FEATURE_CONTROL = 0x3a,
IA32_THERM_DIODE_OFFSET = 0x3f,
IA32_BIOS_UPDT_TRIG = 0x79,
Expand All @@ -115,6 +116,7 @@ enum {
IA32_PMC2 = 0xc3,
IA32_PMC3 = 0xc4,
IA32_FSB_FREQ = 0xcd,
IA32_PLATFORM_INFO = 0xce,
IA32_MPERF = 0xe7,
IA32_APERF = 0xe8,
IA32_TEMP_TARGET = 0xee,
Expand All @@ -130,6 +132,9 @@ enum {
IA32_PERFEVTSEL1 = 0x187,
IA32_PERFEVTSEL2 = 0x188,
IA32_PERFEVTSEL3 = 0x189,
IA32_MCG_R8 = 0x190,
IA32_MCG_R15 = 0x197,
IA32_PERF_STATUS = 0x198,
IA32_PERF_CTL = 0x199,
IA32_MISC_ENABLE = 0x1a0,
IA32_DEBUGCTL = 0x1d9,
Expand Down
1 change: 0 additions & 1 deletion core/include/vcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ struct vcpu_t {
struct vm_t *vm;
struct hax_mmu *mmu;
struct vcpu_state_t *state;
uint64_t _cr8;
struct hax_tunnel *tunnel;
uint8_t *io_buf;
struct hax_page *vmcs_page;
Expand Down
78 changes: 70 additions & 8 deletions core/vcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ struct vcpu_t *vcpu_create(struct vm_t *vm, void *vm_host, int vcpu_id)
sizeof(struct vcpu_state_t), HAX_MEM_NONPAGE);
if (!vcpu->state)
goto fail_4;
memset(vcpu->state, 0, sizeof(struct vcpu_state_t));
memset(vcpu->state, 0, sizeof(struct vcpu_state_t)); //cr8 = 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is unclear (without looking at the whole commit).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove it in the final version. This is the place where cr8 is initialized. I used it to analyze the cr8 support feature.


vcpu->tmutex = hax_mutex_alloc_init();
if (!vcpu->tmutex)
Expand Down Expand Up @@ -2579,7 +2579,10 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
FEATURE(RDTSCP) |
FEATURE(EM64T);

static uint32_t cpuid_8000_0001_features_ecx = 0;
static uint32_t cpuid_8000_0001_features_ecx =
FEATURE(LAHF) |
FEATURE(LZCNT) |
FEATURE(PREFETCHW);

switch (a) {
case 0: { // Maximum Basic Information
Expand Down Expand Up @@ -2630,6 +2633,8 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
(VIRT_STEPPING & 0xF);
}

state->_eax = 0x10673; //Penryn

/* Report all threads in one package XXXXX vapic currently, we
* hardcode it to the maximal number of vcpus, but we should see
* the code in QEMU to vapic initialization.
Expand Down Expand Up @@ -2674,7 +2679,7 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
}
case 4: { // Deterministic Cache Parameters
// [31:26] cores per package - 1
// Use host cache values.
state->_eax = state->_ebx = state->_ecx = state->_edx = 0;
return;
}
case 5: // MONITOR/MWAIT
Expand Down Expand Up @@ -2859,8 +2864,27 @@ static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)
uint64_t old_val = 0;

if (cr == 8) {
// TODO: Redirect CR8 write to user space (emulated APIC.TPR)
hax_log(HAX_LOGW, "Ignored guest CR8 write, val=0x%llx\n", val);
if (vcpu->gstate.apic_base & APIC_BASE_ENABLE) {
// The APIC must be enabled for CR8 to function as the TPR. Writes to CR8 are
// reflected into the APIC Task Priority Register.
// Redirect CR8 write to user space (emulated APIC.TPR)
struct hax_tunnel *htun = vcpu->tunnel;
struct hax_fastmmio *hft = (struct hax_fastmmio *)vcpu->io_buf;
htun->_exit_status = HAX_EXIT_FAST_MMIO;
hft->gpa = APIC_BASE_DEFAULT_ADDR + 0x80; //APIC base cannot be relocated in haxm
hft->size = 1; // register size is 4 bytes but only the first byte is modified by the write to TPR.

//APIC.TPR[bits 7:4] = CR8[bits 3:0], APIC.TPR[bits 3:0] = 0.
hft->value = ( val << 4 ) & 0xF0;
hft->direction = 1;
state->_cr8 = val;

advance_rip(vcpu);

return HAX_EXIT;
}
else
hax_log(HAX_LOGW, "Ignored guest CR8 write since APIC is disabled, val=0x%llx\n", val);
break;
}

Expand Down Expand Up @@ -2968,8 +2992,10 @@ static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)

hax_log(HAX_LOGI, "cr_access R CR%d\n", cr);

val = vcpu_read_cr(state, cr);
// TODO: Redirect CR8 read to user space (emulated APIC.TPR)
if (cr == 8)
val = state->_cr8;
else
val = vcpu_read_cr(state, cr);
state->_regs[vmx(vcpu, exit_qualification).cr.gpr] = val;
break;
}
Expand Down Expand Up @@ -3262,6 +3288,7 @@ static int exit_msr_read(struct vcpu_t *vcpu, struct hax_tunnel *htun)
state->_rax = val & 0xffffffff;
state->_rdx = (val >> 32) & 0xffffffff;
} else {
hax_log(HAX_LOGW, " MSR read 0x%x - GP\n", msr);
hax_inject_exception(vcpu, VECTOR_GP, 0);
return HAX_RESUME;
}
Expand All @@ -3279,6 +3306,7 @@ static int exit_msr_write(struct vcpu_t *vcpu, struct hax_tunnel *htun)
htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason;

if (handle_msr_write(vcpu, msr, val, false)) {
hax_log(HAX_LOGW, " MSR write 0x%x - GP\n", msr);
hax_inject_exception(vcpu, VECTOR_GP, 0);
return HAX_RESUME;
}
Expand Down Expand Up @@ -3310,6 +3338,10 @@ static int misc_msr_read(struct vcpu_t *vcpu, uint32_t msr, uint64_t *val)
(msr >= 0x300 && msr <= 0x3ff)) {
*val = 0;
return 0;
} else if (msr >= IA32_MCG_R8 && msr <= IA32_MCG_R15) {
//R8-R15 registers at last error.
*val = 0;
return 0;
}

return 1;
Expand Down Expand Up @@ -3437,7 +3469,7 @@ static int handle_msr_read(struct vcpu_t *vcpu, uint32_t msr, uint64_t *val)
break;
}
case IA32_FSB_FREQ: {
*val = 4;
*val = 4; //333 MHz
break;
}
case IA32_TEMP_TARGET: {
Expand Down Expand Up @@ -3507,6 +3539,36 @@ static int handle_msr_read(struct vcpu_t *vcpu, uint32_t msr, uint64_t *val)
"value=0x%llx\n", msr - IA32_PERFEVTSEL0, *val);
break;
}
case IA32_CORE_THREAD_COUNT: {
//Bits 15:0 are the core count and bits 31:16 are the thread count
struct vm_t *vm = vcpu->vm;
hax_list_head *list;
int count = 0;

hax_mutex_lock(vm->vm_lock);
hax_list_for_each(list, (hax_list_head *)(&vm->vcpu_list)) {
count++;
}
hax_mutex_unlock(vm->vm_lock);

*val = (((uint64_t)count) << 16) | count;
break;
}
case IA32_PLATFORM_INFO: {
*val = 0x8080838f1011e00;
break;
}
case IA32_PERF_STATUS: {
//Current cpuid returns features and version between Nehalem and Penryn
//CPUs. These define only the lower 16 bits of this MSR. But MacOS uses
//bits 44-40. This can be the maximum bus ratio on Intel Core CPUs.
*val = 0x400000003e8;
break;
}
case IA32_PERF_CTL: {
*val = 0;
break;
}
default: {
r = misc_msr_read(vcpu, msr, val);
break;
Expand Down