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

Add support for multicore Windows 10 guests #272

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
45 changes: 43 additions & 2 deletions core/vcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,16 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
uint32_t reserved2 : 4;
};
} cpuid_eax;
struct vm_t *vm = vcpu->vm;
hax_list_head *list;
int vcpu_count = 0;

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

cpuid_eax.raw = state->_eax;

if (0xF != cpuid_eax.familyID)
Expand Down Expand Up @@ -2651,6 +2661,9 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
// (see IA SDM Vol. 3A 3.2, Table 3-14)
0x00;

if (vcpu_count > 1)
state->_ebx |= (vcpu_count) << 16;

// Report only the features specified, excluding any features not
// supported by the host CPU, but including "hypervisor", which is
// desirable for VMMs.
Expand All @@ -2673,8 +2686,23 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
return;
}
case 4: { // Deterministic Cache Parameters
// [31:26] cores per package - 1
// Use host cache values.
// Use host cache values, but change maximum number of addresable
// IDs according to the number of virtual CPUs (bits [31:26]).
state->_eax &= ~0xFC000000;
if (state->_eax & 31) {
struct vm_t *vm = vcpu->vm;
hax_list_head *list;
int vcpu_count = 0;

hax_mutex_lock(vm->vm_lock);
hax_list_for_each(list, (hax_list_head *)(&vm->vcpu_list)) {
vcpu_count++;
}
hax_mutex_unlock(vm->vm_lock);
Comment on lines +2693 to +2701
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should be moved to a function.


if (vcpu_count > 1)
state->_eax |= (vcpu_count - 1) << 26;
}
return;
}
case 5: // MONITOR/MWAIT
Expand Down Expand Up @@ -2772,13 +2800,26 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
return;
}
case 0x80000008: { // Virtual/Physical Address Size
struct vm_t *vm = vcpu->vm;
hax_list_head *list;
int vcpu_count = 0;

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

// Bit mask to identify the reserved bits in paging structure high
// order address field
physical_address_size = (uint8_t)state->_eax & 0xff;
pw_reserved_bits_high_mask =
~((1 << (physical_address_size - 32)) - 1);

state->_ebx = state->_ecx = state->_edx = 0;

if (vcpu_count > 1)
state->_ecx |= vcpu_count - 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

According to Intel SDM, when the initial EAX value is 0x80000008, ECX is reserved to 0. Why set state->_ecx here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, SDM says it's reserved to 0. I've done this since qemu does the same:

    case 0x80000008:
        /* virtual & phys address size in low 2 bytes. */
        if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
            /* 64 bit processor */
            *eax = cpu->phys_bits; /* configurable physical bits */
            if  (env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_LA57) {
                *eax |= 0x00003900; /* 57 bits virtual */
            } else {
                *eax |= 0x00003000; /* 48 bits virtual */
            }
        } else {
            *eax = cpu->phys_bits;
        }
        *ebx = env->features[FEAT_8000_0008_EBX];
        *ecx = 0;
        *edx = 0;
        if (cs->nr_cores * cs->nr_threads > 1) {
            *ecx |= (cs->nr_cores * cs->nr_threads) - 1;
        }
        break;

return;
}
}
Expand Down