mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-24 22:15:07 +00:00
target-i386: Move features logic that requires CPUState to realize time
Making x86_cpu_parse_featurestr() a pure convertor of legacy feature string into global properties, needs it to be called before a CPU instance is created so parser shouldn't modify CPUState directly or access it at all. Hence move current hack that directly pokes into CPUState, to set/unset +-feats, from parser to CPU's realize method. Backports commit dc15c0517b010a9444a2c05794dae980f2a2cbd9 from qemu
This commit is contained in:
parent
b9ca5c4d33
commit
800b28483b
|
@ -589,6 +589,31 @@ const char *get_register_name_32(unsigned int reg)
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the set of feature flags that are supported and migratable by
|
||||||
|
* QEMU, for a given FeatureWord.
|
||||||
|
*/
|
||||||
|
static uint32_t x86_cpu_get_migratable_flags(FeatureWord w)
|
||||||
|
{
|
||||||
|
FeatureWordInfo *wi = &feature_word_info[w];
|
||||||
|
uint32_t r = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
uint32_t f = 1U << i;
|
||||||
|
/* If the feature name is unknown, it is not supported by QEMU yet */
|
||||||
|
if (!wi->feat_names[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Skip features known to QEMU, but explicitly marked as unmigratable */
|
||||||
|
if (wi->unmigratable_flags & f) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
r |= f;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void host_cpuid(uint32_t function, uint32_t count,
|
void host_cpuid(uint32_t function, uint32_t count,
|
||||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||||
{
|
{
|
||||||
|
@ -1626,7 +1651,8 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t x86_cpu_get_supported_feature_word(struct uc_struct *uc, FeatureWord w);
|
static uint32_t x86_cpu_get_supported_feature_word(struct uc_struct *uc,
|
||||||
|
FeatureWord w, bool migratable);
|
||||||
|
|
||||||
static void report_unavailable_features(FeatureWord w, uint32_t mask)
|
static void report_unavailable_features(FeatureWord w, uint32_t mask)
|
||||||
{
|
{
|
||||||
|
@ -1986,22 +2012,20 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(cs->uc, cs);
|
X86CPU *cpu = X86_CPU(cs->uc, cs);
|
||||||
char *featurestr; /* Single 'key=value" string being parsed */
|
char *featurestr; /* Single 'key=value" string being parsed */
|
||||||
FeatureWord w;
|
|
||||||
/* Features to be added */
|
|
||||||
FeatureWordArray plus_features = { 0 };
|
|
||||||
/* Features to be removed */
|
|
||||||
FeatureWordArray minus_features = { 0 };
|
|
||||||
CPUX86State *env = &cpu->env;
|
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
// Unicorn: added for consistent zeroing out
|
||||||
|
memset(cpu->plus_features, 0, sizeof(cpu->plus_features));
|
||||||
|
memset(cpu->minus_features, 0, sizeof(cpu->minus_features));
|
||||||
|
|
||||||
featurestr = features ? strtok(features, ",") : NULL;
|
featurestr = features ? strtok(features, ",") : NULL;
|
||||||
|
|
||||||
while (featurestr) {
|
while (featurestr) {
|
||||||
char *val;
|
char *val;
|
||||||
if (featurestr[0] == '+') {
|
if (featurestr[0] == '+') {
|
||||||
add_flagname_to_bitmaps(featurestr + 1, plus_features, &local_err);
|
add_flagname_to_bitmaps(featurestr + 1, cpu->plus_features, &local_err);
|
||||||
} else if (featurestr[0] == '-') {
|
} else if (featurestr[0] == '-') {
|
||||||
add_flagname_to_bitmaps(featurestr + 1, minus_features, &local_err);
|
add_flagname_to_bitmaps(featurestr + 1, cpu->minus_features, &local_err);
|
||||||
} else if ((val = strchr(featurestr, '='))) {
|
} else if ((val = strchr(featurestr, '='))) {
|
||||||
*val = 0; val++;
|
*val = 0; val++;
|
||||||
feat2prop(featurestr);
|
feat2prop(featurestr);
|
||||||
|
@ -2030,29 +2054,23 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
|
||||||
}
|
}
|
||||||
featurestr = strtok(NULL, ",");
|
featurestr = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->host_features) {
|
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
|
||||||
env->features[w] =
|
|
||||||
x86_cpu_get_supported_feature_word(env->uc, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
|
||||||
env->features[w] |= plus_features[w];
|
|
||||||
env->features[w] &= ~minus_features[w];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t x86_cpu_get_supported_feature_word(struct uc_struct *uc, FeatureWord w)
|
static uint32_t x86_cpu_get_supported_feature_word(struct uc_struct *uc,
|
||||||
|
FeatureWord w, bool migratable_only)
|
||||||
{
|
{
|
||||||
FeatureWordInfo *wi = &feature_word_info[w];
|
FeatureWordInfo *wi = &feature_word_info[w];
|
||||||
|
uint32_t r;
|
||||||
|
|
||||||
if (tcg_enabled(uc)) {
|
if (tcg_enabled(uc)) {
|
||||||
return wi->tcg_features;
|
r = wi->tcg_features;
|
||||||
} else {
|
} else {
|
||||||
return ~0;
|
return ~0;
|
||||||
}
|
}
|
||||||
|
if (migratable_only) {
|
||||||
|
r &= x86_cpu_get_migratable_flags(w);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2067,7 +2085,7 @@ static int x86_cpu_filter_features(X86CPU *cpu)
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
uint32_t host_feat = x86_cpu_get_supported_feature_word(env->uc, w);
|
uint32_t host_feat = x86_cpu_get_supported_feature_word(env->uc, w, cpu->migratable);
|
||||||
uint32_t requested_features = env->features[w];
|
uint32_t requested_features = env->features[w];
|
||||||
env->features[w] &= host_feat;
|
env->features[w] &= host_feat;
|
||||||
cpu->filtered_features[w] = requested_features & ~env->features[w];
|
cpu->filtered_features[w] = requested_features & ~env->features[w];
|
||||||
|
@ -2814,6 +2832,7 @@ static int x86_cpu_realizefn(struct uc_struct *uc, DeviceState *dev, Error **err
|
||||||
X86CPUClass *xcc = X86_CPU_GET_CLASS(uc, dev);
|
X86CPUClass *xcc = X86_CPU_GET_CLASS(uc, dev);
|
||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
FeatureWord w;
|
||||||
|
|
||||||
if (cpu->apic_id < 0) {
|
if (cpu->apic_id < 0) {
|
||||||
error_setg(errp, "apic-id property was not initialized properly");
|
error_setg(errp, "apic-id property was not initialized properly");
|
||||||
|
@ -2824,6 +2843,23 @@ static int x86_cpu_realizefn(struct uc_struct *uc, DeviceState *dev, Error **err
|
||||||
env->cpuid_level = 7;
|
env->cpuid_level = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*TODO: cpu->host_features incorrectly overwrites features
|
||||||
|
* set using "feat=on|off". Once we fix this, we can convert
|
||||||
|
* plus_features & minus_features to global properties
|
||||||
|
* inside x86_cpu_parse_featurestr() too.
|
||||||
|
*/
|
||||||
|
if (cpu->host_features) {
|
||||||
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
|
env->features[w] =
|
||||||
|
x86_cpu_get_supported_feature_word(uc, w, cpu->migratable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
|
cpu->env.features[w] |= cpu->plus_features[w];
|
||||||
|
cpu->env.features[w] &= ~cpu->minus_features[w];
|
||||||
|
}
|
||||||
|
|
||||||
/* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
|
/* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
|
||||||
* CPUID[1].EDX.
|
* CPUID[1].EDX.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1172,6 +1172,11 @@ typedef struct X86CPU {
|
||||||
user */
|
user */
|
||||||
struct DeviceState *apic_state;
|
struct DeviceState *apic_state;
|
||||||
struct MemoryRegion *cpu_as_root;
|
struct MemoryRegion *cpu_as_root;
|
||||||
|
|
||||||
|
/* Features to be added */
|
||||||
|
FeatureWordArray plus_features;
|
||||||
|
/* Features to be removed */
|
||||||
|
FeatureWordArray minus_features;
|
||||||
} X86CPU;
|
} X86CPU;
|
||||||
|
|
||||||
static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
|
static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
|
||||||
|
|
Loading…
Reference in a new issue