Almost all users of cpu->cfg.satp_mode care only about the "max" value
satp_mode_max_from_map(cpu->cfg.satp_mode.map); convert the QOM
properties back into it. For TCG, consult valid_vm[] instead of
the bitmap of accepted modes.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/riscv/cpu.h | 1 -
hw/riscv/virt-acpi-build.c | 14 +++++---------
hw/riscv/virt.c | 5 ++---
target/riscv/cpu.c | 27 ++++++++++-----------------
target/riscv/csr.c | 9 +++++++--
5 files changed, 24 insertions(+), 32 deletions(-)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 97713681cbe..f9b223bf8a7 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -911,7 +911,6 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
target_ulong riscv_new_csr_seed(target_ulong new_value,
target_ulong write_mask);
-uint8_t satp_mode_max_from_map(uint32_t map);
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
/* Implemented in th_csr.c */
diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
index 2b374ebacbf..1a92a84207d 100644
--- a/hw/riscv/virt-acpi-build.c
+++ b/hw/riscv/virt-acpi-build.c
@@ -261,7 +261,6 @@ static void build_rhct(GArray *table_data,
uint32_t isa_offset, num_rhct_nodes, cmo_offset = 0;
RISCVCPU *cpu = &s->soc[0].harts[0];
uint32_t mmu_offset = 0;
- uint8_t satp_mode_max;
bool rv32 = riscv_cpu_is_32bit(cpu);
g_autofree char *isa = NULL;
@@ -282,8 +281,7 @@ static void build_rhct(GArray *table_data,
num_rhct_nodes++;
}
- if (!rv32 && cpu->cfg.satp_mode.supported != 0 &&
- (cpu->cfg.satp_mode.map & ~(1 << VM_1_10_MBARE))) {
+ if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) {
num_rhct_nodes++;
}
@@ -343,20 +341,18 @@ static void build_rhct(GArray *table_data,
}
/* MMU node structure */
- if (!rv32 && cpu->cfg.satp_mode.supported != 0 &&
- (cpu->cfg.satp_mode.map & ~(1 << VM_1_10_MBARE))) {
- satp_mode_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map);
+ if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) {
mmu_offset = table_data->len - table.table_offset;
build_append_int_noprefix(table_data, 2, 2); /* Type */
build_append_int_noprefix(table_data, 8, 2); /* Length */
build_append_int_noprefix(table_data, 0x1, 2); /* Revision */
build_append_int_noprefix(table_data, 0, 1); /* Reserved */
/* MMU Type */
- if (satp_mode_max == VM_1_10_SV57) {
+ if (cpu->cfg.max_satp_mode == VM_1_10_SV57) {
build_append_int_noprefix(table_data, 2, 1); /* Sv57 */
- } else if (satp_mode_max == VM_1_10_SV48) {
+ } else if (cpu->cfg.max_satp_mode == VM_1_10_SV48) {
build_append_int_noprefix(table_data, 1, 1); /* Sv48 */
- } else if (satp_mode_max == VM_1_10_SV39) {
+ } else if (cpu->cfg.max_satp_mode == VM_1_10_SV39) {
build_append_int_noprefix(table_data, 0, 1); /* Sv39 */
} else {
g_assert_not_reached();
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 241389d72f8..2394fc71df4 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -236,10 +236,10 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
uint32_t cpu_phandle;
MachineState *ms = MACHINE(s);
bool is_32_bit = riscv_is_32bit(&s->soc[0]);
- uint8_t satp_mode_max;
for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
RISCVCPU *cpu_ptr = &s->soc[socket].harts[cpu];
+ int8_t satp_mode_max = cpu_ptr->cfg.max_satp_mode;
g_autofree char *cpu_name = NULL;
g_autofree char *core_name = NULL;
g_autofree char *intc_name = NULL;
@@ -251,8 +251,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
s->soc[socket].hartid_base + cpu);
qemu_fdt_add_subnode(ms->fdt, cpu_name);
- if (cpu_ptr->cfg.satp_mode.supported != 0) {
- satp_mode_max = satp_mode_max_from_map(cpu_ptr->cfg.satp_mode.map);
+ if (satp_mode_max != -1) {
sv_name = g_strdup_printf("riscv,%s",
satp_mode_str(satp_mode_max, is_32_bit));
qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type", sv_name);
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 2d06543217a..ce71ee95a52 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -387,7 +387,7 @@ static uint8_t satp_mode_from_str(const char *satp_mode_str)
g_assert_not_reached();
}
-uint8_t satp_mode_max_from_map(uint32_t map)
+static uint8_t satp_mode_max_from_map(uint32_t map)
{
/*
* 'map = 0' will make us return (31 - 32), which C will
@@ -453,15 +453,13 @@ static void set_satp_mode_default_map(RISCVCPU *cpu)
/*
* Bare CPUs do not default to the max available.
* Users must set a valid satp_mode in the command
- * line.
+ * line. Otherwise, leave the existing max_satp_mode
+ * in place.
*/
if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_BARE_CPU) != NULL) {
warn_report("No satp mode set. Defaulting to 'bare'");
- cpu->cfg.satp_mode.map = (1 << VM_1_10_MBARE);
- return;
+ cpu->cfg.max_satp_mode = VM_1_10_MBARE;
}
-
- cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
}
#endif
@@ -1180,8 +1178,8 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
bool rv32 = riscv_cpu_is_32bit(cpu);
uint8_t satp_mode_map_max;
- /* The CPU wants the OS to decide which satp mode to use */
- if (cpu->cfg.satp_mode.supported == 0) {
+ if (cpu->cfg.max_satp_mode == -1) {
+ /* The CPU wants the hypervisor to decide which satp mode to allow */
return;
}
@@ -1200,14 +1198,14 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
(cpu->cfg.satp_mode.supported & (1 << i))) {
for (int j = i - 1; j >= 0; --j) {
if (cpu->cfg.satp_mode.supported & (1 << j)) {
- cpu->cfg.satp_mode.map |= (1 << j);
- break;
+ cpu->cfg.max_satp_mode = j;
+ return;
}
}
- break;
}
}
}
+ return;
}
satp_mode_map_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map);
@@ -1237,12 +1235,7 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
}
}
- /* Finally expand the map so that all valid modes are set */
- for (int i = satp_mode_map_max - 1; i >= 0; --i) {
- if (cpu->cfg.satp_mode.supported & (1 << i)) {
- cpu->cfg.satp_mode.map |= (1 << i);
- }
- }
+ cpu->cfg.max_satp_mode = satp_mode_map_max;
}
#endif
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index afb7544f078..78db9aeda57 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1862,8 +1862,13 @@ static RISCVException read_mstatus(CPURISCVState *env, int csrno,
static bool validate_vm(CPURISCVState *env, target_ulong vm)
{
- uint64_t mode_supported = riscv_cpu_cfg(env)->satp_mode.map;
- return get_field(mode_supported, (1 << vm));
+ bool rv32 = riscv_cpu_mxl(env) == MXL_RV32;
+ RISCVCPU *cpu = env_archcpu(env);
+ int satp_mode_supported_max = cpu->cfg.max_satp_mode;
+ const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
+
+ assert(satp_mode_supported_max >= 0);
+ return vm <= satp_mode_supported_max && valid_vm[vm];
}
static target_ulong legalize_xatp(CPURISCVState *env, target_ulong old_xatp,
--
2.48.1
On Wed, Feb 19, 2025 at 2:59 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> Almost all users of cpu->cfg.satp_mode care only about the "max" value
> satp_mode_max_from_map(cpu->cfg.satp_mode.map); convert the QOM
> properties back into it. For TCG, consult valid_vm[] instead of
> the bitmap of accepted modes.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> target/riscv/cpu.h | 1 -
> hw/riscv/virt-acpi-build.c | 14 +++++---------
> hw/riscv/virt.c | 5 ++---
> target/riscv/cpu.c | 27 ++++++++++-----------------
> target/riscv/csr.c | 9 +++++++--
> 5 files changed, 24 insertions(+), 32 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 97713681cbe..f9b223bf8a7 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -911,7 +911,6 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
> target_ulong riscv_new_csr_seed(target_ulong new_value,
> target_ulong write_mask);
>
> -uint8_t satp_mode_max_from_map(uint32_t map);
> const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
>
> /* Implemented in th_csr.c */
> diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
> index 2b374ebacbf..1a92a84207d 100644
> --- a/hw/riscv/virt-acpi-build.c
> +++ b/hw/riscv/virt-acpi-build.c
> @@ -261,7 +261,6 @@ static void build_rhct(GArray *table_data,
> uint32_t isa_offset, num_rhct_nodes, cmo_offset = 0;
> RISCVCPU *cpu = &s->soc[0].harts[0];
> uint32_t mmu_offset = 0;
> - uint8_t satp_mode_max;
> bool rv32 = riscv_cpu_is_32bit(cpu);
> g_autofree char *isa = NULL;
>
> @@ -282,8 +281,7 @@ static void build_rhct(GArray *table_data,
> num_rhct_nodes++;
> }
>
> - if (!rv32 && cpu->cfg.satp_mode.supported != 0 &&
> - (cpu->cfg.satp_mode.map & ~(1 << VM_1_10_MBARE))) {
> + if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) {
> num_rhct_nodes++;
> }
>
> @@ -343,20 +341,18 @@ static void build_rhct(GArray *table_data,
> }
>
> /* MMU node structure */
> - if (!rv32 && cpu->cfg.satp_mode.supported != 0 &&
> - (cpu->cfg.satp_mode.map & ~(1 << VM_1_10_MBARE))) {
> - satp_mode_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map);
> + if (!rv32 && cpu->cfg.max_satp_mode >= VM_1_10_SV39) {
> mmu_offset = table_data->len - table.table_offset;
> build_append_int_noprefix(table_data, 2, 2); /* Type */
> build_append_int_noprefix(table_data, 8, 2); /* Length */
> build_append_int_noprefix(table_data, 0x1, 2); /* Revision */
> build_append_int_noprefix(table_data, 0, 1); /* Reserved */
> /* MMU Type */
> - if (satp_mode_max == VM_1_10_SV57) {
> + if (cpu->cfg.max_satp_mode == VM_1_10_SV57) {
> build_append_int_noprefix(table_data, 2, 1); /* Sv57 */
> - } else if (satp_mode_max == VM_1_10_SV48) {
> + } else if (cpu->cfg.max_satp_mode == VM_1_10_SV48) {
> build_append_int_noprefix(table_data, 1, 1); /* Sv48 */
> - } else if (satp_mode_max == VM_1_10_SV39) {
> + } else if (cpu->cfg.max_satp_mode == VM_1_10_SV39) {
> build_append_int_noprefix(table_data, 0, 1); /* Sv39 */
> } else {
> g_assert_not_reached();
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 241389d72f8..2394fc71df4 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -236,10 +236,10 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
> uint32_t cpu_phandle;
> MachineState *ms = MACHINE(s);
> bool is_32_bit = riscv_is_32bit(&s->soc[0]);
> - uint8_t satp_mode_max;
>
> for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
> RISCVCPU *cpu_ptr = &s->soc[socket].harts[cpu];
> + int8_t satp_mode_max = cpu_ptr->cfg.max_satp_mode;
> g_autofree char *cpu_name = NULL;
> g_autofree char *core_name = NULL;
> g_autofree char *intc_name = NULL;
> @@ -251,8 +251,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
> s->soc[socket].hartid_base + cpu);
> qemu_fdt_add_subnode(ms->fdt, cpu_name);
>
> - if (cpu_ptr->cfg.satp_mode.supported != 0) {
> - satp_mode_max = satp_mode_max_from_map(cpu_ptr->cfg.satp_mode.map);
> + if (satp_mode_max != -1) {
> sv_name = g_strdup_printf("riscv,%s",
> satp_mode_str(satp_mode_max, is_32_bit));
> qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type", sv_name);
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 2d06543217a..ce71ee95a52 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -387,7 +387,7 @@ static uint8_t satp_mode_from_str(const char *satp_mode_str)
> g_assert_not_reached();
> }
>
> -uint8_t satp_mode_max_from_map(uint32_t map)
> +static uint8_t satp_mode_max_from_map(uint32_t map)
> {
> /*
> * 'map = 0' will make us return (31 - 32), which C will
> @@ -453,15 +453,13 @@ static void set_satp_mode_default_map(RISCVCPU *cpu)
> /*
> * Bare CPUs do not default to the max available.
> * Users must set a valid satp_mode in the command
> - * line.
> + * line. Otherwise, leave the existing max_satp_mode
> + * in place.
> */
> if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_BARE_CPU) != NULL) {
> warn_report("No satp mode set. Defaulting to 'bare'");
> - cpu->cfg.satp_mode.map = (1 << VM_1_10_MBARE);
> - return;
> + cpu->cfg.max_satp_mode = VM_1_10_MBARE;
> }
> -
> - cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
> }
> #endif
>
> @@ -1180,8 +1178,8 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
> bool rv32 = riscv_cpu_is_32bit(cpu);
> uint8_t satp_mode_map_max;
>
> - /* The CPU wants the OS to decide which satp mode to use */
> - if (cpu->cfg.satp_mode.supported == 0) {
> + if (cpu->cfg.max_satp_mode == -1) {
> + /* The CPU wants the hypervisor to decide which satp mode to allow */
> return;
> }
>
> @@ -1200,14 +1198,14 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
> (cpu->cfg.satp_mode.supported & (1 << i))) {
> for (int j = i - 1; j >= 0; --j) {
> if (cpu->cfg.satp_mode.supported & (1 << j)) {
> - cpu->cfg.satp_mode.map |= (1 << j);
> - break;
> + cpu->cfg.max_satp_mode = j;
> + return;
> }
> }
> - break;
> }
> }
> }
> + return;
> }
>
> satp_mode_map_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map);
> @@ -1237,12 +1235,7 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
> }
> }
>
> - /* Finally expand the map so that all valid modes are set */
> - for (int i = satp_mode_map_max - 1; i >= 0; --i) {
> - if (cpu->cfg.satp_mode.supported & (1 << i)) {
> - cpu->cfg.satp_mode.map |= (1 << i);
> - }
> - }
> + cpu->cfg.max_satp_mode = satp_mode_map_max;
> }
> #endif
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index afb7544f078..78db9aeda57 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -1862,8 +1862,13 @@ static RISCVException read_mstatus(CPURISCVState *env, int csrno,
>
> static bool validate_vm(CPURISCVState *env, target_ulong vm)
> {
> - uint64_t mode_supported = riscv_cpu_cfg(env)->satp_mode.map;
> - return get_field(mode_supported, (1 << vm));
> + bool rv32 = riscv_cpu_mxl(env) == MXL_RV32;
> + RISCVCPU *cpu = env_archcpu(env);
> + int satp_mode_supported_max = cpu->cfg.max_satp_mode;
> + const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
> +
> + assert(satp_mode_supported_max >= 0);
> + return vm <= satp_mode_supported_max && valid_vm[vm];
> }
>
> static target_ulong legalize_xatp(CPURISCVState *env, target_ulong old_xatp,
> --
> 2.48.1
>
>
© 2016 - 2026 Red Hat, Inc.