-
Notifications
You must be signed in to change notification settings - Fork 884
Enable setting CPUID feature for guest VCPUs #277
Conversation
platforms/windows/hax_entry.c
Outdated
if (inBufLength < sizeof(struct hax_cpuid) + | ||
cpuid->total * sizeof(struct hax_cpuid_entry)) { |
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.
This will be a crash, if inBufLength is zero, due to access to cpuid->total field.
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.
Good catch. I will update the code immediately. Thanks for your review.
// * The CPUID feature set is always same for each vCPU. A CPUID instruction | ||
// executed on any core will get the same result. | ||
// * All vCPUs share the unique memory, which is actually allocated by the | ||
// first vCPU created by VM. If any vCPU sets features in this field, all | ||
// vCPUs will change accordingly. |
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.
Why save this data in vCPU if all of them share same memory? Why not in vm?
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, saving in VM has the same effect. But we considered that this IOCTL should be belonging to VCPU as it is CPUID.
cpuid_get_guest_features(vcpu->guest_cpuid, &cpuid_1_features_ecx, | ||
&cpuid_1_features_edx, | ||
&cpuid_8000_0001_features_ecx, | ||
&cpuid_8000_0001_features_edx); |
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.
SET_CPUID interface allows to set all output registers for any cpuid codes. But the only used data is ecx and edx for code 1 and 80000001. Why?
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.
Good question. Other function code can be added one by one in future. We did not open the setting channels for all codes as HAXM still has not supported for all features in current implementation.
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.
I think #271 should be called set_cpuid and this feature set_cpuid_feature_flags. How Android Studio will use this feature? Who adds ioctl calls there?
if (entry->ecx != cpuid->feature_1_ecx || | ||
entry->edx != cpuid->feature_1_edx) { |
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.
There are 3 types of action with the actual supported features and the ones provided in ioctl:
- Use intersection and ignore mismatch. This is currently used.
- Use intersection and return error in case of mismatch. The user wanted the provided features and we can't support these.
- Use provided features, no intersection with supported. It is users responsibility when the provided features are not supported by the cpu. This is the case of KVM, but it supports a lot of features, so the problems will be in case when the CPU does not support them.
Would be good add this as flags to the interface, at least 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.
Thanks for your suggestion. We will consider these cases in future.
hax_log(HAX_LOGI, "%s: eax: %08lx, ebx: %08lx, ecx: %08lx, edx: %08lx\n", | ||
__func__, entry->eax, entry->ebx, entry->ecx, entry->edx); | ||
|
||
cpuid->feature_8000_0001_edx = entry->edx; |
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.
ecx is not merged. CUrrently supported by haxm bits are zero but this will change 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.
You are right. This version is based on the current implementation and this feature will be easy to extend 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.
We will update the implementation of CPUID and include a hash table for feature set, which will add ecx or other register settings. It will not change the HAX_VCPU_IOCTL_SET_CPUID interface. The patch will be ready once the current release completes.
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.
A hash table for searching entries by find_cpuid_entry? There are currently only two codes with such flags, a vector is sufficient for this task.
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 same data structure hax_cpuid_entry vector for storing in hax_cpuid_t for future extensions in this version. The find_cpuid_entry() will not change.
const uint32_t kFixedFeatures = | ||
FEATURE(MCE) | | ||
FEATURE(APIC) | | ||
FEATURE(MTRR) | | ||
FEATURE(PAT); | ||
|
||
cpuid->feature_1_edx |= kFixedFeatures; |
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.
Silently adding flags to the ones provided by the user without even log this. I think when the user want to clear these bits this should be a error.
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.
Actually these flags were referred from your commits. As for logs, it will always output the unchanged bits as warning in the caller functions, such as cpuid_set_0000_0001().
Seems like you need a way to set only ecx/edx for cpuid codes 1 and 80000001. How Android Studio will use this feature? |
This PR is only the first version for CPUID feature, as HAXM is open source, you are welcome to suggest the interfaces or implementations if there is any requirement. Android Emulator will use this feature as below user space patch 987306.
We will continue to provide the user space code to add IOCTL calls for Android Emulator. |
9152ace
to
6f733a3
Compare
Ok to verify |
The Android patch is called "Enable whitelisted CPU options by default if host supports them" and mentions the need for CPUID_EXT_AES, CPUID_EXT_PCLMULQDQ and CPUID_FXSR features. By default hax returns intersection of supported by CPU and hax features. This PR removes feature bits if they are not supported by CPU and hax. So using this PR it is only possible to remove already supported features. Is this OK? |
platforms/windows/hax_entry.c
Outdated
if (inBufLength == 0 || inBufLength < sizeof(struct hax_cpuid) + | ||
cpuid->total * sizeof(struct hax_cpuid_entry)) { |
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.
This is better:
if (inBufLength < sizeof(struct hax_cpuid) || inBufLength < sizeof(struct hax_cpuid) +
cpuid->total * sizeof(struct hax_cpuid_entry)) {
total is first member with 4 bytes size. So any inBufLength less than 4 bytes will crash.
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 your point. Actually, below expressions should be more exact as sizeof(struct hax_cpuid) is 8. Anyway, I will adopt your suggestion.
if (inBufLength < sizeof(cpuid->total) || ...)
or if (inBufLength < sizeof(uint32_t) || ...)
I totally agree with your opinion. In the earlier design of this PR, we would have set the features out of current supported scope. But we found that if user set any value, which feature has not been implemented by HAXM, and then it would result in regression. Just as the feature FEATURE(TSC_DEADLINE), I once asked you in my review comments for PR #271. We will attempt to extend the supported feature set in future after more verification. In future, probably we will separate the default feature set from the supported feature set. Then user can add or remove features by calling this IOCTL. Currently, it is OK to only remove supported features.
Yes, you are right. Actually, this feature requirement came before the FEATURE(PCLMULQDQ) was added. We intended to enable such features by calling this interface. Due to aforementioned reasons, we screened the unsupported features out in this version. We will consider improving the current framework to meet more requirements. Any of your further input will be important for us and your contribution will be welcome. Thanks. |
Add a new IOCTL HAX_VCPU_IOCTL_SET_CPUID to enable setting CPUID features for guest vCPUs. Instead of initializing guest CPUID once by the static features set, this feature will support dynamically setting guest CPUID features during the runtime of VM. The implementation refers to Intel SDM Vol. 2A 3.2 CPUID. * This version implements corresponding interfaces and data structures in CPUID module and completes Windows platform support. * Based on the current implmentation, it only supports to set the guest CPUID features when the initial value of EAX register is 01H or 80000001H. Signed-off-by: Wenchao Wang <[email protected]>
Enables setting CPUID features for guest vCPUs in macOS platform. Signed-off-by: Wenchao Wang <[email protected]>
Enables setting CPUID features for guest vCPUs in Linux platform. Signed-off-by: Wenchao Wang <[email protected]>
Add the capability flag HAX_CAP_CPUID to indicate the CPUID feature is already supported. This capability information is used for user space query. Signed-off-by: Wenchao Wang <[email protected]>
Android Emulator may dynamically extend the CPUID feature set of VCPU at guest runtime via x86_cpu_update_enable_features() ($AOSP/external/qemu/target/i386/cpu.c). It will invoke this IOCTL to set guest CPUID features, which is statically initialized in HAXM. The HAX_VCPU_IOCTL_SET_CPUID specification includes following aspects: * IOCTL definition and description * Parameters * Error codes * Interface availability Signed-off-by: Wenchao Wang <[email protected]>
NetBSD support is missing. I can test it.. but is there a qemu support? |
This feature is made for Android Studio. Qemu support will not be added. I update my PR and then it can be tested. |
OK. I'm going to submit a patch soon. |
This PR also broke building on NetBSD. |
@krytarowski Thanks for your reply. It supports QEMU and I have shared the user space patches for QEMU here. You input will be welcome. |
Add a new IOCTL HAX_VCPU_IOCTL_SET_CPUID to enable setting CPUID features for guest vCPUs. Instead of initializing guest CPUID once by the static features set, this feature will support dynamically setting guest CPUID features during the runtime of VM. The implementation refers to Intel SDM Vol. 2A 3.2 CPUID.