@@ -147,6 +147,26 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset)
g_assert_not_reached();
}
+static const char *cpu_cfg_ext_get_name(uint32_t ext_offset)
+{
+ const RISCVCPUMultiExtConfig *feat;
+ const RISCVIsaExtData *edata;
+
+ for (edata = isa_edata_arr; edata->name != NULL; edata++) {
+ if (edata->ext_enable_offset == ext_offset) {
+ return edata->name;
+ }
+ }
+
+ for (feat = riscv_cpu_named_features; feat->name != NULL; feat++) {
+ if (feat->offset == ext_offset) {
+ return feat->name;
+ }
+ }
+
+ g_assert_not_reached();
+}
+
static bool cpu_cfg_offset_is_named_feat(uint32_t ext_offset)
{
const RISCVCPUMultiExtConfig *feat;
@@ -706,6 +726,54 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
riscv_cpu_disable_priv_spec_isa_exts(cpu);
}
+static void riscv_cpu_validate_profile(RISCVCPU *cpu,
+ RISCVCPUProfile *profile)
+{
+ const char *warn_msg = "Profile %s mandates disabled extension %s";
+ bool send_warn = profile->user_set && profile->enabled;
+ bool profile_impl = true;
+ int i;
+
+ for (i = 0; misa_bits[i] != 0; i++) {
+ uint32_t bit = misa_bits[i];
+
+ if (!(profile->misa_ext & bit)) {
+ continue;
+ }
+
+ if (!riscv_has_ext(&cpu->env, bit)) {
+ profile_impl = false;
+
+ if (send_warn) {
+ warn_report(warn_msg, profile->name,
+ riscv_get_misa_ext_name(bit));
+ }
+ }
+ }
+
+ for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) {
+ int ext_offset = profile->ext_offsets[i];
+
+ if (!isa_ext_is_enabled(cpu, ext_offset)) {
+ profile_impl = false;
+
+ if (send_warn) {
+ warn_report(warn_msg, profile->name,
+ cpu_cfg_ext_get_name(ext_offset));
+ }
+ }
+ }
+
+ profile->enabled = profile_impl;
+}
+
+static void riscv_cpu_validate_profiles(RISCVCPU *cpu)
+{
+ for (int i = 0; riscv_profiles[i] != NULL; i++) {
+ riscv_cpu_validate_profile(cpu, riscv_profiles[i]);
+ }
+}
+
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
{
CPURISCVState *env = &cpu->env;
@@ -724,6 +792,7 @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
}
riscv_cpu_validate_named_features(cpu);
+ riscv_cpu_validate_profiles(cpu);
if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) {
/*