target/riscv/kvm/kvm-cpu.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
This patch adds host satp mode while kvm/host cpu satp mode is not
set.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2931
Signed-off-by: Meng Zhuo <mengzhuo@iscas.ac.cn>
---
target/riscv/kvm/kvm-cpu.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 5315134e08..942f942b25 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -953,6 +953,21 @@ static void kvm_riscv_destroy_scratch_vcpu(KVMScratchCPU *scratch)
close(scratch->kvmfd);
}
+static void kvm_riscv_init_satp_mode(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
+{
+ CPURISCVState *env = &cpu->env;
+ struct kvm_one_reg reg;
+ int ret;
+ uint64_t val;
+ reg.id = RISCV_CONFIG_REG(env, satp_mode);
+ reg.addr = (uint64_t)&val;
+ ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
+ if (ret != 0) {
+ error_report("Unable to retrieve satp from host, error %d", ret);
+ }
+ env->satp = 1 << val;
+}
+
static void kvm_riscv_init_machine_ids(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
{
CPURISCVState *env = &cpu->env;
@@ -1212,6 +1227,7 @@ static void riscv_init_kvm_registers(Object *cpu_obj)
kvm_riscv_init_machine_ids(cpu, &kvmcpu);
kvm_riscv_init_misa_ext_mask(cpu, &kvmcpu);
kvm_riscv_init_multiext_cfg(cpu, &kvmcpu);
+ kvm_riscv_init_satp_mode(cpu, &kvmcpu);
kvm_riscv_destroy_scratch_vcpu(&kvmcpu);
}
@@ -1891,7 +1907,16 @@ static bool kvm_cpu_realize(CPUState *cs, Error **errp)
}
}
- return true;
+ RISCVSATPMap *satp_mode = &cpu->cfg.satp_mode;
+ CPURISCVState *env = &cpu->env;
+
+ if (!satp_mode->init && env->satp) {
+ satp_mode->init = env->satp;
+ satp_mode->map = env->satp;
+ satp_mode->supported = env->satp;
+ }
+
+ return true;
}
void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
--
2.39.5
On Sun, Apr 27, 2025 at 09:25:57PM +0800, Meng Zhuo wrote:
> This patch adds host satp mode while kvm/host cpu satp mode is not
> set.
Huh, the KVM side[1] was written for this purpose, but it appears we never
got a QEMU side merged.
[1] commit 2776421e6839 ("RISC-V: KVM: provide UAPI for host SATP mode")
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2931
> Signed-off-by: Meng Zhuo <mengzhuo@iscas.ac.cn>
> ---
> target/riscv/kvm/kvm-cpu.c | 27 ++++++++++++++++++++++++++-
> 1 file changed, 26 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
> index 5315134e08..942f942b25 100644
> --- a/target/riscv/kvm/kvm-cpu.c
> +++ b/target/riscv/kvm/kvm-cpu.c
> @@ -953,6 +953,21 @@ static void kvm_riscv_destroy_scratch_vcpu(KVMScratchCPU *scratch)
> close(scratch->kvmfd);
> }
>
> +static void kvm_riscv_init_satp_mode(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
> +{
> + CPURISCVState *env = &cpu->env;
> + struct kvm_one_reg reg;
> + int ret;
> + uint64_t val;
Please add a blank line here.
> + reg.id = RISCV_CONFIG_REG(env, satp_mode);
> + reg.addr = (uint64_t)&val;
> + ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
> + if (ret != 0) {
> + error_report("Unable to retrieve satp from host, error %d", ret);
> + }
> + env->satp = 1 << val;
We need to expose set_satp_mode_max_supported() and then call it here
instead of setting env->satp. At this phase we're just figuring out what's
supported by KVM. riscv_cpu_finalize_features() will then sort out what's
supported by KVM and what's selected by the user (if anything) in order
to determine what mode should be used.
> +}
> +
> static void kvm_riscv_init_machine_ids(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
> {
> CPURISCVState *env = &cpu->env;
> @@ -1212,6 +1227,7 @@ static void riscv_init_kvm_registers(Object *cpu_obj)
> kvm_riscv_init_machine_ids(cpu, &kvmcpu);
> kvm_riscv_init_misa_ext_mask(cpu, &kvmcpu);
> kvm_riscv_init_multiext_cfg(cpu, &kvmcpu);
> + kvm_riscv_init_satp_mode(cpu, &kvmcpu);
>
> kvm_riscv_destroy_scratch_vcpu(&kvmcpu);
> }
> @@ -1891,7 +1907,16 @@ static bool kvm_cpu_realize(CPUState *cs, Error **errp)
> }
> }
>
> - return true;
> + RISCVSATPMap *satp_mode = &cpu->cfg.satp_mode;
> + CPURISCVState *env = &cpu->env;
> +
> + if (!satp_mode->init && env->satp) {
> + satp_mode->init = env->satp;
> + satp_mode->map = env->satp;
> + satp_mode->supported = env->satp;
> + }
> +
> + return true;
Other than the indentation fix, none of the above hunk is correct or
needed.
Thanks,
drew
> }
>
> void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
> --
> 2.39.5
>
>
2025-04-28T09:00:55+02:00, Andrew Jones <ajones@ventanamicro.com>:
> On Sun, Apr 27, 2025 at 09:25:57PM +0800, Meng Zhuo wrote:
>> This patch adds host satp mode while kvm/host cpu satp mode is not
>> set.
>
> Huh, the KVM side[1] was written for this purpose, but it appears we never
> got a QEMU side merged.
>
> [1] commit 2776421e6839 ("RISC-V: KVM: provide UAPI for host SATP mode")
KVM satp_mode is the current SATP.mode and I don't think the other
SATP.modes can generally be guessed from the host SATP mode.
Can't QEMU use the host capabilities from cpuinfo or something?
Do we need to return a bitmask from KVM?
(e.g. WARL all modes in vsatp and return what sticks.)
Thanks.
On Mon, Apr 28, 2025 at 11:30:36AM +0200, Radim Krčmář wrote:
> 2025-04-28T09:00:55+02:00, Andrew Jones <ajones@ventanamicro.com>:
> > On Sun, Apr 27, 2025 at 09:25:57PM +0800, Meng Zhuo wrote:
> >> This patch adds host satp mode while kvm/host cpu satp mode is not
> >> set.
> >
> > Huh, the KVM side[1] was written for this purpose, but it appears we never
> > got a QEMU side merged.
> >
> > [1] commit 2776421e6839 ("RISC-V: KVM: provide UAPI for host SATP mode")
>
> KVM satp_mode is the current SATP.mode and I don't think the other
> SATP.modes can generally be guessed from the host SATP mode.
>
> Can't QEMU use the host capabilities from cpuinfo or something?
>
> Do we need to return a bitmask from KVM?
> (e.g. WARL all modes in vsatp and return what sticks.)
>
The widest supported is sufficient because all narrower must also be
supported. Linux should be figuring out the widest and capturing that
at boot time and we should be returing that info for the KVM satp_mode
get-one-reg call.
If the satp_mode we're currently returning isn't the widest possible,
then we should fix that in KVM.
Thanks,
drew
2025-04-28T14:08:59+02:00, Andrew Jones <ajones@ventanamicro.com>:
> On Mon, Apr 28, 2025 at 11:30:36AM +0200, Radim Krčmář wrote:
>> 2025-04-28T09:00:55+02:00, Andrew Jones <ajones@ventanamicro.com>:
>> > On Sun, Apr 27, 2025 at 09:25:57PM +0800, Meng Zhuo wrote:
>> >> This patch adds host satp mode while kvm/host cpu satp mode is not
>> >> set.
>> >
>> > Huh, the KVM side[1] was written for this purpose, but it appears we never
>> > got a QEMU side merged.
>> >
>> > [1] commit 2776421e6839 ("RISC-V: KVM: provide UAPI for host SATP mode")
>>
>> KVM satp_mode is the current SATP.mode and I don't think the other
>> SATP.modes can generally be guessed from the host SATP mode.
>>
>> Can't QEMU use the host capabilities from cpuinfo or something?
>>
>> Do we need to return a bitmask from KVM?
>> (e.g. WARL all modes in vsatp and return what sticks.)
>>
>
> The widest supported is sufficient because all narrower must also be
> supported. Linux should be figuring out the widest and capturing that
> at boot time and we should be returing that info for the KVM satp_mode
> get-one-reg call.
Linux has command line overrides for the mode (no4lvl and no5vlv), so
the active mode in Linux might not be the widest supported by the cpu.
Let's say Linux decides to use 9 on a host cpu that has 0,8,9,10.
set_satp_mode_max_supported() will set supported vcpu modes to 0,8,9.
Should "-cpu host" contain the 10?
> If the satp_mode we're currently returning isn't the widest possible,
> then we should fix that in KVM.
The numbers are even more complicated... Pasting the values from manual:
0 Bare
1-7 Reserved for standard use
8 Sv39
9 Sv48
10 Sv57
11 Reserved for Sv64
12-13 Reserved for standard use
14-15 Designated for custom use
The reserved values make this extra juicy, let's say Linux uses 14 on
machine that has 0,8,9,14. QEMU sees 14 and sets the vcpu modes to
0,8,9,10 -- it's not even a subset of the host CPU.
(There might be similar problems even with future standard extensions.)
On Mon, Apr 28, 2025 at 03:37:26PM +0200, Radim Krčmář wrote:
> 2025-04-28T14:08:59+02:00, Andrew Jones <ajones@ventanamicro.com>:
> > On Mon, Apr 28, 2025 at 11:30:36AM +0200, Radim Krčmář wrote:
> >> 2025-04-28T09:00:55+02:00, Andrew Jones <ajones@ventanamicro.com>:
> >> > On Sun, Apr 27, 2025 at 09:25:57PM +0800, Meng Zhuo wrote:
> >> >> This patch adds host satp mode while kvm/host cpu satp mode is not
> >> >> set.
> >> >
> >> > Huh, the KVM side[1] was written for this purpose, but it appears we never
> >> > got a QEMU side merged.
> >> >
> >> > [1] commit 2776421e6839 ("RISC-V: KVM: provide UAPI for host SATP mode")
> >>
> >> KVM satp_mode is the current SATP.mode and I don't think the other
> >> SATP.modes can generally be guessed from the host SATP mode.
> >>
> >> Can't QEMU use the host capabilities from cpuinfo or something?
> >>
> >> Do we need to return a bitmask from KVM?
> >> (e.g. WARL all modes in vsatp and return what sticks.)
> >>
> >
> > The widest supported is sufficient because all narrower must also be
> > supported. Linux should be figuring out the widest and capturing that
> > at boot time and we should be returing that info for the KVM satp_mode
> > get-one-reg call.
>
> Linux has command line overrides for the mode (no4lvl and no5vlv), so
> the active mode in Linux might not be the widest supported by the cpu.
>
> Let's say Linux decides to use 9 on a host cpu that has 0,8,9,10.
> set_satp_mode_max_supported() will set supported vcpu modes to 0,8,9.
>
> Should "-cpu host" contain the 10?
If the architecture allows it and the host kernel/KVM is aware of it. If,
OTOH, the boot options / hardware description has hidden the platform's
capabilities from KVM, then it won't know 10 is supported, so it won't
tell the vmm it is and the vmm shouldn't second guess that.
>
> > If the satp_mode we're currently returning isn't the widest possible,
> > then we should fix that in KVM.
>
> The numbers are even more complicated... Pasting the values from manual:
>
> 0 Bare
> 1-7 Reserved for standard use
> 8 Sv39
> 9 Sv48
> 10 Sv57
> 11 Reserved for Sv64
> 12-13 Reserved for standard use
> 14-15 Designated for custom use
>
> The reserved values make this extra juicy, let's say Linux uses 14 on
> machine that has 0,8,9,14. QEMU sees 14 and sets the vcpu modes to
> 0,8,9,10 -- it's not even a subset of the host CPU.
> (There might be similar problems even with future standard extensions.)
Currently QEMU won't recognize anything higher than 10 and it knows how
to skip 1-7. If we need to add more standard support (or custom support)
we'll have to modify set_satp_mode_max_supported(). But let's burn that
bridge later. We should probably sanity check the input to that function
with something like the (untested) diff below, though.
Thanks,
drew
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 09ded6829a2c..a9088c7b1770 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -435,10 +435,18 @@ const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
}
static void set_satp_mode_max_supported(RISCVCPU *cpu,
- uint8_t satp_mode)
+ uint8_t satp_mode,
+ Error **errp)
{
bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
+ int satp_max = rv32 ? VM_1_10_SV32 : VM_1_10_MAX;
+
+ if (satp_mode > satp_max) {
+ error_setg(errp, "satp_mode %s is higher than the supported max %s",
+ satp_mode_str(satp_max, rv32),
+ satp_mode_str(satp_max, rv32));
+ }
for (int i = 0; i <= satp_mode; ++i) {
if (valid_vm[i]) {
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index a30317c61781..46d206abba97 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -662,6 +662,7 @@ typedef enum {
#define VM_1_10_SV48 9
#define VM_1_10_SV57 10
#define VM_1_10_SV64 11
+#define VM_1_10_MAX VM_1_10_SV64
/* Page table entry (PTE) fields */
#define PTE_V 0x001 /* Valid */
© 2016 - 2025 Red Hat, Inc.