Commit 7d50dd50 authored by Anup Patel's avatar Anup Patel Committed by Anup Patel

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: default avatarAnup Patel <apatel@ventanamicro.com>
Reviewed-by: default avatarAndrew Jones <ajones@ventanamicro.com>
Reviewed-by: default avatarAtish Patra <atishp@rivosinc.com>
Signed-off-by: default avatarAnup Patel <anup@brainfault.org>
parent 54e43320
...@@ -65,7 +65,7 @@ struct kvm_riscv_core { ...@@ -65,7 +65,7 @@ struct kvm_riscv_core {
#define KVM_RISCV_MODE_S 1 #define KVM_RISCV_MODE_S 1
#define KVM_RISCV_MODE_U 0 #define KVM_RISCV_MODE_U 0
/* CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ /* General CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
struct kvm_riscv_csr { struct kvm_riscv_csr {
unsigned long sstatus; unsigned long sstatus;
unsigned long sie; unsigned long sie;
...@@ -152,6 +152,7 @@ enum KVM_RISCV_SBI_EXT_ID { ...@@ -152,6 +152,7 @@ enum KVM_RISCV_SBI_EXT_ID {
/* Control and status registers are mapped as type 3 */ /* Control and status registers are mapped as type 3 */
#define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT) #define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT)
#define KVM_REG_RISCV_CSR_GENERAL (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_CSR_REG(name) \ #define KVM_REG_RISCV_CSR_REG(name) \
(offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long)) (offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long))
......
...@@ -460,27 +460,72 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu, ...@@ -460,27 +460,72 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu,
return 0; return 0;
} }
static int kvm_riscv_vcpu_general_get_csr(struct kvm_vcpu *vcpu,
unsigned long reg_num,
unsigned long *out_val)
{
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
return -EINVAL;
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
kvm_riscv_vcpu_flush_interrupts(vcpu);
*out_val = (csr->hvip >> VSIP_TO_HVIP_SHIFT) & VSIP_VALID_MASK;
} else
*out_val = ((unsigned long *)csr)[reg_num];
return 0;
}
static inline int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
unsigned long reg_num,
unsigned long reg_val)
{
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
return -EINVAL;
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
reg_val &= VSIP_VALID_MASK;
reg_val <<= VSIP_TO_HVIP_SHIFT;
}
((unsigned long *)csr)[reg_num] = reg_val;
if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
WRITE_ONCE(vcpu->arch.irqs_pending_mask, 0);
return 0;
}
static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu, static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg) const struct kvm_one_reg *reg)
{ {
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; int rc;
unsigned long __user *uaddr = unsigned long __user *uaddr =
(unsigned long __user *)(unsigned long)reg->addr; (unsigned long __user *)(unsigned long)reg->addr;
unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
KVM_REG_SIZE_MASK | KVM_REG_SIZE_MASK |
KVM_REG_RISCV_CSR); KVM_REG_RISCV_CSR);
unsigned long reg_val; unsigned long reg_val, reg_subtype;
if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
return -EINVAL; return -EINVAL;
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
return -EINVAL;
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) { reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
kvm_riscv_vcpu_flush_interrupts(vcpu); reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
reg_val = (csr->hvip >> VSIP_TO_HVIP_SHIFT) & VSIP_VALID_MASK; switch (reg_subtype) {
} else case KVM_REG_RISCV_CSR_GENERAL:
reg_val = ((unsigned long *)csr)[reg_num]; rc = kvm_riscv_vcpu_general_get_csr(vcpu, reg_num, &reg_val);
break;
default:
rc = -EINVAL;
break;
}
if (rc)
return rc;
if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id))) if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
return -EFAULT; return -EFAULT;
...@@ -491,31 +536,32 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu, ...@@ -491,31 +536,32 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu, static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg) const struct kvm_one_reg *reg)
{ {
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; int rc;
unsigned long __user *uaddr = unsigned long __user *uaddr =
(unsigned long __user *)(unsigned long)reg->addr; (unsigned long __user *)(unsigned long)reg->addr;
unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
KVM_REG_SIZE_MASK | KVM_REG_SIZE_MASK |
KVM_REG_RISCV_CSR); KVM_REG_RISCV_CSR);
unsigned long reg_val; unsigned long reg_val, reg_subtype;
if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
return -EINVAL; return -EINVAL;
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
return -EINVAL;
if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id))) if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
return -EFAULT; return -EFAULT;
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) { reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
reg_val &= VSIP_VALID_MASK; reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
reg_val <<= VSIP_TO_HVIP_SHIFT; switch (reg_subtype) {
case KVM_REG_RISCV_CSR_GENERAL:
rc = kvm_riscv_vcpu_general_set_csr(vcpu, reg_num, reg_val);
break;
default:
rc = -EINVAL;
break;
} }
if (rc)
((unsigned long *)csr)[reg_num] = reg_val; return rc;
if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
WRITE_ONCE(vcpu->arch.irqs_pending_mask, 0);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment