KVM: selftests: Split out kvm_cpuid2_size() from allocate_kvm_cpuid2()
Split out the computation of the effective size of a kvm_cpuid2 struct from allocate_kvm_cpuid2(), and modify both to take an arbitrary number of entries. Future commits will add caching of a vCPU's CPUID model, and will (a) be able to precisely size the entries array, and (b) will need to know the effective size of the struct in order to copy to/from the cache. Expose the helpers so that the Hyper-V Features test can use them in the (somewhat distant) future. The Hyper-V test very, very subtly relies on propagating CPUID info across vCPU instances, and will need to make a copy of the previous vCPU's CPUID information when it switches to using the per-vCPU cache. Alternatively, KVM could provide helpers to duplicate and/or copy a kvm_cpuid2 instance, but each is literally a single line of code if the helpers are exposed, and it's not like the size of kvm_cpuid2 is secret knowledge. Signed-off-by: Sean Christopherson <seanjc@google.com> Link: https://lore.kernel.org/r/20220614200707.3315957-18-seanjc@google.com
This commit is contained in:
@@ -595,6 +595,29 @@ static inline bool kvm_cpu_has(struct kvm_x86_cpu_feature feature)
|
|||||||
return kvm_cpuid_has(kvm_get_supported_cpuid(), feature);
|
return kvm_cpuid_has(kvm_get_supported_cpuid(), feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline size_t kvm_cpuid2_size(int nr_entries)
|
||||||
|
{
|
||||||
|
return sizeof(struct kvm_cpuid2) +
|
||||||
|
sizeof(struct kvm_cpuid_entry2) * nr_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a "struct kvm_cpuid2* instance, with the 0-length arrary of
|
||||||
|
* entries sized to hold @nr_entries. The caller is responsible for freeing
|
||||||
|
* the struct.
|
||||||
|
*/
|
||||||
|
static inline struct kvm_cpuid2 *allocate_kvm_cpuid2(int nr_entries)
|
||||||
|
{
|
||||||
|
struct kvm_cpuid2 *cpuid;
|
||||||
|
|
||||||
|
cpuid = malloc(kvm_cpuid2_size(nr_entries));
|
||||||
|
TEST_ASSERT(cpuid, "-ENOMEM when allocating kvm_cpuid2");
|
||||||
|
|
||||||
|
cpuid->nent = nr_entries;
|
||||||
|
|
||||||
|
return cpuid;
|
||||||
|
}
|
||||||
|
|
||||||
struct kvm_cpuid2 *vcpu_get_cpuid(struct kvm_vcpu *vcpu);
|
struct kvm_cpuid2 *vcpu_get_cpuid(struct kvm_vcpu *vcpu);
|
||||||
|
|
||||||
static inline int __vcpu_set_cpuid(struct kvm_vcpu *vcpu,
|
static inline int __vcpu_set_cpuid(struct kvm_vcpu *vcpu,
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#define DEFAULT_CODE_SELECTOR 0x8
|
#define DEFAULT_CODE_SELECTOR 0x8
|
||||||
#define DEFAULT_DATA_SELECTOR 0x10
|
#define DEFAULT_DATA_SELECTOR 0x10
|
||||||
|
|
||||||
|
#define MAX_NR_CPUID_ENTRIES 100
|
||||||
|
|
||||||
vm_vaddr_t exception_handlers;
|
vm_vaddr_t exception_handlers;
|
||||||
|
|
||||||
static void regs_dump(FILE *stream, struct kvm_regs *regs, uint8_t indent)
|
static void regs_dump(FILE *stream, struct kvm_regs *regs, uint8_t indent)
|
||||||
@@ -672,40 +674,6 @@ struct kvm_vcpu *vm_arch_vcpu_recreate(struct kvm_vm *vm, uint32_t vcpu_id)
|
|||||||
return vcpu;
|
return vcpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate an instance of struct kvm_cpuid2
|
|
||||||
*
|
|
||||||
* Input Args: None
|
|
||||||
*
|
|
||||||
* Output Args: None
|
|
||||||
*
|
|
||||||
* Return: A pointer to the allocated struct. The caller is responsible
|
|
||||||
* for freeing this struct.
|
|
||||||
*
|
|
||||||
* Since kvm_cpuid2 uses a 0-length array to allow a the size of the
|
|
||||||
* array to be decided at allocation time, allocation is slightly
|
|
||||||
* complicated. This function uses a reasonable default length for
|
|
||||||
* the array and performs the appropriate allocation.
|
|
||||||
*/
|
|
||||||
static struct kvm_cpuid2 *allocate_kvm_cpuid2(void)
|
|
||||||
{
|
|
||||||
struct kvm_cpuid2 *cpuid;
|
|
||||||
int nent = 100;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
size = sizeof(*cpuid);
|
|
||||||
size += nent * sizeof(struct kvm_cpuid_entry2);
|
|
||||||
cpuid = malloc(size);
|
|
||||||
if (!cpuid) {
|
|
||||||
perror("malloc");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuid->nent = nent;
|
|
||||||
|
|
||||||
return cpuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* KVM Supported CPUID Get
|
* KVM Supported CPUID Get
|
||||||
*
|
*
|
||||||
@@ -725,7 +693,7 @@ struct kvm_cpuid2 *kvm_get_supported_cpuid(void)
|
|||||||
if (cpuid)
|
if (cpuid)
|
||||||
return cpuid;
|
return cpuid;
|
||||||
|
|
||||||
cpuid = allocate_kvm_cpuid2();
|
cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES);
|
||||||
kvm_fd = open_kvm_dev_path_or_exit();
|
kvm_fd = open_kvm_dev_path_or_exit();
|
||||||
|
|
||||||
kvm_ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
|
kvm_ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
|
||||||
@@ -781,7 +749,7 @@ struct kvm_cpuid2 *vcpu_get_cpuid(struct kvm_vcpu *vcpu)
|
|||||||
int max_ent;
|
int max_ent;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
cpuid = allocate_kvm_cpuid2();
|
cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES);
|
||||||
max_ent = cpuid->nent;
|
max_ent = cpuid->nent;
|
||||||
|
|
||||||
for (cpuid->nent = 1; cpuid->nent <= max_ent; cpuid->nent++) {
|
for (cpuid->nent = 1; cpuid->nent <= max_ent; cpuid->nent++) {
|
||||||
@@ -1295,7 +1263,7 @@ struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void)
|
|||||||
if (cpuid)
|
if (cpuid)
|
||||||
return cpuid;
|
return cpuid;
|
||||||
|
|
||||||
cpuid = allocate_kvm_cpuid2();
|
cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES);
|
||||||
kvm_fd = open_kvm_dev_path_or_exit();
|
kvm_fd = open_kvm_dev_path_or_exit();
|
||||||
|
|
||||||
kvm_ioctl(kvm_fd, KVM_GET_SUPPORTED_HV_CPUID, cpuid);
|
kvm_ioctl(kvm_fd, KVM_GET_SUPPORTED_HV_CPUID, cpuid);
|
||||||
@@ -1314,9 +1282,7 @@ void vcpu_set_hv_cpuid(struct kvm_vcpu *vcpu)
|
|||||||
cpuid_sys = kvm_get_supported_cpuid();
|
cpuid_sys = kvm_get_supported_cpuid();
|
||||||
cpuid_hv = kvm_get_supported_hv_cpuid();
|
cpuid_hv = kvm_get_supported_hv_cpuid();
|
||||||
|
|
||||||
cpuid_full = malloc(sizeof(*cpuid_full) +
|
cpuid_full = allocate_kvm_cpuid2(cpuid_sys->nent + cpuid_hv->nent);
|
||||||
(cpuid_sys->nent + cpuid_hv->nent) *
|
|
||||||
sizeof(struct kvm_cpuid_entry2));
|
|
||||||
if (!cpuid_full) {
|
if (!cpuid_full) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
abort();
|
abort();
|
||||||
@@ -1343,7 +1309,7 @@ struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vcpu *vcpu)
|
|||||||
{
|
{
|
||||||
static struct kvm_cpuid2 *cpuid;
|
static struct kvm_cpuid2 *cpuid;
|
||||||
|
|
||||||
cpuid = allocate_kvm_cpuid2();
|
cpuid = allocate_kvm_cpuid2(MAX_NR_CPUID_ENTRIES);
|
||||||
|
|
||||||
vcpu_ioctl(vcpu, KVM_GET_SUPPORTED_HV_CPUID, cpuid);
|
vcpu_ioctl(vcpu, KVM_GET_SUPPORTED_HV_CPUID, cpuid);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user