* [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] @ 2024-01-23 16:17 Daniel Henrique Barboza 2024-01-23 16:17 ` [PATCH 1/3] target/riscv/kvm: change kvm_reg_id to uint64_t Daniel Henrique Barboza ` (3 more replies) 0 siblings, 4 replies; 8+ messages in thread From: Daniel Henrique Barboza @ 2024-01-23 16:17 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, bmeng, liwei1518, zhiwei_liu, palmer, ajones, Daniel Henrique Barboza Hi, This short series implements both 'vlenb' and 'vregs[]' in the KVM driver. The patches were done a couple of months ago but we were missing some changes in Linux (support to 'vlenb' in KVM) that got upstreamed recently with Linux 6.8. Patches based on top of Alistair's riscv-to-apply.next that already has the 'remove vlen, add vlenb' changes. Daniel Henrique Barboza (3): target/riscv/kvm: change kvm_reg_id to uint64_t target/riscv/kvm: initialize 'vlenb' via get-reg-list target/riscv/kvm: get/set vector vregs[] target/riscv/kvm/kvm-cpu.c | 144 +++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 6 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] target/riscv/kvm: change kvm_reg_id to uint64_t 2024-01-23 16:17 [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] Daniel Henrique Barboza @ 2024-01-23 16:17 ` Daniel Henrique Barboza 2024-01-25 3:20 ` Alistair Francis 2024-01-23 16:17 ` [PATCH 2/3] target/riscv/kvm: initialize 'vlenb' via get-reg-list Daniel Henrique Barboza ` (2 subsequent siblings) 3 siblings, 1 reply; 8+ messages in thread From: Daniel Henrique Barboza @ 2024-01-23 16:17 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, bmeng, liwei1518, zhiwei_liu, palmer, ajones, Daniel Henrique Barboza The field isn't big enough to hold an uint64_t kvm register and Vector registers will end up overflowing it. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> --- target/riscv/kvm/kvm-cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 4dec91740b..902180e8a5 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -145,7 +145,7 @@ typedef struct KVMCPUConfig { const char *name; const char *description; target_ulong offset; - int kvm_reg_id; + uint64_t kvm_reg_id; bool user_set; bool supported; } KVMCPUConfig; -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] target/riscv/kvm: change kvm_reg_id to uint64_t 2024-01-23 16:17 ` [PATCH 1/3] target/riscv/kvm: change kvm_reg_id to uint64_t Daniel Henrique Barboza @ 2024-01-25 3:20 ` Alistair Francis 0 siblings, 0 replies; 8+ messages in thread From: Alistair Francis @ 2024-01-25 3:20 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liwei1518, zhiwei_liu, palmer, ajones On Wed, Jan 24, 2024 at 2:18 AM Daniel Henrique Barboza <dbarboza@ventanamicro.com> wrote: > > The field isn't big enough to hold an uint64_t kvm register and Vector > registers will end up overflowing it. > > Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > target/riscv/kvm/kvm-cpu.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c > index 4dec91740b..902180e8a5 100644 > --- a/target/riscv/kvm/kvm-cpu.c > +++ b/target/riscv/kvm/kvm-cpu.c > @@ -145,7 +145,7 @@ typedef struct KVMCPUConfig { > const char *name; > const char *description; > target_ulong offset; > - int kvm_reg_id; > + uint64_t kvm_reg_id; > bool user_set; > bool supported; > } KVMCPUConfig; > -- > 2.43.0 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/3] target/riscv/kvm: initialize 'vlenb' via get-reg-list 2024-01-23 16:17 [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] Daniel Henrique Barboza 2024-01-23 16:17 ` [PATCH 1/3] target/riscv/kvm: change kvm_reg_id to uint64_t Daniel Henrique Barboza @ 2024-01-23 16:17 ` Daniel Henrique Barboza 2024-01-25 3:23 ` Alistair Francis 2024-01-23 16:17 ` [PATCH 3/3] target/riscv/kvm: get/set vector vregs[] Daniel Henrique Barboza 2024-01-25 4:48 ` [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] Alistair Francis 3 siblings, 1 reply; 8+ messages in thread From: Daniel Henrique Barboza @ 2024-01-23 16:17 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, bmeng, liwei1518, zhiwei_liu, palmer, ajones, Daniel Henrique Barboza KVM will check for the correct 'reg_size' when accessing the vector registers, erroring with EINVAL if we encode the wrong size in reg ID. Vector registers varies in size with the vector length in bytes, or 'vlenb'. This means that we need the current 'vlenb' being used by the host, otherwise we won't be able to fetch all vector regs. We'll deal with 'vlenb' first. Its support was added in Linux 6.8 as a get-reg-list register. We'll read 'vlenb' via get-reg-list and mark the register as 'supported'. All 'vlenb' ops via kvm_arch_get_registers() and kvm_arch_put_registers() will only be done if the reg is supported, i.e. we fetched it in get-reg-list during init. If the user sets a new vlenb value using the 'vlen' property, throw an error if the user value differs from the host. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> --- target/riscv/kvm/kvm-cpu.c | 85 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 902180e8a5..3812481971 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -352,6 +352,13 @@ static KVMCPUConfig kvm_cboz_blocksize = { .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicboz_block_size) }; +static KVMCPUConfig kvm_v_vlenb = { + .name = "vlenb", + .offset = CPU_CFG_OFFSET(vlenb), + .kvm_reg_id = KVM_REG_RISCV | KVM_REG_SIZE_U64 | KVM_REG_RISCV_VECTOR | + KVM_REG_RISCV_VECTOR_CSR_REG(vlenb) +}; + static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs) { CPURISCVState *env = &cpu->env; @@ -684,7 +691,8 @@ static void kvm_riscv_put_regs_timer(CPUState *cs) static int kvm_riscv_get_regs_vector(CPUState *cs) { - CPURISCVState *env = &RISCV_CPU(cs)->env; + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; target_ulong reg; int ret = 0; @@ -710,12 +718,21 @@ static int kvm_riscv_get_regs_vector(CPUState *cs) } env->vtype = reg; + if (kvm_v_vlenb.supported) { + ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), ®); + if (ret) { + return ret; + } + cpu->cfg.vlenb = reg; + } + return 0; } static int kvm_riscv_put_regs_vector(CPUState *cs) { - CPURISCVState *env = &RISCV_CPU(cs)->env; + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; target_ulong reg; int ret = 0; @@ -737,6 +754,14 @@ static int kvm_riscv_put_regs_vector(CPUState *cs) reg = env->vtype; ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vtype), ®); + if (ret) { + return ret; + } + + if (kvm_v_vlenb.supported) { + reg = cpu->cfg.vlenb; + ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), ®); + } return ret; } @@ -921,6 +946,33 @@ static int uint64_cmp(const void *a, const void *b) return 0; } +static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu, + struct kvm_reg_list *reglist) +{ + struct kvm_one_reg reg; + struct kvm_reg_list *reg_search; + uint64_t val; + int ret; + + reg_search = bsearch(&kvm_v_vlenb.kvm_reg_id, reglist->reg, reglist->n, + sizeof(uint64_t), uint64_cmp); + + if (reg_search) { + reg.id = kvm_v_vlenb.kvm_reg_id; + reg.addr = (uint64_t)&val; + + ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); + if (ret != 0) { + error_report("Unable to read vlenb register, error code: %s", + strerrorname_np(errno)); + exit(EXIT_FAILURE); + } + + kvm_v_vlenb.supported = true; + cpu->cfg.vlenb = val; + } +} + static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) { KVMCPUConfig *multi_ext_cfg; @@ -995,6 +1047,10 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) if (cpu->cfg.ext_zicboz) { kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cboz_blocksize); } + + if (riscv_has_ext(&cpu->env, RVV)) { + kvm_riscv_read_vlenb(cpu, kvmcpu, reglist); + } } static void riscv_init_kvm_registers(Object *cpu_obj) @@ -1566,7 +1622,8 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) int ret; /* short-circuit without spinning the scratch CPU */ - if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicboz) { + if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicboz && + !riscv_has_ext(env, RVV)) { return; } @@ -1613,6 +1670,28 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) } } + /* Users are setting vlen, not vlenb */ + if (riscv_has_ext(env, RVV) && riscv_cpu_option_set("vlen")) { + if (!kvm_v_vlenb.supported) { + error_setg(errp, "Unable to set 'vlenb': register not supported"); + return; + } + + reg.id = kvm_v_vlenb.kvm_reg_id; + reg.addr = (uint64_t)&val; + ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, ®); + if (ret != 0) { + error_setg(errp, "Unable to read vlenb register, error %d", errno); + return; + } + + if (cpu->cfg.vlenb != val) { + error_setg(errp, "Unable to set 'vlen' to a different " + "value than the host (%lu)", val * 8); + return; + } + } + kvm_riscv_destroy_scratch_vcpu(&kvmcpu); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] target/riscv/kvm: initialize 'vlenb' via get-reg-list 2024-01-23 16:17 ` [PATCH 2/3] target/riscv/kvm: initialize 'vlenb' via get-reg-list Daniel Henrique Barboza @ 2024-01-25 3:23 ` Alistair Francis 0 siblings, 0 replies; 8+ messages in thread From: Alistair Francis @ 2024-01-25 3:23 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liwei1518, zhiwei_liu, palmer, ajones On Wed, Jan 24, 2024 at 2:18 AM Daniel Henrique Barboza <dbarboza@ventanamicro.com> wrote: > > KVM will check for the correct 'reg_size' when accessing the vector > registers, erroring with EINVAL if we encode the wrong size in reg ID. > Vector registers varies in size with the vector length in bytes, or > 'vlenb'. This means that we need the current 'vlenb' being used by the > host, otherwise we won't be able to fetch all vector regs. > > We'll deal with 'vlenb' first. Its support was added in Linux 6.8 as a > get-reg-list register. We'll read 'vlenb' via get-reg-list and mark the > register as 'supported'. All 'vlenb' ops via kvm_arch_get_registers() > and kvm_arch_put_registers() will only be done if the reg is supported, > i.e. we fetched it in get-reg-list during init. > > If the user sets a new vlenb value using the 'vlen' property, throw an > error if the user value differs from the host. > > Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > target/riscv/kvm/kvm-cpu.c | 85 ++++++++++++++++++++++++++++++++++++-- > 1 file changed, 82 insertions(+), 3 deletions(-) > > diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c > index 902180e8a5..3812481971 100644 > --- a/target/riscv/kvm/kvm-cpu.c > +++ b/target/riscv/kvm/kvm-cpu.c > @@ -352,6 +352,13 @@ static KVMCPUConfig kvm_cboz_blocksize = { > .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicboz_block_size) > }; > > +static KVMCPUConfig kvm_v_vlenb = { > + .name = "vlenb", > + .offset = CPU_CFG_OFFSET(vlenb), > + .kvm_reg_id = KVM_REG_RISCV | KVM_REG_SIZE_U64 | KVM_REG_RISCV_VECTOR | > + KVM_REG_RISCV_VECTOR_CSR_REG(vlenb) > +}; > + > static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs) > { > CPURISCVState *env = &cpu->env; > @@ -684,7 +691,8 @@ static void kvm_riscv_put_regs_timer(CPUState *cs) > > static int kvm_riscv_get_regs_vector(CPUState *cs) > { > - CPURISCVState *env = &RISCV_CPU(cs)->env; > + RISCVCPU *cpu = RISCV_CPU(cs); > + CPURISCVState *env = &cpu->env; > target_ulong reg; > int ret = 0; > > @@ -710,12 +718,21 @@ static int kvm_riscv_get_regs_vector(CPUState *cs) > } > env->vtype = reg; > > + if (kvm_v_vlenb.supported) { > + ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), ®); > + if (ret) { > + return ret; > + } > + cpu->cfg.vlenb = reg; > + } > + > return 0; > } > > static int kvm_riscv_put_regs_vector(CPUState *cs) > { > - CPURISCVState *env = &RISCV_CPU(cs)->env; > + RISCVCPU *cpu = RISCV_CPU(cs); > + CPURISCVState *env = &cpu->env; > target_ulong reg; > int ret = 0; > > @@ -737,6 +754,14 @@ static int kvm_riscv_put_regs_vector(CPUState *cs) > > reg = env->vtype; > ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vtype), ®); > + if (ret) { > + return ret; > + } > + > + if (kvm_v_vlenb.supported) { > + reg = cpu->cfg.vlenb; > + ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), ®); > + } > > return ret; > } > @@ -921,6 +946,33 @@ static int uint64_cmp(const void *a, const void *b) > return 0; > } > > +static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu, > + struct kvm_reg_list *reglist) > +{ > + struct kvm_one_reg reg; > + struct kvm_reg_list *reg_search; > + uint64_t val; > + int ret; > + > + reg_search = bsearch(&kvm_v_vlenb.kvm_reg_id, reglist->reg, reglist->n, > + sizeof(uint64_t), uint64_cmp); > + > + if (reg_search) { > + reg.id = kvm_v_vlenb.kvm_reg_id; > + reg.addr = (uint64_t)&val; > + > + ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); > + if (ret != 0) { > + error_report("Unable to read vlenb register, error code: %s", > + strerrorname_np(errno)); > + exit(EXIT_FAILURE); > + } > + > + kvm_v_vlenb.supported = true; > + cpu->cfg.vlenb = val; > + } > +} > + > static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) > { > KVMCPUConfig *multi_ext_cfg; > @@ -995,6 +1047,10 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) > if (cpu->cfg.ext_zicboz) { > kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cboz_blocksize); > } > + > + if (riscv_has_ext(&cpu->env, RVV)) { > + kvm_riscv_read_vlenb(cpu, kvmcpu, reglist); > + } > } > > static void riscv_init_kvm_registers(Object *cpu_obj) > @@ -1566,7 +1622,8 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) > int ret; > > /* short-circuit without spinning the scratch CPU */ > - if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicboz) { > + if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicboz && > + !riscv_has_ext(env, RVV)) { > return; > } > > @@ -1613,6 +1670,28 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) > } > } > > + /* Users are setting vlen, not vlenb */ > + if (riscv_has_ext(env, RVV) && riscv_cpu_option_set("vlen")) { > + if (!kvm_v_vlenb.supported) { > + error_setg(errp, "Unable to set 'vlenb': register not supported"); > + return; > + } > + > + reg.id = kvm_v_vlenb.kvm_reg_id; > + reg.addr = (uint64_t)&val; > + ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, ®); > + if (ret != 0) { > + error_setg(errp, "Unable to read vlenb register, error %d", errno); > + return; > + } > + > + if (cpu->cfg.vlenb != val) { > + error_setg(errp, "Unable to set 'vlen' to a different " > + "value than the host (%lu)", val * 8); > + return; > + } > + } > + > kvm_riscv_destroy_scratch_vcpu(&kvmcpu); > } > > -- > 2.43.0 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/3] target/riscv/kvm: get/set vector vregs[] 2024-01-23 16:17 [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] Daniel Henrique Barboza 2024-01-23 16:17 ` [PATCH 1/3] target/riscv/kvm: change kvm_reg_id to uint64_t Daniel Henrique Barboza 2024-01-23 16:17 ` [PATCH 2/3] target/riscv/kvm: initialize 'vlenb' via get-reg-list Daniel Henrique Barboza @ 2024-01-23 16:17 ` Daniel Henrique Barboza 2024-01-25 3:28 ` Alistair Francis 2024-01-25 4:48 ` [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] Alistair Francis 3 siblings, 1 reply; 8+ messages in thread From: Daniel Henrique Barboza @ 2024-01-23 16:17 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, bmeng, liwei1518, zhiwei_liu, palmer, ajones, Daniel Henrique Barboza vregs[] have variable size that depends on the current vlenb set by the host, meaning we can't use our regular kvm_riscv_reg_id() to retrieve it. Create a generic kvm_encode_reg_size_id() helper to encode any given size in bytes into a given kvm reg id. kvm_riscv_vector_reg_id() will use it to encode vlenb into a given vreg ID. kvm_riscv_(get|set)_vector() can then get/set all 32 vregs. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> --- target/riscv/kvm/kvm-cpu.c | 57 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 3812481971..a7881de7f9 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -86,6 +86,27 @@ static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) return KVM_REG_RISCV | KVM_REG_SIZE_U64 | type | idx; } +static uint64_t kvm_encode_reg_size_id(uint64_t id, size_t size_b) +{ + uint64_t size_ctz = __builtin_ctz(size_b); + + return id | (size_ctz << KVM_REG_SIZE_SHIFT); +} + +static uint64_t kvm_riscv_vector_reg_id(RISCVCPU *cpu, + uint64_t idx) +{ + uint64_t id; + size_t size_b; + + g_assert(idx < 32); + + id = KVM_REG_RISCV | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(idx); + size_b = cpu->cfg.vlenb; + + return kvm_encode_reg_size_id(id, size_b); +} + #define RISCV_CORE_REG(env, name) \ kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, \ KVM_REG_RISCV_CORE_REG(name)) @@ -694,7 +715,8 @@ static int kvm_riscv_get_regs_vector(CPUState *cs) RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; target_ulong reg; - int ret = 0; + uint64_t vreg_id; + int vreg_idx, ret = 0; if (!riscv_has_ext(env, RVV)) { return 0; @@ -724,6 +746,21 @@ static int kvm_riscv_get_regs_vector(CPUState *cs) return ret; } cpu->cfg.vlenb = reg; + + for (int i = 0; i < 32; i++) { + /* + * vreg[] is statically allocated using RV_VLEN_MAX. + * Use it instead of vlenb to calculate vreg_idx for + * simplicity. + */ + vreg_idx = i * RV_VLEN_MAX / 64; + vreg_id = kvm_riscv_vector_reg_id(cpu, i); + + ret = kvm_get_one_reg(cs, vreg_id, &env->vreg[vreg_idx]); + if (ret) { + return ret; + } + } } return 0; @@ -734,7 +771,8 @@ static int kvm_riscv_put_regs_vector(CPUState *cs) RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; target_ulong reg; - int ret = 0; + uint64_t vreg_id; + int vreg_idx, ret = 0; if (!riscv_has_ext(env, RVV)) { return 0; @@ -761,6 +799,21 @@ static int kvm_riscv_put_regs_vector(CPUState *cs) if (kvm_v_vlenb.supported) { reg = cpu->cfg.vlenb; ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), ®); + + for (int i = 0; i < 32; i++) { + /* + * vreg[] is statically allocated using RV_VLEN_MAX. + * Use it instead of vlenb to calculate vreg_idx for + * simplicity. + */ + vreg_idx = i * RV_VLEN_MAX / 64; + vreg_id = kvm_riscv_vector_reg_id(cpu, i); + + ret = kvm_set_one_reg(cs, vreg_id, &env->vreg[vreg_idx]); + if (ret) { + return ret; + } + } } return ret; -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 3/3] target/riscv/kvm: get/set vector vregs[] 2024-01-23 16:17 ` [PATCH 3/3] target/riscv/kvm: get/set vector vregs[] Daniel Henrique Barboza @ 2024-01-25 3:28 ` Alistair Francis 0 siblings, 0 replies; 8+ messages in thread From: Alistair Francis @ 2024-01-25 3:28 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liwei1518, zhiwei_liu, palmer, ajones On Wed, Jan 24, 2024 at 2:18 AM Daniel Henrique Barboza <dbarboza@ventanamicro.com> wrote: > > vregs[] have variable size that depends on the current vlenb set by the > host, meaning we can't use our regular kvm_riscv_reg_id() to retrieve > it. > > Create a generic kvm_encode_reg_size_id() helper to encode any given > size in bytes into a given kvm reg id. kvm_riscv_vector_reg_id() will > use it to encode vlenb into a given vreg ID. > > kvm_riscv_(get|set)_vector() can then get/set all 32 vregs. > > Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > target/riscv/kvm/kvm-cpu.c | 57 ++++++++++++++++++++++++++++++++++++-- > 1 file changed, 55 insertions(+), 2 deletions(-) > > diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c > index 3812481971..a7881de7f9 100644 > --- a/target/riscv/kvm/kvm-cpu.c > +++ b/target/riscv/kvm/kvm-cpu.c > @@ -86,6 +86,27 @@ static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) > return KVM_REG_RISCV | KVM_REG_SIZE_U64 | type | idx; > } > > +static uint64_t kvm_encode_reg_size_id(uint64_t id, size_t size_b) > +{ > + uint64_t size_ctz = __builtin_ctz(size_b); > + > + return id | (size_ctz << KVM_REG_SIZE_SHIFT); > +} > + > +static uint64_t kvm_riscv_vector_reg_id(RISCVCPU *cpu, > + uint64_t idx) > +{ > + uint64_t id; > + size_t size_b; > + > + g_assert(idx < 32); > + > + id = KVM_REG_RISCV | KVM_REG_RISCV_VECTOR | KVM_REG_RISCV_VECTOR_REG(idx); > + size_b = cpu->cfg.vlenb; > + > + return kvm_encode_reg_size_id(id, size_b); > +} > + > #define RISCV_CORE_REG(env, name) \ > kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, \ > KVM_REG_RISCV_CORE_REG(name)) > @@ -694,7 +715,8 @@ static int kvm_riscv_get_regs_vector(CPUState *cs) > RISCVCPU *cpu = RISCV_CPU(cs); > CPURISCVState *env = &cpu->env; > target_ulong reg; > - int ret = 0; > + uint64_t vreg_id; > + int vreg_idx, ret = 0; > > if (!riscv_has_ext(env, RVV)) { > return 0; > @@ -724,6 +746,21 @@ static int kvm_riscv_get_regs_vector(CPUState *cs) > return ret; > } > cpu->cfg.vlenb = reg; > + > + for (int i = 0; i < 32; i++) { > + /* > + * vreg[] is statically allocated using RV_VLEN_MAX. > + * Use it instead of vlenb to calculate vreg_idx for > + * simplicity. > + */ > + vreg_idx = i * RV_VLEN_MAX / 64; > + vreg_id = kvm_riscv_vector_reg_id(cpu, i); > + > + ret = kvm_get_one_reg(cs, vreg_id, &env->vreg[vreg_idx]); > + if (ret) { > + return ret; > + } > + } > } > > return 0; > @@ -734,7 +771,8 @@ static int kvm_riscv_put_regs_vector(CPUState *cs) > RISCVCPU *cpu = RISCV_CPU(cs); > CPURISCVState *env = &cpu->env; > target_ulong reg; > - int ret = 0; > + uint64_t vreg_id; > + int vreg_idx, ret = 0; > > if (!riscv_has_ext(env, RVV)) { > return 0; > @@ -761,6 +799,21 @@ static int kvm_riscv_put_regs_vector(CPUState *cs) > if (kvm_v_vlenb.supported) { > reg = cpu->cfg.vlenb; > ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), ®); > + > + for (int i = 0; i < 32; i++) { > + /* > + * vreg[] is statically allocated using RV_VLEN_MAX. > + * Use it instead of vlenb to calculate vreg_idx for > + * simplicity. > + */ > + vreg_idx = i * RV_VLEN_MAX / 64; > + vreg_id = kvm_riscv_vector_reg_id(cpu, i); > + > + ret = kvm_set_one_reg(cs, vreg_id, &env->vreg[vreg_idx]); > + if (ret) { > + return ret; > + } > + } > } > > return ret; > -- > 2.43.0 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] 2024-01-23 16:17 [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] Daniel Henrique Barboza ` (2 preceding siblings ...) 2024-01-23 16:17 ` [PATCH 3/3] target/riscv/kvm: get/set vector vregs[] Daniel Henrique Barboza @ 2024-01-25 4:48 ` Alistair Francis 3 siblings, 0 replies; 8+ messages in thread From: Alistair Francis @ 2024-01-25 4:48 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, bmeng, liwei1518, zhiwei_liu, palmer, ajones On Wed, Jan 24, 2024 at 2:18 AM Daniel Henrique Barboza <dbarboza@ventanamicro.com> wrote: > > Hi, > > This short series implements both 'vlenb' and 'vregs[]' in the KVM > driver. > > The patches were done a couple of months ago but we were missing some > changes in Linux (support to 'vlenb' in KVM) that got upstreamed > recently with Linux 6.8. > > Patches based on top of Alistair's riscv-to-apply.next that already has > the 'remove vlen, add vlenb' changes. > > Daniel Henrique Barboza (3): > target/riscv/kvm: change kvm_reg_id to uint64_t > target/riscv/kvm: initialize 'vlenb' via get-reg-list > target/riscv/kvm: get/set vector vregs[] Thanks! Applied to riscv-to-apply.next Alistair > > target/riscv/kvm/kvm-cpu.c | 144 +++++++++++++++++++++++++++++++++++-- > 1 file changed, 138 insertions(+), 6 deletions(-) > > -- > 2.43.0 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-01-25 4:49 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-01-23 16:17 [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] Daniel Henrique Barboza 2024-01-23 16:17 ` [PATCH 1/3] target/riscv/kvm: change kvm_reg_id to uint64_t Daniel Henrique Barboza 2024-01-25 3:20 ` Alistair Francis 2024-01-23 16:17 ` [PATCH 2/3] target/riscv/kvm: initialize 'vlenb' via get-reg-list Daniel Henrique Barboza 2024-01-25 3:23 ` Alistair Francis 2024-01-23 16:17 ` [PATCH 3/3] target/riscv/kvm: get/set vector vregs[] Daniel Henrique Barboza 2024-01-25 3:28 ` Alistair Francis 2024-01-25 4:48 ` [PATCH 0/3] target/riscv/kvm: support 'vlenb' and vregs[] Alistair Francis
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).