Commit 9f2011ed authored by Bibo Mao's avatar Bibo Mao Committed by Xianglai Li
Browse files

LoongArch: KVM: Add software breakpoint support

mainline inclusion
from mainline-v6.10-rc1
commit 163e9fc6957fc24d1d6c0a30a3febfd2ecade039
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAZJDO


CVE: NA

--------------------------------

When VM runs in kvm mode, system will not exit to host mode when
executing a general software breakpoint instruction such as INSN_BREAK,
trap exception happens in guest mode rather than host mode. In order to
debug guest kernel on host side, one mechanism should be used to let VM
exit to host mode.

Here a hypercall instruction with a special code is used for software
breakpoint usage. VM exits to host mode and kvm hypervisor identifies
the special hypercall code and sets exit_reason with KVM_EXIT_DEBUG. And
then let qemu handle it.

Idea comes from ppc kvm, one api KVM_REG_LOONGARCH_DEBUG_INST is added
to get the hypercall code. VMM needs get sw breakpoint instruction with
this api and set the corresponding sw break point for guest kernel.

Signed-off-by: default avatarBibo Mao <maobibo@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
Signed-off-by: default avatarXianglai Li <lixianglai@loongson.cn>
parent 0c71893b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -35,6 +35,11 @@
#define KVM_HALT_POLL_NS_DEFAULT	500000
#define KVM_REQ_RECORD_STEAL		KVM_ARCH_REQ(1)

#define KVM_GUESTDBG_SW_BP_MASK		\
	(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)
#define KVM_GUESTDBG_VALID_MASK		\
	(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP | KVM_GUESTDBG_SINGLESTEP)

/* KVM_IRQ_LINE irq field index values */
#define KVM_LOONGARCH_IRQ_TYPE_SHIFT	24
#define KVM_LOONGARCH_IRQ_TYPE_MASK	0xff
+6 −6
Original line number Diff line number Diff line
@@ -834,9 +834,9 @@ static int kvm_save_notify(struct kvm_vcpu *vcpu)

static int kvm_handle_hypercall(struct kvm_vcpu *vcpu)
{
	int ret;
	larch_inst inst;
	unsigned int code;
	int ret;

	inst.word = vcpu->arch.badi;
	code = inst.reg0i15_format.immediate;
@@ -848,13 +848,13 @@ static int kvm_handle_hypercall(struct kvm_vcpu *vcpu)
		kvm_handle_service(vcpu);
		break;
	case KVM_HCALL_SWDBG:
		/* KVM_HC_SWDBG only in effective when SW_BP is enabled */
		if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) {
		/* KVM_HCALL_SWDBG only in effective when SW_BP is enabled */
		if (vcpu->guest_debug & KVM_GUESTDBG_SW_BP_MASK) {
			vcpu->run->exit_reason = KVM_EXIT_DEBUG;
			ret = RESUME_HOST;
		} else
			vcpu->arch.gprs[LOONGARCH_GPR_A0] = KVM_HCALL_INVALID_CODE;
			break;
		}
		fallthrough;
	default:
		/* Treat it as noop intruction, only set return value */
		vcpu->arch.gprs[LOONGARCH_GPR_A0] = KVM_HCALL_INVALID_CODE;
+1 −1
Original line number Diff line number Diff line
@@ -782,7 +782,7 @@ static int kvm_get_one_reg(struct kvm_vcpu *vcpu,
			*v = drdtime() + vcpu->kvm->arch.time_offset;
			break;
		case KVM_REG_LOONGARCH_DEBUG_INST:
			*v = INSN_HVCL + KVM_HCALL_SWDBG;
			*v = INSN_HVCL | KVM_HCALL_SWDBG;
			break;
		default:
			ret = -EINVAL;