-
Notifications
You must be signed in to change notification settings - Fork 878
Conversation
core/vcpu.c
Outdated
unsigned extFamilyID : 8; | ||
unsigned reserved2 : 4; | ||
}; | ||
} cpuid_eax, cpuid_eax2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable cpuid_eax2
is not used anywhere.
Due to the strict compiler flags in the Darwin builds this triggers an error:
https://travis-ci.com/intel/haxm/jobs/203067260#L592
PS: Congrats on getting Windows 10 running, it's a huge step forward! 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Yes, we have more strict compiler flags enabled on Mac. Unused variables should be removed.
Thank you so much for enabling this big feature and submitting this PR! I'm leaving Intel, and @coxuintel is the new maintainer of HAXM. Please give Colin some time to finish this review. As my last contribution to the project, let me give a quick response to some of the open questions:
Yes, it looks like a bug to me. It doesn't make sense to update
That's also a good catch. The |
@raphaelning Best of luck in your future projects! It was really great contributing to HAXM under your careful supervision. |
More questions: @raphaelning good luck! Leaving Intel is not an excuse for not contributing )) |
If you think of virtualized apic as APICv, then this needs very recent Intel x86. Personally, I don't have any hw that handles it.. The solution of handling CR8 is to pass it to qemu and emulate by qemu. You can check the reference in NVMM from NetBSD as it does exactly this. |
@raphaelning good luck! |
@krytarowski NVMM passes CR8 reads\writes to qemu as MMIO and is able to running windows10x64? I implemented such solution but running windows installation get's stuck using 100% of CPU. When NVMM is able to run windows10x64 using this solution, than there must be another reason of problems in my tests. |
Win10 is known to work, but I have not tested it myself. |
The link contains a snapshot of windows 10 x86 and a comment about x64 support: |
I see, I haven't tested win10 myself - I'm just aware that CR8 was implemented. From other users of CR8 that I know there is just Solaris.. but more difficult to verify (proprietary and niche OS). |
Intel docs mention "Virtualize APIC accesses" feature. I can't find cpuids or capability MSRs to check to know if the processor supports it. How did you check your hardware for APICv support? |
https://www.redhat.com/archives/vfio-users/2016-June/msg00055.html here are ways how to detect it on Linux. |
|
Sorry fot the late reply. I tried to test on Win10 1903 x64 host, boot a Win10 1903 x86 or a Win7 x86 iso with upstream QEMU v4.0.0. However it triggers the IRQL_NOT_LESS_OR_EQUAL BSOD when haxm driver completing an IRP. Did you ever hit such issue? It looks like your patch did several things, and the v2 solve the compile error on Darwin.
Overall your patches looks ok, although I didn't yet boot the iso successfully 😢.
|
core/vcpu.c
Outdated
@@ -1189,6 +1188,10 @@ void vcpu_save_host_state(struct vcpu_t *vcpu) | |||
vmwrite(vcpu, HOST_EFER, hstate->_efer); | |||
} | |||
|
|||
if (vmx(vcpu, exit_ctls) & EXIT_CONTROL_LOAD_PAT) { | |||
vmwrite(vcpu, HOST_PAT, ia32_rdmsr(IA32_CR_PAT)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add ia32_pat to hstate so that more debug friendly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What means more debug friendly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the context I'd say (@coxuintel correct me if I'm wrong) something analogous to the few IA32_EFER-related lines above, i.e. first storing the IA32_CR_PAT
value in hstate:
hstate->_pat = ia32_rdmsr(IA32_CR_PAT);
and then vmwriting directly from that field:
if (vmx(vcpu, exit_ctls) & EXIT_CONTROL_LOAD_PAT) {
vmwrite(vcpu, HOST_PAT, hstate->_pat);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. Then functions like vcpu_get_host_state() could output more information then.
core/vcpu.c
Outdated
@@ -2009,11 +2016,12 @@ static void vmwrite_cr(struct vcpu_t *vcpu) | |||
if ((state->_cr4 & CR4_PAE) && (state->_cr0 & CR0_PG) && | |||
(state->_cr0 & CR0_PE)) { | |||
entry_ctls |= ENTRY_CONTROL_LOAD_EFER; | |||
vmx(vcpu, entry_ctls) |= ENTRY_CONTROL_LOAD_EFER; | |||
vmx(vcpu, entry_ctls) |= ENTRY_CONTROL_LOAD_EFER; //Without that VM triple faults! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the check. We can investigate later why this write is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some inline comments in addition to in the PR comments.
core/vcpu.c
Outdated
} else { | ||
entry_ctls &= ~ENTRY_CONTROL_LOAD_EFER; | ||
vmx(vcpu, entry_ctls) &= ~ENTRY_CONTROL_LOAD_EFER; | ||
vmx(vcpu, entry_ctls) &= ~ENTRY_CONTROL_LOAD_EFER; //Without that VM triple faults! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
core/vcpu.c
Outdated
unsigned reserved2 : 4; | ||
}; | ||
} cpuid_eax; | ||
cpuid_eax.raw = state->_eax; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have some alignment issue here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On which platforms? I think it would be better to change unsigned to uint32_t.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, to align with the type of raw could eliminate the reading ambiguity.
And I didn't mean byte alignment here but the format. 😄 There seems an extra space before the piece of code.
core/vcpu.c
Outdated
hw_model = (cpuid_eax.extModelID << 4) + cpuid_eax.model; | ||
else | ||
hw_model = cpuid_eax.model; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's much clean now and follow the pseudo code of SDM. 😄
core/vcpu.c
Outdated
@@ -78,7 +78,6 @@ static void vcpu_init(struct vcpu_t *vcpu); | |||
static void vcpu_prepare(struct vcpu_t *vcpu); | |||
static void vcpu_init_emulator(struct vcpu_t *vcpu); | |||
|
|||
static void vmread_cr(struct vcpu_t *vcpu); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this for clean-up? If so, we can do it together in future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, cleanup.
core/vcpu.c
Outdated
@@ -3766,7 +3813,7 @@ static int exit_ept_violation(struct vcpu_t *vcpu, struct hax_tunnel *htun) | |||
htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason; | |||
|
|||
if (qual->ept.gla1 == 0 && qual->ept.gla2 == 1) { | |||
hax_panic_vcpu(vcpu, "Incorrect EPT seting\n"); | |||
hax_panic_vcpu(vcpu, "Incorrect EPT setting\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do the clean-up work together in future.
BSOD on the host? Never. I used qemu 2.12 and 3.1.
PAT and LAHF are required, PDPE1GB, LZCNT and PREFETCHW are not, but I included these because they don't need any other support code.
OK, but I would wait with the merge till I solve the problem of saving PAT to qemu. Question 1 in my first post. |
I'll investigate this.
Then I would suggest split to 2 patches so that will be helpful to bisect in case some issue that hasn't been found during current test.
Oops, missed this one. HAXM has HAX_IOCTL_VERSION and HAX_IOCTL_CAPABILITY which we could leverage to take different actions from QEMU side. |
The reason seems like IRP sent with some ioctl get corrupted when calling into IoCompleteRequest(). It looks like irrelevant with your implementation, but I hit this every time booting a Windows ISO. |
C:\user\qemux64\qemu-system-i386.exe -L C:\user\qemu\pc-bios\ -name win10x86 -m 2G -uuid 564db62e-e031-b5cf-5f34-a75f8cefa98f -rtc base=localtime -accel hax -hdd C:\VirtualMachines\qemu\win10x86.qcow2 -cdrom C:\user\qemu\Windows10En.iso |
Left questions:
|
Excellent! If you changed some common CPU code in qemu, then there could be more comments from the community. Please check this link for more information:
I can't find the history why the author left such comment. We could run more tests based on you PAT enhancement, if it runs OK for both upstream QEMU and Android Emulator, it could be safe then.
If the "nonstandard solution" you mentioned is the case that HAXM handle APIC by disable rwx in page, the reason could be we doesn't support APICv like KVM yet.
Thus any operations on IRQL (which are quite frequent) will cause tons of CR8 access. To handle CR8 correctly, certain IRQs have to be handled as well. |
No, only i386 hax working code.
OK. I thought, since PAT was conciously disabled, there where issues with some OSes.
The problem is that Windows 10 x64 still doesn't work. When I wrote my initial question, I thought the reason was performance - too many vmexits and returns to usermode slowed the execution so much, that it looked like the OS hung. Later investigation showed, that there are many more HPET access vmexits, which return to usermode too, and a cycle in the code, which exit condition I'm still unable to figure out. The last post about CR8 problem was just a status report, that should be read as "Windows 10x64 does not work". |
The patch also needs sent to the mailing list, if you wish you enhancement upstreamed. 😄
We will run more tests based on you patch see any unexpected shows up. Currently I can't find any record discussing why PAT disabled in the initial version.
May be we can take one step at a time and continue the investigation. Enabling 32-bit Win10 is an excellent enhancement. I'm trying to figure out why I always hit an 0xA BSOD although seems like not introduced by your patch, however it blocks me the testing boot a 32-bit Win10. Then our QA colleague could run more tests and merge your PR. |
The version without the patch merged crashes too? |
QEMU develop mailing list is the place that reviewing QEMU HAX code. It is also available to discuss HAX related issues in HAXM GitHub. We did not actively check launchpad regularly.
Not all registers are saved and restored unless it is necessary, in consideration of both necessity and performance. The officially supported VM is Android Emulator and we have a test suite to cover most of the tests. For upstream QEMU, it works but is not guaranteed to run all OSes without problem. I have added the review comments in the commits inline. You may reference them and adjust some coding styles this time. e.g., space usage, comments style, parentheses alignment, etc. Thanks. |
Maybe submit a patch to qemu MAINTAINERS file and add this info there?
Yes, but immediately before saving register/MSR values to the snapshot, qemu should get actual values from haxm, but does this not.
So far I understand, qemu saves CPUArchState to the snapshot and it contains full state (all registers/MSRs). |
Did it have any problem using host returned value actually? If true, is it possible to replace the hard-coded values by the OR-operations of defined macros, rather than the instant numbers?
Sure, I agree.
We have submitted the patch to QEMU MAINTAINERS file.
To solve the issue in PR #204, you may add those required registers that you find for now. Maybe we will consider to add more specified necessary registers for HAXM according to the feature requirement in future. |
There was no problems using host returned values. So far I understand, qemu loads same values to kvm, so it should return these too. |
Since there is no problem found, we recommended to use host value directly but macros should be okay. Does KVM use instant values, too? |
This is an example from qemu: |
acce9c7
to
25e3cb9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for late review. The round only focused on the coding style and some of suggestions will be up to your customs. Thanks for your update.
core/include/hax_core_interface.h
Outdated
@@ -43,6 +43,7 @@ int vcpu_set_msr(struct vcpu_t *vcpu, uint64_t index, uint64_t value); | |||
int vcpu_get_msr(struct vcpu_t *vcpu, uint64_t index, uint64_t *value); | |||
int vcpu_put_fpu(struct vcpu_t *vcpu, struct fx_layout *fl); | |||
int vcpu_get_fpu(struct vcpu_t *vcpu, struct fx_layout *fl); | |||
int get_vcpu_state_size( struct vcpu_t *vcpu ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Rename the function to vcpu_get_state_size()
- Remove extra spaces around the parentheses
- Move this line down before vcpu_debug()
core/include/vcpu.h
Outdated
@@ -256,6 +257,7 @@ void vcpu_vmwrite_all(struct vcpu_t *vcpu, int force_vtlb_flush); | |||
|
|||
int vcpu_teardown(struct vcpu_t *vcpu); | |||
|
|||
int get_vcpu_state_size( struct vcpu_t *vcpu ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same changes apply here.
core/vcpu.c
Outdated
@@ -3964,6 +3964,13 @@ static int _copy_desc(segment_desc_t *old, segment_desc_t *new) | |||
return flags; | |||
} | |||
|
|||
int get_vcpu_state_size( struct vcpu_t *vcpu ) | |||
{ | |||
if( vcpu->vm->features & VM_FEATURES_CR8 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Add a space after
if
- Remove extra spaces around parentheses
core/vcpu.c
Outdated
@@ -3999,6 +4006,9 @@ int vcpu_get_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate) | |||
_copy_desc(&state->_gdt, &ustate->_gdt); | |||
_copy_desc(&state->_idt, &ustate->_idt); | |||
|
|||
if( vcpu->vm->features & VM_FEATURES_CR8 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same changes apply here.
core/vcpu.c
Outdated
@@ -4124,6 +4134,9 @@ int vcpu_set_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate) | |||
VMWRITE_DESC(vcpu, IDTR, state->_idt); | |||
} | |||
|
|||
if( vcpu->vm->features & VM_FEATURES_CR8 ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
platforms/windows/hax_entry.c
Outdated
@@ -398,15 +398,15 @@ NTSTATUS HaxVcpuControl(PDEVICE_OBJECT DeviceObject, | |||
} | |||
case HAX_VCPU_GET_REGS: { | |||
struct vcpu_state_t *vc_state; | |||
if(outBufLength < sizeof(struct vcpu_state_t)) { | |||
infret = get_vcpu_state_size(cvcpu); | |||
if(outBufLength < infret) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a space after if
.
@@ -84,6 +84,7 @@ struct hstate { | |||
uint64_t dr7; | |||
// CR0 | |||
bool cr0_ts; | |||
uint64_t _pat; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you think pat_msr
is better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there is already _efer named in the same way in the same struct. There are other PATs - in vcpu it is called cr_pat and in hstate_compare it is called pat_msr. It helps to distinct them by names. If it is necessary to use common names, it should be done as a standalone feature for the entire code.
core/vcpu.c
Outdated
@@ -3605,6 +3612,15 @@ static int misc_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val) | |||
return 1; | |||
} | |||
|
|||
static inline bool pat_valid(uint64_t val) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you think is_pat_valid()
is better for bool
function?
core/vcpu.c
Outdated
@@ -3763,7 +3779,15 @@ static int handle_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val, | |||
break; | |||
} | |||
case IA32_CR_PAT: { | |||
//Attempting to write an undefined memory type encoding into the PAT causes a | |||
//general-protection (#GP) exception to be generated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a space after slashes and pay attention to the line wrap to ensure the long line does not exceed column 80.
// Attempting to write an undefined memory type encoding into the
// PAT causes a general-protection (#GP) exception to be generated.
|
Signed-off-by: Alexey Romko <nevilad@yahoo.com>
Signed-off-by: Alexey Romko <nevilad@yahoo.com>
Signed-off-by: Alexey Romko <nevilad@yahoo.com>
Hi @wayne-ma, my results are:
Looks like it is not possible to change drive type after installation. |
Hi @nevilad ,yes, I almost got the same result. Regarding the 3rd * scenario, I noticed that I could boot up the OS after removing this option '-device scsi-hd,bus=scsihw0.0,drive=scsi0,id=scsi0', I am not sure if it is a must for scsi device. Anyway, paste my cmd for your reference, |
@nevilad, thanks for your update. Could you submit the QEMU patch to the community as well and CC the maintainers as previous list so that we can receive it? Thanks. |
I've sent the qemu patch 29.02 to qemu-devel@nongnu.org and CC wenchao.wang@intel.com, colin.xu@intel.com. Did you not receive it? |
This issue can be closed - #59 |
Created an issue for SCSI discussion #270. |
Sure, I received the QEMU patch and will give you feedback soon. Thanks for your notification. |
@nevilad, after we tested this patch further, we found that the Windows guest could not be launched again. When (a == 4) and (c == 0) in handle_cpuid_virtual(), the log is as below,
After applying a part of your previous patch as below, the Windows guest can be booted up successfully.
So using the host value directly will not work, at least EAX value needs to change. Could you submit another patch to resolve this issue? You may decide whether to fully inherit the values from QEMU for other cases, but using macros for assignments. Sorry for not finding this issue before merging your patch. Thanks. |
Created #272, this should help when passing host values to the guest. Your cache output says your host has 6 cores and the guest only one. |
Added more supported features to cpuid and PAT MSR support. This enables to install and run a windows10 x86 guest. Windows10 x64 guests are not yet working, since the amount of CR8 reads\writes is very big and the loading process stucks on handling them.
The patch was tested on a windows 7 and windows 10 guests on a windows10x64 host.
There are open questions:
if (cpu_has_feature(X86_FEATURE_AESNI)) {
cpuid_1_features_ecx |= FEATURE(AESNI);
}
Is this really necessary, given that the function returns the intersection of cpuid_1_features_ecx and the value returned by host cpuid:
state->_ecx = (cpuid_1_features_ecx & state->_ecx) | FEATURE(HYPERVISOR);
?