arch/arm64/include/asm/el2_setup.h

Source file repositories/reference/linux-study-clean/arch/arm64/include/asm/el2_setup.h

File Facts

System
Linux kernel
Corpus path
arch/arm64/include/asm/el2_setup.h
Extension
.h
Size
17076 bytes
Lines
606
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

#ifndef __ARM_KVM_INIT_H__
#define __ARM_KVM_INIT_H__

#ifndef __ASSEMBLER__
#error Assembly-only header
#endif

#include <asm/kvm_arm.h>
#include <asm/ptrace.h>
#include <asm/sysreg.h>
#include <linux/irqchip/arm-gic-v3.h>

.macro init_el2_hcr	val
	mov_q	x0, \val

	/*
	 * Compliant CPUs advertise their VHE-onlyness with
	 * ID_AA64MMFR4_EL1.E2H0 < 0. On such CPUs HCR_EL2.E2H is RES1, but it
	 * can reset into an UNKNOWN state and might not read as 1 until it has
	 * been initialized explicitly.
	 * Initialize HCR_EL2.E2H so that later code can rely upon HCR_EL2.E2H
	 * indicating whether the CPU is running in E2H mode.
	 */
	mrs_s	x1, SYS_ID_AA64MMFR4_EL1
	sbfx	x1, x1, #ID_AA64MMFR4_EL1_E2H0_SHIFT, #ID_AA64MMFR4_EL1_E2H0_WIDTH
	cmp	x1, #0
	b.lt	.LnE2H0_\@

	/*
	 * Unfortunately, HCR_EL2.E2H can be RES1 even if not advertised
	 * as such via ID_AA64MMFR4_EL1.E2H0:
	 *
	 * - Fruity CPUs predate the !FEAT_E2H0 relaxation, and seem to
	 *   have HCR_EL2.E2H implemented as RAO/WI.
	 *
	 * - On CPUs that lack FEAT_FGT, a hypervisor can't trap guest
	 *   reads of ID_AA64MMFR4_EL1 to advertise !FEAT_E2H0. NV
	 *   guests on these hosts can write to HCR_EL2.E2H without
	 *   trapping to the hypervisor, but these writes have no
	 *   functional effect.
	 *
	 * Handle both cases by checking for an essential VHE property
	 * (system register remapping) to decide whether we're
	 * effectively VHE-only or not.
	 */
	msr_hcr_el2 x0		// Setup HCR_EL2 as nVHE
	mov	x1, #1		// Write something to FAR_EL1
	msr	far_el1, x1
	isb
	mov	x1, #2		// Try to overwrite it via FAR_EL2
	msr	far_el2, x1
	isb
	mrs	x1, far_el1	// If we see the latest write in FAR_EL1,
	cmp	x1, #2		// we can safely assume we are VHE only.
	b.ne	.LnVHE_\@	// Otherwise, we know that nVHE works.

.LnE2H0_\@:
	orr	x0, x0, #HCR_E2H
	msr_hcr_el2 x0
.LnVHE_\@:
.endm

.macro __init_el2_sctlr
	mov_q	x0, INIT_SCTLR_EL2_MMU_OFF
	msr	sctlr_el2, x0
	isb
.endm

.macro __init_el2_hcrx
	mrs	x0, id_aa64mmfr1_el1
	ubfx	x0, x0, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4
	cbz	x0, .Lskip_hcrx_\@
	mov_q	x0, (HCRX_EL2_MSCEn | HCRX_EL2_TCR2En | HCRX_EL2_EnFPM)

        /* Enable GCS if supported */
	mrs_s	x1, SYS_ID_AA64PFR1_EL1
	ubfx	x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4
	cbz	x1, .Lskip_gcs_hcrx_\@
	orr	x0, x0, #HCRX_EL2_GCSEn

.Lskip_gcs_hcrx_\@:
	/* Enable LS64, LS64_V if supported */
	mrs_s	x1, SYS_ID_AA64ISAR1_EL1
	ubfx	x1, x1, #ID_AA64ISAR1_EL1_LS64_SHIFT, #4
	cbz	x1, .Lset_hcrx_\@
	orr	x0, x0, #HCRX_EL2_EnALS
	cmp	x1, #ID_AA64ISAR1_EL1_LS64_LS64_V
	b.lt	.Lset_hcrx_\@
	orr	x0, x0, #HCRX_EL2_EnASR

Annotation

Implementation Notes