arch/arm64/kvm/hyp/vhe/sysreg-sr.c

Source file repositories/reference/linux-study-clean/arch/arm64/kvm/hyp/vhe/sysreg-sr.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/hyp/vhe/sysreg-sr.c
Extension
.c
Size
10104 bytes
Lines
294
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source 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 (ctxt_has_tcrx(&vcpu->arch.ctxt)) {
			__vcpu_assign_sys_reg(vcpu, TCR2_EL2, read_sysreg_el1(SYS_TCR2));

			if (ctxt_has_s1pie(&vcpu->arch.ctxt)) {
				__vcpu_assign_sys_reg(vcpu, PIRE0_EL2, read_sysreg_el1(SYS_PIRE0));
				__vcpu_assign_sys_reg(vcpu, PIR_EL2, read_sysreg_el1(SYS_PIR));
			}

			if (ctxt_has_s1poe(&vcpu->arch.ctxt))
				__vcpu_assign_sys_reg(vcpu, POR_EL2, read_sysreg_el1(SYS_POR));
		}

		/*
		 * The EL1 view of CNTKCTL_EL1 has a bunch of RES0 bits where
		 * the interesting CNTHCTL_EL2 bits live. So preserve these
		 * bits when reading back the guest-visible value.
		 */
		val = read_sysreg_el1(SYS_CNTKCTL);
		val &= CNTKCTL_VALID_BITS;
		__vcpu_rmw_sys_reg(vcpu, CNTHCTL_EL2, &=, ~CNTKCTL_VALID_BITS);
		__vcpu_rmw_sys_reg(vcpu, CNTHCTL_EL2, |=, val);
	}

	__vcpu_assign_sys_reg(vcpu, SP_EL2,	 read_sysreg(sp_el1));
	__vcpu_assign_sys_reg(vcpu, ELR_EL2,	 read_sysreg_el1(SYS_ELR));
	__vcpu_assign_sys_reg(vcpu, SPSR_EL2,	 read_sysreg_el1(SYS_SPSR));

	if (ctxt_has_sctlr2(&vcpu->arch.ctxt))
		__vcpu_assign_sys_reg(vcpu, SCTLR2_EL2, read_sysreg_el1(SYS_SCTLR2));
}

static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu)
{
	u64 val;

	/* These registers are common with EL1 */
	write_sysreg(__vcpu_sys_reg(vcpu, PAR_EL1),	par_el1);
	write_sysreg(__vcpu_sys_reg(vcpu, TPIDR_EL1),	tpidr_el1);

	write_sysreg(ctxt_midr_el1(&vcpu->arch.ctxt),			vpidr_el2);
	write_sysreg(__vcpu_sys_reg(vcpu, MPIDR_EL1),			vmpidr_el2);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, MAIR_EL2),		SYS_MAIR);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, VBAR_EL2),		SYS_VBAR);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, CONTEXTIDR_EL2),		SYS_CONTEXTIDR);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, AMAIR_EL2),		SYS_AMAIR);

	if (vcpu_el2_e2h_is_set(vcpu)) {
		/*
		 * In VHE mode those registers are compatible between
		 * EL1 and EL2.
		 */
		write_sysreg_el1(__vcpu_sys_reg(vcpu, SCTLR_EL2),   SYS_SCTLR);
		write_sysreg_el1(__vcpu_sys_reg(vcpu, CPTR_EL2),    SYS_CPACR);
		write_sysreg_el1(__vcpu_sys_reg(vcpu, TTBR0_EL2),   SYS_TTBR0);
		write_sysreg_el1(__vcpu_sys_reg(vcpu, TTBR1_EL2),   SYS_TTBR1);
		write_sysreg_el1(__vcpu_sys_reg(vcpu, TCR_EL2),	    SYS_TCR);
		write_sysreg_el1(__vcpu_sys_reg(vcpu, CNTHCTL_EL2), SYS_CNTKCTL);
	} else {
		/*
		 * CNTHCTL_EL2 only affects EL1 when running nVHE, so
		 * no need to restore it.
		 */
		val = translate_sctlr_el2_to_sctlr_el1(__vcpu_sys_reg(vcpu, SCTLR_EL2));
		write_sysreg_el1(val, SYS_SCTLR);
		val = translate_cptr_el2_to_cpacr_el1(__vcpu_sys_reg(vcpu, CPTR_EL2));
		write_sysreg_el1(val, SYS_CPACR);
		val = translate_ttbr0_el2_to_ttbr0_el1(__vcpu_sys_reg(vcpu, TTBR0_EL2));
		write_sysreg_el1(val, SYS_TTBR0);
		val = translate_tcr_el2_to_tcr_el1(__vcpu_sys_reg(vcpu, TCR_EL2));
		write_sysreg_el1(val, SYS_TCR);
	}

	if (ctxt_has_tcrx(&vcpu->arch.ctxt)) {
		write_sysreg_el1(__vcpu_sys_reg(vcpu, TCR2_EL2), SYS_TCR2);

		if (ctxt_has_s1pie(&vcpu->arch.ctxt)) {
			write_sysreg_el1(__vcpu_sys_reg(vcpu, PIR_EL2), SYS_PIR);
			write_sysreg_el1(__vcpu_sys_reg(vcpu, PIRE0_EL2), SYS_PIRE0);
		}

		if (ctxt_has_s1poe(&vcpu->arch.ctxt))
			write_sysreg_el1(__vcpu_sys_reg(vcpu, POR_EL2), SYS_POR);
	}

	write_sysreg_el1(__vcpu_sys_reg(vcpu, ESR_EL2),		SYS_ESR);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, AFSR0_EL2),	SYS_AFSR0);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, AFSR1_EL2),	SYS_AFSR1);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, FAR_EL2),		SYS_FAR);
	write_sysreg(__vcpu_sys_reg(vcpu, SP_EL2),		sp_el1);
	write_sysreg_el1(__vcpu_sys_reg(vcpu, ELR_EL2),		SYS_ELR);

Annotation

Implementation Notes