mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-11-04 09:35:05 +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