mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-11-04 14:14:57 +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>
 | 
			
		||||
#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,
 | 
			
		||||
                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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1986,22 +2012,20 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
 | 
			
		|||
{
 | 
			
		||||
    X86CPU *cpu = X86_CPU(cs->uc, cs);
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    // 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;
 | 
			
		||||
 | 
			
		||||
    while (featurestr) {
 | 
			
		||||
        char *val;
 | 
			
		||||
        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] == '-') {
 | 
			
		||||
            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, '='))) {
 | 
			
		||||
            *val = 0; val++;
 | 
			
		||||
            feat2prop(featurestr);
 | 
			
		||||
| 
						 | 
				
			
			@ -2030,29 +2054,23 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
 | 
			
		|||
        }
 | 
			
		||||
        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];
 | 
			
		||||
    uint32_t r;
 | 
			
		||||
 | 
			
		||||
    if (tcg_enabled(uc)) {
 | 
			
		||||
        return wi->tcg_features;
 | 
			
		||||
        r = wi->tcg_features;
 | 
			
		||||
    } else {
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
    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];
 | 
			
		||||
        env->features[w] &= host_feat;
 | 
			
		||||
        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);
 | 
			
		||||
    CPUX86State *env = &cpu->env;
 | 
			
		||||
    Error *local_err = NULL;
 | 
			
		||||
    FeatureWord w;
 | 
			
		||||
 | 
			
		||||
    if (cpu->apic_id < 0) {
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*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
 | 
			
		||||
     * CPUID[1].EDX.
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1172,6 +1172,11 @@ typedef struct X86CPU {
 | 
			
		|||
       user */
 | 
			
		||||
    struct DeviceState *apic_state;
 | 
			
		||||
    struct MemoryRegion *cpu_as_root;
 | 
			
		||||
 | 
			
		||||
    /* Features to be added */
 | 
			
		||||
    FeatureWordArray plus_features;
 | 
			
		||||
    /* Features to be removed */
 | 
			
		||||
    FeatureWordArray minus_features;
 | 
			
		||||
} X86CPU;
 | 
			
		||||
 | 
			
		||||
static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue