[PATCH v6 3/7] KVM: arm64: Handle DABT caused by LS64* instructions on unsupported memory

Oliver Upton oliver.upton at linux.dev
Fri Oct 24 12:54:01 PDT 2025


Hi Zhou,

On Fri, Oct 24, 2025 at 05:08:15PM +0800, Zhou Wang wrote:
> +/**
> + * kvm_inject_dabt_excl_atomic - inject a data abort for unsupported exclusive
> + *				 or atomic access
> + * @vcpu: The VCPU to receive the data abort
> + * @addr: The address to report in the DFAR
> + *
> + * It is assumed that this code is called from the VCPU thread and that the
> + * VCPU therefore is not currently executing guest code.
> + */
> +void kvm_inject_dabt_excl_atomic(struct kvm_vcpu *vcpu, u64 addr)
> +{
> +	u64 esr;
> +
> +	/* Reuse the general DABT injection routine and modify the DFSC */
> +	kvm_inject_sea(vcpu, false, addr);

This potentially injects a nested SEA which I'm not sure you want. There
still is an interaction with nested, from DDI0487L.a B2.2.6:

  For the EL1&0 translation regime, if the atomic instruction is not
  supported because of the memory type that is defined in the first
  stage of translation, or the second stage of translation is not
  enabled, then this exception is a first stage abort and is taken to
  EL1. Otherwise, the exception is a second stage abort and is taken to EL2.

We don't need to worry about the S1 memory type since hardware will
handle that for us. But we do need to consider whether the guest
hypervisor enabled stage-2 translation or not and route accordingly.

int kvm_inject_nested_excl_atomic(struct kvm_vcpu *vcpu, u64 addr)
{
	u64 esr = FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_DABT_LOW) |
		  FIELD_PREP(ESR_ELx_FSC, ESR_ELx_FSC_EXCL_ATOMIC) |
		  ESR_ELx_IL;

	vcpu_write_sys_reg(vcpu, addr, FAR_EL2);
	return kvm_inject_nested_sync(vcpu, esr);
}

int kvm_inject_excl_atomic(struct kvm_vcpu *vcpu, u64 addr)
{
	if (is_nested_ctxt(vcpu) && (vcpu_read_sys_reg(vcpu, HCR_EL2) & HCR_VM))
		return kvm_inject_nested_excl_atomic(vcpu, addr);

	__kvm_inject_sea(vcpu, false, addr);
	esr = vcpu_read_sys_reg(vcpu, exception_esr_elx(vcpu));
	esr &= ~ESR_ELx_FSC;
	esr |= ESR_ELx_FSC_EXCL_ATOMIC;
	vcpu_write_sys_reg(vcpu, esr, exception_esr_elx(vcpu));
	return 1;
}

Thanks,
Oliver



More information about the linux-arm-kernel mailing list