@@ -147,6 +147,22 @@ 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 RISCVIsaExtData *edata;
+
+ for (edata = isa_edata_arr; edata && edata->name; edata++) {
+ if (edata->ext_enable_offset != ext_offset) {
+ continue;
+ }
+
+ return edata->name;
+ }
+
+ g_assert_not_reached();
+}
+
+
static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset,
bool value)
{
@@ -644,11 +660,52 @@ 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";
+ 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)) {
+ 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)) {
+ warn_report(warn_msg, profile->name,
+ cpu_cfg_ext_get_name(ext_offset));
+ }
+ }
+}
+
+static void riscv_cpu_validate_profiles(RISCVCPU *cpu)
+{
+ for (int i = 0; riscv_profiles[i] != NULL; i++) {
+ RISCVCPUProfile *profile = riscv_profiles[i];
+
+ if (profile->user_set && profile->enabled) {
+ riscv_cpu_validate_profile(cpu, profile);
+ }
+ }
+}
+
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
{
CPURISCVState *env = &cpu->env;
Error *local_err = NULL;
+ riscv_cpu_validate_profiles(cpu);
+
riscv_cpu_validate_priv_spec(cpu, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);