linux-next: manual merge of the kvm-arm tree with the origin tree
From: Mark Brown
Date: Fri Oct 02 2026 - 19:03:51 EST
Hi all,
Today's linux-next merge of the kvm-arm tree got a conflict in:
arch/arm64/kvm/hyp/nvhe/hyp-main.c
between commit:
04447b95c62be ("KVM: arm64: Use the host's HCR_EL2 for non-protected VMs in pKVM")
from the origin tree and commits:
872383bd12e11 ("KVM: arm64: Add per-EC entry/exit state marshalling for protected guests")
06499de8f998e ("KVM: arm64: Skip fixed-feature state flush for protected vCPUs")
from the kvm-arm tree. I am very unconvinced about the merge below.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc arch/arm64/kvm/hyp/nvhe/hyp-main.c
index ac64a036b0a95,c709a6ff7448b..0000000000000
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@@ -216,7 -693,8 +693,9 @@@ static void sync_debug_state(struct pkv
static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
{
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
+ u64 host_hcr_mask = PKVM_HCR_EL2_HOST_PVM;
+ hyp_entry_exit_handler_fn ec_handler;
+ u8 esr_ec;
fpsimd_sve_flush();
flush_debug_state(hyp_vcpu);
@@@ -229,35 -707,60 +708,64 @@@
if (!pkvm_hyp_vcpu_is_protected(hyp_vcpu)) {
if (vcpu_get_flag(host_vcpu, PKVM_HOST_STATE_DIRTY))
flush_hyp_vcpu_state(hyp_vcpu);
+ host_hcr_mask = PKVM_HCR_EL2_HOST_NPVM;
+ } else {
+ hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt;
+
+ hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE);
+ hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
+ (HCR_TWI | HCR_TWE);
+
+ hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
+ hyp_vcpu->vcpu.arch.iflags = host_vcpu->arch.iflags;
}
/* __hyp_running_vcpu must be NULL in a guest context. */
hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
- hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
/*
- * HCR_EL2.VSE is host-owned (a pending virtual SError to inject), not a
- * trap-control bit, so it must flow to the hyp vCPU alongside TWI/TWE
- * for the vSError to be delivered. sync_hyp_vcpu() reflects it back.
+ * A host-injected vSError is masked by the guest's own PSTATE.A, so it
+ * applies to protected guests too.
*/
- hyp_vcpu->vcpu.arch.hcr_el2 &= ~HCR_VSE;
- hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) & HCR_VSE;
- hyp_vcpu->vcpu.arch.vsesr_el2 = host_vcpu->arch.vsesr_el2;
+ hyp_vcpu->vcpu.arch.hcr_el2 &= ~host_hcr_mask;
+ hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) & host_hcr_mask;
+
- hyp_vcpu->vcpu.arch.iflags = host_vcpu->arch.iflags;
-
+ hyp_vcpu->vcpu.arch.vsesr_el2 = host_vcpu->arch.vsesr_el2;
flush_hyp_vgic_state(hyp_vcpu);
+ flush_hyp_timer_state(hyp_vcpu);
hyp_vcpu->vcpu.arch.pid = host_vcpu->arch.pid;
+
+ switch (ARM_EXCEPTION_CODE(hyp_vcpu->exit_code)) {
+ case ARM_EXCEPTION_IRQ:
+ case ARM_EXCEPTION_EL1_SERROR:
+ case ARM_EXCEPTION_IL:
+ break;
+ case ARM_EXCEPTION_TRAP:
+ /* Nothing was marshalled for this trap, see sync_hyp_vcpu(). */
+ if (ARM_SERROR_PENDING(hyp_vcpu->exit_code))
+ break;
+
+ if (pkvm_hyp_vcpu_is_protected(hyp_vcpu)) {
+ esr_ec = ESR_ELx_EC(kvm_vcpu_get_esr(&hyp_vcpu->vcpu));
+ ec_handler = entry_hyp_pvm_handlers[esr_ec];
+ if (ec_handler)
+ ec_handler(hyp_vcpu);
+ }
+ break;
+ default:
+ BUG();
+ }
+
+ hyp_vcpu->exit_code = 0;
}
- static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
+ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu, u32 exit_reason)
{
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
+ hyp_entry_exit_handler_fn ec_handler;
+ u8 esr_ec;
fpsimd_sve_sync(&hyp_vcpu->vcpu);
sync_debug_state(hyp_vcpu);
Attachment:
signature.asc
Description: PGP signature