Skip to content

Commit 5b9e413

Browse files
Andrew Jonesavpatel
authored andcommitted
RISC-V: KVM: Add support for SBI extension registers
Some SBI extensions have state that needs to be saved / restored when migrating the VM. Provide a get/set-one-reg register type for SBI extension registers. Each SBI extension that uses this type will have its own subtype. There are currently no subtypes defined. The next patch introduces the first one. Reviewed-by: Anup Patel <anup@brainfault.org> Reviewed-by: Atish Patra <atishp@rivosinc.com> Signed-off-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent 38b3390 commit 5b9e413

4 files changed

Lines changed: 103 additions & 4 deletions

File tree

arch/riscv/include/asm/kvm_vcpu_sbi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu,
6060
const struct kvm_one_reg *reg);
6161
int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
6262
const struct kvm_one_reg *reg);
63+
int kvm_riscv_vcpu_set_reg_sbi(struct kvm_vcpu *vcpu,
64+
const struct kvm_one_reg *reg);
65+
int kvm_riscv_vcpu_get_reg_sbi(struct kvm_vcpu *vcpu,
66+
const struct kvm_one_reg *reg);
6367
const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
6468
struct kvm_vcpu *vcpu, unsigned long extid);
6569
bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx);

arch/riscv/include/uapi/asm/kvm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ enum KVM_RISCV_SBI_EXT_ID {
242242
#define KVM_REG_RISCV_VECTOR_REG(n) \
243243
((n) + sizeof(struct __riscv_v_ext_state) / sizeof(unsigned long))
244244

245+
/* Registers for specific SBI extensions are mapped as type 10 */
246+
#define KVM_REG_RISCV_SBI_STATE (0x0a << KVM_REG_RISCV_TYPE_SHIFT)
247+
245248
/* Device Control API: RISC-V AIA */
246249
#define KVM_DEV_RISCV_APLIC_ALIGN 0x1000
247250
#define KVM_DEV_RISCV_APLIC_SIZE 0x4000

arch/riscv/kvm/vcpu_onereg.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,29 @@ static unsigned long num_sbi_ext_regs(struct kvm_vcpu *vcpu)
961961
return copy_sbi_ext_reg_indices(vcpu, NULL);
962962
}
963963

