Skip to content

Commit 7d50dd5

Browse files
committed
RISC-V: KVM: Implement subtype for CSR ONE_REG interface
To make the CSR ONE_REG interface extensible, we implement subtype for the CSR ONE_REG IDs. The existing CSR ONE_REG IDs are treated as subtype = 0 (aka General CSRs). Signed-off-by: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Atish Patra <atishp@rivosinc.com> Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent 54e4332 commit 7d50dd5

2 files changed

Lines changed: 69 additions & 22 deletions

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ struct kvm_riscv_core {
6565
#define KVM_RISCV_MODE_S 1
6666
#define KVM_RISCV_MODE_U 0
6767

68-
/* CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
68+
/* General CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
6969
struct kvm_riscv_csr {
7070
unsigned long sstatus;
7171
unsigned long sie;
@@ -152,6 +152,7 @@ enum KVM_RISCV_SBI_EXT_ID {
152152

153153
/* Control and status registers are mapped as type 3 */
154154
#define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT)
155+
#define KVM_REG_RISCV_CSR_GENERAL (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
155156
#define KVM_REG_RISCV_CSR_REG(name) \
156157
(offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long))
157158

arch/riscv/kvm/vcpu.c

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -460,27 +460,72 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu,
460460
return 0;
461461
}
462462

463+
static int kvm_riscv_vcpu_general_get_csr(struct kvm_vcpu *vcpu,
464+
unsigned long reg_num,
465+
unsigned long *out_val)
466+
{
467+
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
468+
469+
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
470+
return -EINVAL;
471+
472+
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
473+
kvm_riscv_vcpu_flush_interrupts(vcpu);
474+
*out_val = (csr->hvip >> VSIP_TO_HVIP_SHIFT) & VSIP_VALID_MASK;
475+
} else
476+
*out_val = ((unsigned long *)csr)[reg_num];
477+
478+
return 0;
479+
}
480+
481+
static inline int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
482+
unsigned long reg_num,
483+
unsigned long reg_val)
484+
{
485+
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
486+
487+
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
488+
return -EINVAL;
489+
490+
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
491+
reg_val &= VSIP_VALID_MASK;
492+
reg_val <<= VSIP_TO_HVIP_SHIFT;
493+
}
494+
495+
((unsigned long *)csr)[reg_num] = reg_val;
496+
497+
if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
498+
WRITE_ONCE(vcpu->arch.irqs_pending_mask, 0);
499+
500+
return 0;
501+
}
502+
463503
static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
464504
const struct kvm_one_reg *reg)
465505
{
466-
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
506+
int rc;
467507
unsigned long __user *uaddr =
468508
(unsigned long __user *)(unsigned long)reg->addr;
469509
unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
470510
KVM_REG_SIZE_MASK |
471511
KVM_REG_RISCV_CSR);
472-
unsigned long reg_val;
512+
unsigned long reg_val, reg_subtype;
473513

474514
if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
475515
return -EINVAL;
476-
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
477-
return -EINVAL;
478516

479-
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
480-
kvm_riscv_vcpu_flush_interrupts(vcpu);
481-
reg_val = (csr->hvip >> VSIP_TO_HVIP_SHIFT) & VSIP_VALID_MASK;
482-
} else
483-
reg_val = ((unsigned long *)csr)[reg_num];
517+
reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
518+
reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
519+
switch (reg_subtype) {
520+
case KVM_REG_RISCV_CSR_GENERAL:
521+
rc = kvm_riscv_vcpu_general_get_csr(vcpu, reg_num, &reg_val);
522+
break;
523+
default:
524+
rc = -EINVAL;
525+
break;
526+
}
527+
if (rc)
528+
return rc;
484529

485530
if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
486531
return -EFAULT;
@@ -491,31 +536,32 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
491536
static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu,
492537
const struct kvm_one_reg *reg)
493538
{
494-
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
539+
int rc;
495540
unsigned long __user *uaddr =
496541
(unsigned long __user *)(unsigned long)reg->addr;
497542
unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
498543
KVM_REG_SIZE_MASK |
499544
KVM_REG_RISCV_CSR);
500-
unsigned long reg_val;
545+
unsigned long reg_val, reg_subtype;
501546

502547
if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
503548
return -EINVAL;
504-
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
505-
return -EINVAL;
506549

507550
if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
508551
return -EFAULT;
509552

510-
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
511-
reg_val &= VSIP_VALID_MASK;
512-
reg_val <<= VSIP_TO_HVIP_SHIFT;
553+
reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
554+
reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
555+
switch (reg_subtype) {
556+
case KVM_REG_RISCV_CSR_GENERAL:
557+
rc = kvm_riscv_vcpu_general_set_csr(vcpu, reg_num, reg_val);
558+
break;
559+
default:
560+
rc = -EINVAL;
561+
break;
513562
}
514-
515-
((unsigned long *)csr)[reg_num] = reg_val;
516-
517-
if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
518-
WRITE_ONCE(vcpu->arch.irqs_pending_mask, 0);
563+
if (rc)
564+
return rc;
519565

520566
return 0;
521567
}

0 commit comments

Comments
 (0)