arch/arm64/kvm/debug.c

Source file repositories/reference/linux-study-clean/arch/arm64/kvm/debug.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/debug.c
Extension
.c
Size
8466 bytes
Lines
294
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
			if (*vcpu_cpsr(vcpu) & DBG_SPSR_SS)
				vcpu_clear_flag(vcpu, GUEST_SS_ACTIVE_PENDING);
			else
				vcpu_set_flag(vcpu, GUEST_SS_ACTIVE_PENDING);

			if (!vcpu_get_flag(vcpu, HOST_SS_ACTIVE_PENDING))
				*vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
			else
				*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
		}
	} else {
		mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);

		if (mdscr & (MDSCR_EL1_KDE | MDSCR_EL1_MDE))
			vcpu->arch.debug_owner = VCPU_DEBUG_GUEST_OWNED;
		else
			vcpu->arch.debug_owner = VCPU_DEBUG_FREE;
	}

	kvm_arm_setup_mdcr_el2(vcpu);
}

void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu)
{
	if (has_vhe())
		write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2);

	if (likely(!(vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
		return;

	/*
	 * Save the host's software step state and restore the guest's before
	 * potentially returning to userspace.
	 */
	if (!(*vcpu_cpsr(vcpu) & DBG_SPSR_SS))
		vcpu_set_flag(vcpu, HOST_SS_ACTIVE_PENDING);
	else
		vcpu_clear_flag(vcpu, HOST_SS_ACTIVE_PENDING);

	if (vcpu_get_flag(vcpu, GUEST_SS_ACTIVE_PENDING))
		*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
	else
		*vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
}

/*
 * Updates ownership of the debug registers after a trapped guest access to a
 * breakpoint/watchpoint register. Host ownership of the debug registers is of
 * strictly higher priority, and it is the responsibility of the VMM to emulate
 * guest debug exceptions in this configuration.
 */
void kvm_debug_set_guest_ownership(struct kvm_vcpu *vcpu)
{
	if (kvm_host_owns_debug_regs(vcpu))
		return;

	vcpu->arch.debug_owner = VCPU_DEBUG_GUEST_OWNED;
	kvm_arm_setup_mdcr_el2(vcpu);
}

void kvm_debug_handle_oslar(struct kvm_vcpu *vcpu, u64 val)
{
	if (val & OSLAR_EL1_OSLK)
		__vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, |=, OSLSR_EL1_OSLK);
	else
		__vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, &=, ~OSLSR_EL1_OSLK);

	preempt_disable();
	kvm_arch_vcpu_put(vcpu);
	kvm_arch_vcpu_load(vcpu, smp_processor_id());
	preempt_enable();
}

static bool skip_trbe_access(bool skip_condition)
{
	return (WARN_ON_ONCE(preemptible()) || skip_condition ||
		is_protected_kvm_enabled() || !is_kvm_arm_initialised());
}

void kvm_enable_trbe(void)
{
	if (!skip_trbe_access(has_vhe()))
		host_data_set_flag(TRBE_ENABLED);
}
EXPORT_SYMBOL_GPL(kvm_enable_trbe);

void kvm_disable_trbe(void)
{
	if (!skip_trbe_access(has_vhe()))

Annotation

Implementation Notes