int init_domain_cpuid_policy(struct domain *d)
{
- unsigned int i;
-
d->arch.cpuid = xmalloc(struct cpuid_policy);
if ( !d->arch.cpuid )
recalculate_cpuid_policy(d);
- for ( i = 0; i < MAX_CPUID_INPUT; i++ )
- {
- d->arch.cpuid->legacy[i].input[0] = XEN_CPUID_INPUT_UNUSED;
- d->arch.cpuid->legacy[i].input[1] = XEN_CPUID_INPUT_UNUSED;
- }
-
return 0;
}
-static void domain_cpuid(const struct domain *d, uint32_t leaf,
- uint32_t subleaf, struct cpuid_leaf *res)
-{
- unsigned int i;
-
- for ( i = 0; i < MAX_CPUID_INPUT; i++ )
- {
- xen_domctl_cpuid_t *cpuid = &d->arch.cpuid->legacy[i];
-
- if ( (cpuid->input[0] == leaf) &&
- ((cpuid->input[1] == XEN_CPUID_INPUT_UNUSED) ||
- (cpuid->input[1] == subleaf)) )
- {
- *res = (struct cpuid_leaf){ cpuid->eax, cpuid->ebx,
- cpuid->ecx, cpuid->edx };
- return;
- }
- }
-}
-
-static void pv_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
-{
- struct vcpu *curr = current;
- struct domain *currd = curr->domain;
-
- if ( !is_control_domain(currd) && !is_hardware_domain(currd) )
- domain_cpuid(currd, leaf, subleaf, res);
- else
- cpuid_count_leaf(leaf, subleaf, res);
-
- switch ( leaf )
- {
- case 0x0 ... XSTATE_CPUID:
- case 0x80000000 ... 0xffffffff:
- ASSERT_UNREACHABLE();
- /* Now handled in guest_cpuid(). */
- }
-}
-
-static void hvm_cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid_leaf *res)
-{
- struct vcpu *v = current;
- struct domain *d = v->domain;
-
- domain_cpuid(d, leaf, subleaf, res);
-
- switch ( leaf )
- {
- case 0x0 ... XSTATE_CPUID:
- case 0x80000000 ... 0xffffffff:
- ASSERT_UNREACHABLE();
- /* Now handled in guest_cpuid(). */
- }
-}
-
void guest_cpuid(const struct vcpu *v, uint32_t leaf,
uint32_t subleaf, struct cpuid_leaf *res)
{
break;
default:
- goto legacy;
-
- case 0x0 ... 0x3:
- case 0x5 ... 0x6:
- case 0x8 ... 0xc:
*res = p->basic.raw[leaf];
break;
}
res->a = (res->d & v->arch.hvm_svm.guest_lwp_cfg) | 1;
break;
}
-
- /* Done. */
- return;
-
- legacy:
- /* {hvm,pv}_cpuid() have this expectation. */
- ASSERT(v == current);
- (is_hvm_domain(d) ? hvm_cpuid : pv_cpuid)(leaf, subleaf, res);
}
static void __init __maybe_unused build_assertions(void)
return iop->remain ? -EFAULT : 0;
}
-static int update_legacy_cpuid_array(struct domain *d,
- const xen_domctl_cpuid_t *ctl)
-{
- xen_domctl_cpuid_t *cpuid, *unused = NULL;
- unsigned int i;
-
- /* Try to insert ctl into d->arch.cpuids[] */
- for ( i = 0; i < MAX_CPUID_INPUT; i++ )
- {
- cpuid = &d->arch.cpuid->legacy[i];
-
- if ( cpuid->input[0] == XEN_CPUID_INPUT_UNUSED )
- {
- if ( !unused )
- unused = cpuid;
- continue;
- }
-
- if ( (cpuid->input[0] == ctl->input[0]) &&
- ((cpuid->input[1] == XEN_CPUID_INPUT_UNUSED) ||
- (cpuid->input[1] == ctl->input[1])) )
- break;
- }
-
- if ( !(ctl->eax | ctl->ebx | ctl->ecx | ctl->edx) )
- {
- if ( i < MAX_CPUID_INPUT )
- cpuid->input[0] = XEN_CPUID_INPUT_UNUSED;
- }
- else if ( i < MAX_CPUID_INPUT )
- *cpuid = *ctl;
- else if ( unused )
- *unused = *ctl;
- else
- return -ENOENT;
-
- return 0;
-}
-
static int update_domain_cpuid_info(struct domain *d,
const xen_domctl_cpuid_t *ctl)
{
struct cpuid_policy *p = d->arch.cpuid;
const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx };
- int rc, old_vendor = p->x86_vendor;
+ int old_vendor = p->x86_vendor;
/*
* Skip update for leaves we don't care about. This avoids the overhead
return 0;
}
- rc = update_legacy_cpuid_array(d, ctl);
- if ( rc )
- return rc;
-
/* Insert ctl data into cpuid_policy. */
switch ( ctl->input[0] )
{
struct cpuid_policy
{
- /*
- * WARNING: During the CPUID transition period, not all information here
- * is accurate. The following items are accurate, and can be relied upon.
- *
- * Global *_policy objects:
- *
- * - Guest accurate:
- * - All of the feat, xstate and extd unions
- * - max_{,sub}leaf
- * - All FEATURESET_* words
- * - Short vendor infomation
- *
- * Per-domain objects:
- *
- * - Guest accurate:
- * - All of the feat, xstate and extd unions
- * - max_{,sub}leaf
- * - All FEATURESET_* words
- * - Short vendor infomation
- *
- * Everything else should be considered inaccurate, and not necesserily 0.
- */
-
#define DECL_BITFIELD(word) _DECL_BITFIELD(FEATURESET_ ## word)
#define _DECL_BITFIELD(x) __DECL_BITFIELD(x)
#define __DECL_BITFIELD(x) CPUID_BITFIELD_ ## x
/* Value calculated from raw data above. */
uint8_t x86_vendor;
-
- /* Temporary: Legacy data array. */
-#define MAX_CPUID_INPUT 40
- xen_domctl_cpuid_t legacy[MAX_CPUID_INPUT];
};
/* Fill in a featureset bitmap from a CPUID policy. */