RISC-V: KVM: Implement kvm_arch_vcpu_ioctl_set_guest_debug()
kvm_vm_ioctl_check_extension(): Return 1 if KVM_CAP_SET_GUEST_DEBUG is been checked. kvm_arch_vcpu_ioctl_set_guest_debug(): Update the guest_debug flags from userspace accordingly. Route the breakpoint exceptions to HS mode if the VCPU is being debugged by userspace, by clearing the corresponding bit in hedeleg. Initialize the hedeleg configuration in kvm_riscv_vcpu_setup_config(). Write the actual CSR in kvm_arch_vcpu_load(). Signed-off-by: Chao Du <duchao@eswincomputing.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20240402062628.5425-2-duchao@eswincomputing.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
parent
fec50db703
commit
edcbe90f12
@ -43,6 +43,17 @@
|
|||||||
KVM_ARCH_REQ_FLAGS(5, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
|
KVM_ARCH_REQ_FLAGS(5, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
|
||||||
#define KVM_REQ_STEAL_UPDATE KVM_ARCH_REQ(6)
|
#define KVM_REQ_STEAL_UPDATE KVM_ARCH_REQ(6)
|
||||||
|
|
||||||
|
#define KVM_HEDELEG_DEFAULT (BIT(EXC_INST_MISALIGNED) | \
|
||||||
|
BIT(EXC_BREAKPOINT) | \
|
||||||
|
BIT(EXC_SYSCALL) | \
|
||||||
|
BIT(EXC_INST_PAGE_FAULT) | \
|
||||||
|
BIT(EXC_LOAD_PAGE_FAULT) | \
|
||||||
|
BIT(EXC_STORE_PAGE_FAULT))
|
||||||
|
|
||||||
|
#define KVM_HIDELEG_DEFAULT (BIT(IRQ_VS_SOFT) | \
|
||||||
|
BIT(IRQ_VS_TIMER) | \
|
||||||
|
BIT(IRQ_VS_EXT))
|
||||||
|
|
||||||
enum kvm_riscv_hfence_type {
|
enum kvm_riscv_hfence_type {
|
||||||
KVM_RISCV_HFENCE_UNKNOWN = 0,
|
KVM_RISCV_HFENCE_UNKNOWN = 0,
|
||||||
KVM_RISCV_HFENCE_GVMA_VMID_GPA,
|
KVM_RISCV_HFENCE_GVMA_VMID_GPA,
|
||||||
@ -169,6 +180,7 @@ struct kvm_vcpu_csr {
|
|||||||
struct kvm_vcpu_config {
|
struct kvm_vcpu_config {
|
||||||
u64 henvcfg;
|
u64 henvcfg;
|
||||||
u64 hstateen0;
|
u64 hstateen0;
|
||||||
|
unsigned long hedeleg;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kvm_vcpu_smstateen_csr {
|
struct kvm_vcpu_smstateen_csr {
|
||||||
|
@ -22,22 +22,8 @@ long kvm_arch_dev_ioctl(struct file *filp,
|
|||||||
|
|
||||||
int kvm_arch_hardware_enable(void)
|
int kvm_arch_hardware_enable(void)
|
||||||
{
|
{
|
||||||
unsigned long hideleg, hedeleg;
|
csr_write(CSR_HEDELEG, KVM_HEDELEG_DEFAULT);
|
||||||
|
csr_write(CSR_HIDELEG, KVM_HIDELEG_DEFAULT);
|
||||||
hedeleg = 0;
|
|
||||||
hedeleg |= (1UL << EXC_INST_MISALIGNED);
|
|
||||||
hedeleg |= (1UL << EXC_BREAKPOINT);
|
|
||||||
hedeleg |= (1UL << EXC_SYSCALL);
|
|
||||||
hedeleg |= (1UL << EXC_INST_PAGE_FAULT);
|
|
||||||
hedeleg |= (1UL << EXC_LOAD_PAGE_FAULT);
|
|
||||||
hedeleg |= (1UL << EXC_STORE_PAGE_FAULT);
|
|
||||||
csr_write(CSR_HEDELEG, hedeleg);
|
|
||||||
|
|
||||||
hideleg = 0;
|
|
||||||
hideleg |= (1UL << IRQ_VS_SOFT);
|
|
||||||
hideleg |= (1UL << IRQ_VS_TIMER);
|
|
||||||
hideleg |= (1UL << IRQ_VS_EXT);
|
|
||||||
csr_write(CSR_HIDELEG, hideleg);
|
|
||||||
|
|
||||||
/* VS should access only the time counter directly. Everything else should trap */
|
/* VS should access only the time counter directly. Everything else should trap */
|
||||||
csr_write(CSR_HCOUNTEREN, 0x02);
|
csr_write(CSR_HCOUNTEREN, 0x02);
|
||||||
|
@ -475,8 +475,15 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
|
|||||||
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
|
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
|
||||||
struct kvm_guest_debug *dbg)
|
struct kvm_guest_debug *dbg)
|
||||||
{
|
{
|
||||||
/* TODO; To be implemented later. */
|
if (dbg->control & KVM_GUESTDBG_ENABLE) {
|
||||||
return -EINVAL;
|
vcpu->guest_debug = dbg->control;
|
||||||
|
vcpu->arch.cfg.hedeleg &= ~BIT(EXC_BREAKPOINT);
|
||||||
|
} else {
|
||||||
|
vcpu->guest_debug = 0;
|
||||||
|
vcpu->arch.cfg.hedeleg |= BIT(EXC_BREAKPOINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
|
static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
|
||||||
@ -505,6 +512,10 @@ static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
|
|||||||
if (riscv_isa_extension_available(isa, SMSTATEEN))
|
if (riscv_isa_extension_available(isa, SMSTATEEN))
|
||||||
cfg->hstateen0 |= SMSTATEEN0_SSTATEEN0;
|
cfg->hstateen0 |= SMSTATEEN0_SSTATEEN0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg->hedeleg = KVM_HEDELEG_DEFAULT;
|
||||||
|
if (vcpu->guest_debug)
|
||||||
|
cfg->hedeleg &= ~BIT(EXC_BREAKPOINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||||
@ -519,6 +530,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|||||||
csr_write(CSR_VSEPC, csr->vsepc);
|
csr_write(CSR_VSEPC, csr->vsepc);
|
||||||
csr_write(CSR_VSCAUSE, csr->vscause);
|
csr_write(CSR_VSCAUSE, csr->vscause);
|
||||||
csr_write(CSR_VSTVAL, csr->vstval);
|
csr_write(CSR_VSTVAL, csr->vstval);
|
||||||
|
csr_write(CSR_HEDELEG, cfg->hedeleg);
|
||||||
csr_write(CSR_HVIP, csr->hvip);
|
csr_write(CSR_HVIP, csr->hvip);
|
||||||
csr_write(CSR_VSATP, csr->vsatp);
|
csr_write(CSR_VSATP, csr->vsatp);
|
||||||
csr_write(CSR_HENVCFG, cfg->henvcfg);
|
csr_write(CSR_HENVCFG, cfg->henvcfg);
|
||||||
|
@ -186,6 +186,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||||||
case KVM_CAP_READONLY_MEM:
|
case KVM_CAP_READONLY_MEM:
|
||||||
case KVM_CAP_MP_STATE:
|
case KVM_CAP_MP_STATE:
|
||||||
case KVM_CAP_IMMEDIATE_EXIT:
|
case KVM_CAP_IMMEDIATE_EXIT:
|
||||||
|
case KVM_CAP_SET_GUEST_DEBUG:
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_CAP_NR_VCPUS:
|
case KVM_CAP_NR_VCPUS:
|
||||||
|
Loading…
Reference in New Issue
Block a user