964+
static inline unsigned long num_sbi_regs(struct kvm_vcpu *vcpu)
965+
{
966+
return 0;
967+
}
968+
969+
static int copy_sbi_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
970+
{
971+
int n = num_sbi_regs(vcpu);
972+
973+
for (int i = 0; i < n; i++) {
974+
u64 reg = KVM_REG_RISCV | KVM_REG_SIZE_U64 |
975+
KVM_REG_RISCV_SBI_STATE | i;
976+
977+
if (uindices) {
978+
if (put_user(reg, uindices))
979+
return -EFAULT;
980+
uindices++;
981+
}
982+
}
983+
984+
return n;
985+
}
986+
964987
static inline unsigned long num_vector_regs(const struct kvm_vcpu *vcpu)
965988
{
966989
if (!riscv_isa_extension_available(vcpu->arch.isa, v))
@@ -1028,6 +1051,7 @@ unsigned long kvm_riscv_vcpu_num_regs(struct kvm_vcpu *vcpu)
10281051
res += num_vector_regs(vcpu);
10291052
res += num_isa_ext_regs(vcpu);
10301053
res += num_sbi_ext_regs(vcpu);
1054+
res += num_sbi_regs(vcpu);
10311055

10321056
return res;
10331057
}
@@ -1083,6 +1107,12 @@ int kvm_riscv_vcpu_copy_reg_indices(struct kvm_vcpu *vcpu,
10831107
ret = copy_sbi_ext_reg_indices(vcpu, uindices);
10841108
if (ret < 0)
10851109
return ret;
1110+
uindices += ret;
1111+
1112+
ret = copy_sbi_reg_indices(vcpu, uindices);
1113+
if (ret < 0)
1114+
return ret;
1115+
uindices += ret;
10861116

10871117
return 0;
10881118
}
@@ -1105,12 +1135,14 @@ int kvm_riscv_vcpu_set_reg(struct kvm_vcpu *vcpu,
11051135
case KVM_REG_RISCV_FP_D:
11061136
return kvm_riscv_vcpu_set_reg_fp(vcpu, reg,
11071137
KVM_REG_RISCV_FP_D);
1138+
case KVM_REG_RISCV_VECTOR:
1139+
return kvm_riscv_vcpu_set_reg_vector(vcpu, reg);
11081140
case KVM_REG_RISCV_ISA_EXT:
11091141
return kvm_riscv_vcpu_set_reg_isa_ext(vcpu, reg);
11101142
case KVM_REG_RISCV_SBI_EXT:
11111143
return kvm_riscv_vcpu_set_reg_sbi_ext(vcpu, reg);
1112-
case KVM_REG_RISCV_VECTOR:
1113-
return kvm_riscv_vcpu_set_reg_vector(vcpu, reg);
1144+
case KVM_REG_RISCV_SBI_STATE:
1145+
return kvm_riscv_vcpu_set_reg_sbi(vcpu, reg);
11141146
default:
11151147
break;
11161148
}
@@ -1136,12 +1168,14 @@ int kvm_riscv_vcpu_get_reg(struct kvm_vcpu *vcpu,
11361168
case KVM_REG_RISCV_FP_D:
11371169
return kvm_riscv_vcpu_get_reg_fp(vcpu, reg,
11381170
KVM_REG_RISCV_FP_D);
1171+
case KVM_REG_RISCV_VECTOR:
1172+
return kvm_riscv_vcpu_get_reg_vector(vcpu, reg);
11391173
case KVM_REG_RISCV_ISA_EXT:
11401174
return kvm_riscv_vcpu_get_reg_isa_ext(vcpu, reg);
11411175
case KVM_REG_RISCV_SBI_EXT:
11421176
return kvm_riscv_vcpu_get_reg_sbi_ext(vcpu, reg);
1143-
case KVM_REG_RISCV_VECTOR:
1144-
return kvm_riscv_vcpu_get_reg_vector(vcpu, reg);
1177+
case KVM_REG_RISCV_SBI_STATE:
1178+
return kvm_riscv_vcpu_get_reg_sbi(vcpu, reg);
11451179
default:
11461180
break;
11471181
}

arch/riscv/kvm/vcpu_sbi.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,64 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
325325
return 0;
326326
}
327327

328+
int kvm_riscv_vcpu_set_reg_sbi(struct kvm_vcpu *vcpu,
329+
const struct kvm_one_reg *reg)
330+
{
331+
unsigned long __user *uaddr =
332+
(unsigned long __user *)(unsigned long)reg->addr;
333+
unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
334+
KVM_REG_SIZE_MASK |
335+
KVM_REG_RISCV_SBI_STATE);
336+
unsigned long reg_subtype, reg_val;
337+
338+
if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
339+
return -EINVAL;
340+
341+
if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
342+
return -EFAULT;
343+
344+
reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
345+
reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
346+
347+
switch (reg_subtype) {
348+
default:
349+
return -EINVAL;
350+
}
351+
352+
return 0;
353+
}
354+
355+
int kvm_riscv_vcpu_get_reg_sbi(struct kvm_vcpu *vcpu,
356+
const struct kvm_one_reg *reg)
357+
{
358+
unsigned long __user *uaddr =
359+
(unsigned long __user *)(unsigned long)reg->addr;
360+
unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
361+
KVM_REG_SIZE_MASK |
362+
KVM_REG_RISCV_SBI_STATE);
363+
unsigned long reg_subtype, reg_val;
364+
int ret;
365+
366+
if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
367+
return -EINVAL;
368+
369+
reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
370+
reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
371+
372+
switch (reg_subtype) {
373+
default:
374+
return -EINVAL;
375+
}
376+
377+
if (ret)
378+
return ret;
379+
380+
if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
381+
return -EFAULT;
382+
383+
return 0;
384+
}
385+
328386
const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
329387
struct kvm_vcpu *vcpu, unsigned long extid)
330388
{

0 commit comments

Comments
 (0)