162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2012,2013 - ARM Ltd
462306a36Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __ARM_KVM_INIT_H__
862306a36Sopenharmony_ci#define __ARM_KVM_INIT_H__
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef __ASSEMBLY__
1162306a36Sopenharmony_ci#error Assembly-only header
1262306a36Sopenharmony_ci#endif
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <asm/kvm_arm.h>
1562306a36Sopenharmony_ci#include <asm/ptrace.h>
1662306a36Sopenharmony_ci#include <asm/sysreg.h>
1762306a36Sopenharmony_ci#include <linux/irqchip/arm-gic-v3.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci.macro __init_el2_sctlr
2062306a36Sopenharmony_ci	mov_q	x0, INIT_SCTLR_EL2_MMU_OFF
2162306a36Sopenharmony_ci	msr	sctlr_el2, x0
2262306a36Sopenharmony_ci	isb
2362306a36Sopenharmony_ci.endm
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci.macro __init_el2_hcrx
2662306a36Sopenharmony_ci	mrs	x0, id_aa64mmfr1_el1
2762306a36Sopenharmony_ci	ubfx	x0, x0, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4
2862306a36Sopenharmony_ci	cbz	x0, .Lskip_hcrx_\@
2962306a36Sopenharmony_ci	mov_q	x0, HCRX_HOST_FLAGS
3062306a36Sopenharmony_ci	msr_s	SYS_HCRX_EL2, x0
3162306a36Sopenharmony_ci.Lskip_hcrx_\@:
3262306a36Sopenharmony_ci.endm
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* Check if running in host at EL2 mode, i.e., (h)VHE. Jump to fail if not. */
3562306a36Sopenharmony_ci.macro __check_hvhe fail, tmp
3662306a36Sopenharmony_ci	mrs	\tmp, hcr_el2
3762306a36Sopenharmony_ci	and	\tmp, \tmp, #HCR_E2H
3862306a36Sopenharmony_ci	cbz	\tmp, \fail
3962306a36Sopenharmony_ci.endm
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*
4262306a36Sopenharmony_ci * Allow Non-secure EL1 and EL0 to access physical timer and counter.
4362306a36Sopenharmony_ci * This is not necessary for VHE, since the host kernel runs in EL2,
4462306a36Sopenharmony_ci * and EL0 accesses are configured in the later stage of boot process.
4562306a36Sopenharmony_ci * Note that when HCR_EL2.E2H == 1, CNTHCTL_EL2 has the same bit layout
4662306a36Sopenharmony_ci * as CNTKCTL_EL1, and CNTKCTL_EL1 accessing instructions are redefined
4762306a36Sopenharmony_ci * to access CNTHCTL_EL2. This allows the kernel designed to run at EL1
4862306a36Sopenharmony_ci * to transparently mess with the EL0 bits via CNTKCTL_EL1 access in
4962306a36Sopenharmony_ci * EL2.
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_ci.macro __init_el2_timers
5262306a36Sopenharmony_ci	mov	x0, #3				// Enable EL1 physical timers
5362306a36Sopenharmony_ci	__check_hvhe .LnVHE_\@, x1
5462306a36Sopenharmony_ci	lsl	x0, x0, #10
5562306a36Sopenharmony_ci.LnVHE_\@:
5662306a36Sopenharmony_ci	msr	cnthctl_el2, x0
5762306a36Sopenharmony_ci	msr	cntvoff_el2, xzr		// Clear virtual offset
5862306a36Sopenharmony_ci.endm
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci.macro __init_el2_debug
6162306a36Sopenharmony_ci	mrs	x1, id_aa64dfr0_el1
6262306a36Sopenharmony_ci	sbfx	x0, x1, #ID_AA64DFR0_EL1_PMUVer_SHIFT, #4
6362306a36Sopenharmony_ci	cmp	x0, #1
6462306a36Sopenharmony_ci	b.lt	.Lskip_pmu_\@			// Skip if no PMU present
6562306a36Sopenharmony_ci	mrs	x0, pmcr_el0			// Disable debug access traps
6662306a36Sopenharmony_ci	ubfx	x0, x0, #11, #5			// to EL2 and allow access to
6762306a36Sopenharmony_ci.Lskip_pmu_\@:
6862306a36Sopenharmony_ci	csel	x2, xzr, x0, lt			// all PMU counters from EL1
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* Statistical profiling */
7162306a36Sopenharmony_ci	ubfx	x0, x1, #ID_AA64DFR0_EL1_PMSVer_SHIFT, #4
7262306a36Sopenharmony_ci	cbz	x0, .Lskip_spe_\@		// Skip if SPE not present
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	mrs_s	x0, SYS_PMBIDR_EL1              // If SPE available at EL2,
7562306a36Sopenharmony_ci	and	x0, x0, #(1 << PMBIDR_EL1_P_SHIFT)
7662306a36Sopenharmony_ci	cbnz	x0, .Lskip_spe_el2_\@		// then permit sampling of physical
7762306a36Sopenharmony_ci	mov	x0, #(1 << PMSCR_EL2_PCT_SHIFT | \
7862306a36Sopenharmony_ci		      1 << PMSCR_EL2_PA_SHIFT)
7962306a36Sopenharmony_ci	msr_s	SYS_PMSCR_EL2, x0		// addresses and physical counter
8062306a36Sopenharmony_ci.Lskip_spe_el2_\@:
8162306a36Sopenharmony_ci	mov	x0, #(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT)
8262306a36Sopenharmony_ci	orr	x2, x2, x0			// If we don't have VHE, then
8362306a36Sopenharmony_ci						// use EL1&0 translation.
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci.Lskip_spe_\@:
8662306a36Sopenharmony_ci	/* Trace buffer */
8762306a36Sopenharmony_ci	ubfx	x0, x1, #ID_AA64DFR0_EL1_TraceBuffer_SHIFT, #4
8862306a36Sopenharmony_ci	cbz	x0, .Lskip_trace_\@		// Skip if TraceBuffer is not present
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	mrs_s	x0, SYS_TRBIDR_EL1
9162306a36Sopenharmony_ci	and	x0, x0, TRBIDR_EL1_P
9262306a36Sopenharmony_ci	cbnz	x0, .Lskip_trace_\@		// If TRBE is available at EL2
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	mov	x0, #(MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT)
9562306a36Sopenharmony_ci	orr	x2, x2, x0			// allow the EL1&0 translation
9662306a36Sopenharmony_ci						// to own it.
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci.Lskip_trace_\@:
9962306a36Sopenharmony_ci	msr	mdcr_el2, x2			// Configure debug traps
10062306a36Sopenharmony_ci.endm
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/* LORegions */
10362306a36Sopenharmony_ci.macro __init_el2_lor
10462306a36Sopenharmony_ci	mrs	x1, id_aa64mmfr1_el1
10562306a36Sopenharmony_ci	ubfx	x0, x1, #ID_AA64MMFR1_EL1_LO_SHIFT, 4
10662306a36Sopenharmony_ci	cbz	x0, .Lskip_lor_\@
10762306a36Sopenharmony_ci	msr_s	SYS_LORC_EL1, xzr
10862306a36Sopenharmony_ci.Lskip_lor_\@:
10962306a36Sopenharmony_ci.endm
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/* Stage-2 translation */
11262306a36Sopenharmony_ci.macro __init_el2_stage2
11362306a36Sopenharmony_ci	msr	vttbr_el2, xzr
11462306a36Sopenharmony_ci.endm
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/* GICv3 system register access */
11762306a36Sopenharmony_ci.macro __init_el2_gicv3
11862306a36Sopenharmony_ci	mrs	x0, id_aa64pfr0_el1
11962306a36Sopenharmony_ci	ubfx	x0, x0, #ID_AA64PFR0_EL1_GIC_SHIFT, #4
12062306a36Sopenharmony_ci	cbz	x0, .Lskip_gicv3_\@
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	mrs_s	x0, SYS_ICC_SRE_EL2
12362306a36Sopenharmony_ci	orr	x0, x0, #ICC_SRE_EL2_SRE	// Set ICC_SRE_EL2.SRE==1
12462306a36Sopenharmony_ci	orr	x0, x0, #ICC_SRE_EL2_ENABLE	// Set ICC_SRE_EL2.Enable==1
12562306a36Sopenharmony_ci	msr_s	SYS_ICC_SRE_EL2, x0
12662306a36Sopenharmony_ci	isb					// Make sure SRE is now set
12762306a36Sopenharmony_ci	mrs_s	x0, SYS_ICC_SRE_EL2		// Read SRE back,
12862306a36Sopenharmony_ci	tbz	x0, #0, .Lskip_gicv3_\@		// and check that it sticks
12962306a36Sopenharmony_ci	msr_s	SYS_ICH_HCR_EL2, xzr		// Reset ICH_HCR_EL2 to defaults
13062306a36Sopenharmony_ci.Lskip_gicv3_\@:
13162306a36Sopenharmony_ci.endm
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci.macro __init_el2_hstr
13462306a36Sopenharmony_ci	msr	hstr_el2, xzr			// Disable CP15 traps to EL2
13562306a36Sopenharmony_ci.endm
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci/* Virtual CPU ID registers */
13862306a36Sopenharmony_ci.macro __init_el2_nvhe_idregs
13962306a36Sopenharmony_ci	mrs	x0, midr_el1
14062306a36Sopenharmony_ci	mrs	x1, mpidr_el1
14162306a36Sopenharmony_ci	msr	vpidr_el2, x0
14262306a36Sopenharmony_ci	msr	vmpidr_el2, x1
14362306a36Sopenharmony_ci.endm
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/* Coprocessor traps */
14662306a36Sopenharmony_ci.macro __init_el2_cptr
14762306a36Sopenharmony_ci	__check_hvhe .LnVHE_\@, x1
14862306a36Sopenharmony_ci	mov	x0, #(CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN)
14962306a36Sopenharmony_ci	msr	cpacr_el1, x0
15062306a36Sopenharmony_ci	b	.Lskip_set_cptr_\@
15162306a36Sopenharmony_ci.LnVHE_\@:
15262306a36Sopenharmony_ci	mov	x0, #0x33ff
15362306a36Sopenharmony_ci	msr	cptr_el2, x0			// Disable copro. traps to EL2
15462306a36Sopenharmony_ci.Lskip_set_cptr_\@:
15562306a36Sopenharmony_ci.endm
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/* Disable any fine grained traps */
15862306a36Sopenharmony_ci.macro __init_el2_fgt
15962306a36Sopenharmony_ci	mrs	x1, id_aa64mmfr0_el1
16062306a36Sopenharmony_ci	ubfx	x1, x1, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
16162306a36Sopenharmony_ci	cbz	x1, .Lskip_fgt_\@
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	mov	x0, xzr
16462306a36Sopenharmony_ci	mrs	x1, id_aa64dfr0_el1
16562306a36Sopenharmony_ci	ubfx	x1, x1, #ID_AA64DFR0_EL1_PMSVer_SHIFT, #4
16662306a36Sopenharmony_ci	cmp	x1, #3
16762306a36Sopenharmony_ci	b.lt	.Lset_debug_fgt_\@
16862306a36Sopenharmony_ci	/* Disable PMSNEVFR_EL1 read and write traps */
16962306a36Sopenharmony_ci	orr	x0, x0, #(1 << 62)
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci.Lset_debug_fgt_\@:
17262306a36Sopenharmony_ci	msr_s	SYS_HDFGRTR_EL2, x0
17362306a36Sopenharmony_ci	msr_s	SYS_HDFGWTR_EL2, x0
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	mov	x0, xzr
17662306a36Sopenharmony_ci	mrs	x1, id_aa64pfr1_el1
17762306a36Sopenharmony_ci	ubfx	x1, x1, #ID_AA64PFR1_EL1_SME_SHIFT, #4
17862306a36Sopenharmony_ci	cbz	x1, .Lset_pie_fgt_\@
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	/* Disable nVHE traps of TPIDR2 and SMPRI */
18162306a36Sopenharmony_ci	orr	x0, x0, #HFGxTR_EL2_nSMPRI_EL1_MASK
18262306a36Sopenharmony_ci	orr	x0, x0, #HFGxTR_EL2_nTPIDR2_EL0_MASK
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci.Lset_pie_fgt_\@:
18562306a36Sopenharmony_ci	mrs_s	x1, SYS_ID_AA64MMFR3_EL1
18662306a36Sopenharmony_ci	ubfx	x1, x1, #ID_AA64MMFR3_EL1_S1PIE_SHIFT, #4
18762306a36Sopenharmony_ci	cbz	x1, .Lset_fgt_\@
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	/* Disable trapping of PIR_EL1 / PIRE0_EL1 */
19062306a36Sopenharmony_ci	orr	x0, x0, #HFGxTR_EL2_nPIR_EL1
19162306a36Sopenharmony_ci	orr	x0, x0, #HFGxTR_EL2_nPIRE0_EL1
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci.Lset_fgt_\@:
19462306a36Sopenharmony_ci	msr_s	SYS_HFGRTR_EL2, x0
19562306a36Sopenharmony_ci	msr_s	SYS_HFGWTR_EL2, x0
19662306a36Sopenharmony_ci	msr_s	SYS_HFGITR_EL2, xzr
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	mrs	x1, id_aa64pfr0_el1		// AMU traps UNDEF without AMU
19962306a36Sopenharmony_ci	ubfx	x1, x1, #ID_AA64PFR0_EL1_AMU_SHIFT, #4
20062306a36Sopenharmony_ci	cbz	x1, .Lskip_fgt_\@
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	msr_s	SYS_HAFGRTR_EL2, xzr
20362306a36Sopenharmony_ci.Lskip_fgt_\@:
20462306a36Sopenharmony_ci.endm
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci.macro __init_el2_nvhe_prepare_eret
20762306a36Sopenharmony_ci	mov	x0, #INIT_PSTATE_EL1
20862306a36Sopenharmony_ci	msr	spsr_el2, x0
20962306a36Sopenharmony_ci.endm
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci/**
21262306a36Sopenharmony_ci * Initialize EL2 registers to sane values. This should be called early on all
21362306a36Sopenharmony_ci * cores that were booted in EL2. Note that everything gets initialised as
21462306a36Sopenharmony_ci * if VHE was not available. The kernel context will be upgraded to VHE
21562306a36Sopenharmony_ci * if possible later on in the boot process
21662306a36Sopenharmony_ci *
21762306a36Sopenharmony_ci * Regs: x0, x1 and x2 are clobbered.
21862306a36Sopenharmony_ci */
21962306a36Sopenharmony_ci.macro init_el2_state
22062306a36Sopenharmony_ci	__init_el2_sctlr
22162306a36Sopenharmony_ci	__init_el2_hcrx
22262306a36Sopenharmony_ci	__init_el2_timers
22362306a36Sopenharmony_ci	__init_el2_debug
22462306a36Sopenharmony_ci	__init_el2_lor
22562306a36Sopenharmony_ci	__init_el2_stage2
22662306a36Sopenharmony_ci	__init_el2_gicv3
22762306a36Sopenharmony_ci	__init_el2_hstr
22862306a36Sopenharmony_ci	__init_el2_nvhe_idregs
22962306a36Sopenharmony_ci	__init_el2_cptr
23062306a36Sopenharmony_ci	__init_el2_fgt
23162306a36Sopenharmony_ci.endm
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci#ifndef __KVM_NVHE_HYPERVISOR__
23462306a36Sopenharmony_ci// This will clobber tmp1 and tmp2, and expect tmp1 to contain
23562306a36Sopenharmony_ci// the id register value as read from the HW
23662306a36Sopenharmony_ci.macro __check_override idreg, fld, width, pass, fail, tmp1, tmp2
23762306a36Sopenharmony_ci	ubfx	\tmp1, \tmp1, #\fld, #\width
23862306a36Sopenharmony_ci	cbz	\tmp1, \fail
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	adr_l	\tmp1, \idreg\()_override
24162306a36Sopenharmony_ci	ldr	\tmp2, [\tmp1, FTR_OVR_VAL_OFFSET]
24262306a36Sopenharmony_ci	ldr	\tmp1, [\tmp1, FTR_OVR_MASK_OFFSET]
24362306a36Sopenharmony_ci	ubfx	\tmp2, \tmp2, #\fld, #\width
24462306a36Sopenharmony_ci	ubfx	\tmp1, \tmp1, #\fld, #\width
24562306a36Sopenharmony_ci	cmp	\tmp1, xzr
24662306a36Sopenharmony_ci	and	\tmp2, \tmp2, \tmp1
24762306a36Sopenharmony_ci	csinv	\tmp2, \tmp2, xzr, ne
24862306a36Sopenharmony_ci	cbnz	\tmp2, \pass
24962306a36Sopenharmony_ci	b	\fail
25062306a36Sopenharmony_ci.endm
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci// This will clobber tmp1 and tmp2
25362306a36Sopenharmony_ci.macro check_override idreg, fld, pass, fail, tmp1, tmp2
25462306a36Sopenharmony_ci	mrs	\tmp1, \idreg\()_el1
25562306a36Sopenharmony_ci	__check_override \idreg \fld 4 \pass \fail \tmp1 \tmp2
25662306a36Sopenharmony_ci.endm
25762306a36Sopenharmony_ci#else
25862306a36Sopenharmony_ci// This will clobber tmp
25962306a36Sopenharmony_ci.macro __check_override idreg, fld, width, pass, fail, tmp, ignore
26062306a36Sopenharmony_ci	ldr_l	\tmp, \idreg\()_el1_sys_val
26162306a36Sopenharmony_ci	ubfx	\tmp, \tmp, #\fld, #\width
26262306a36Sopenharmony_ci	cbnz	\tmp, \pass
26362306a36Sopenharmony_ci	b	\fail
26462306a36Sopenharmony_ci.endm
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci.macro check_override idreg, fld, pass, fail, tmp, ignore
26762306a36Sopenharmony_ci	__check_override \idreg \fld 4 \pass \fail \tmp \ignore
26862306a36Sopenharmony_ci.endm
26962306a36Sopenharmony_ci#endif
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci.macro finalise_el2_state
27262306a36Sopenharmony_ci	check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci.Linit_sve_\@:	/* SVE register access */
27562306a36Sopenharmony_ci	__check_hvhe .Lcptr_nvhe_\@, x1
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	// (h)VHE case
27862306a36Sopenharmony_ci	mrs	x0, cpacr_el1			// Disable SVE traps
27962306a36Sopenharmony_ci	orr	x0, x0, #(CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN)
28062306a36Sopenharmony_ci	msr	cpacr_el1, x0
28162306a36Sopenharmony_ci	b	.Lskip_set_cptr_\@
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci.Lcptr_nvhe_\@: // nVHE case
28462306a36Sopenharmony_ci	mrs	x0, cptr_el2			// Disable SVE traps
28562306a36Sopenharmony_ci	bic	x0, x0, #CPTR_EL2_TZ
28662306a36Sopenharmony_ci	msr	cptr_el2, x0
28762306a36Sopenharmony_ci.Lskip_set_cptr_\@:
28862306a36Sopenharmony_ci	isb
28962306a36Sopenharmony_ci	mov	x1, #ZCR_ELx_LEN_MASK		// SVE: Enable full vector
29062306a36Sopenharmony_ci	msr_s	SYS_ZCR_EL2, x1			// length for EL1.
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci.Lskip_sve_\@:
29362306a36Sopenharmony_ci	check_override id_aa64pfr1, ID_AA64PFR1_EL1_SME_SHIFT, .Linit_sme_\@, .Lskip_sme_\@, x1, x2
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci.Linit_sme_\@:	/* SME register access and priority mapping */
29662306a36Sopenharmony_ci	__check_hvhe .Lcptr_nvhe_sme_\@, x1
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	// (h)VHE case
29962306a36Sopenharmony_ci	mrs	x0, cpacr_el1			// Disable SME traps
30062306a36Sopenharmony_ci	orr	x0, x0, #(CPACR_EL1_SMEN_EL0EN | CPACR_EL1_SMEN_EL1EN)
30162306a36Sopenharmony_ci	msr	cpacr_el1, x0
30262306a36Sopenharmony_ci	b	.Lskip_set_cptr_sme_\@
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci.Lcptr_nvhe_sme_\@: // nVHE case
30562306a36Sopenharmony_ci	mrs	x0, cptr_el2			// Disable SME traps
30662306a36Sopenharmony_ci	bic	x0, x0, #CPTR_EL2_TSM
30762306a36Sopenharmony_ci	msr	cptr_el2, x0
30862306a36Sopenharmony_ci.Lskip_set_cptr_sme_\@:
30962306a36Sopenharmony_ci	isb
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	mrs	x1, sctlr_el2
31262306a36Sopenharmony_ci	orr	x1, x1, #SCTLR_ELx_ENTP2	// Disable TPIDR2 traps
31362306a36Sopenharmony_ci	msr	sctlr_el2, x1
31462306a36Sopenharmony_ci	isb
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	mov	x0, #0				// SMCR controls
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	// Full FP in SM?
31962306a36Sopenharmony_ci	mrs_s	x1, SYS_ID_AA64SMFR0_EL1
32062306a36Sopenharmony_ci	__check_override id_aa64smfr0, ID_AA64SMFR0_EL1_FA64_SHIFT, 1, .Linit_sme_fa64_\@, .Lskip_sme_fa64_\@, x1, x2
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci.Linit_sme_fa64_\@:
32362306a36Sopenharmony_ci	orr	x0, x0, SMCR_ELx_FA64_MASK
32462306a36Sopenharmony_ci.Lskip_sme_fa64_\@:
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	// ZT0 available?
32762306a36Sopenharmony_ci	mrs_s	x1, SYS_ID_AA64SMFR0_EL1
32862306a36Sopenharmony_ci	__check_override id_aa64smfr0, ID_AA64SMFR0_EL1_SMEver_SHIFT, 4, .Linit_sme_zt0_\@, .Lskip_sme_zt0_\@, x1, x2
32962306a36Sopenharmony_ci.Linit_sme_zt0_\@:
33062306a36Sopenharmony_ci	orr	x0, x0, SMCR_ELx_EZT0_MASK
33162306a36Sopenharmony_ci.Lskip_sme_zt0_\@:
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	orr	x0, x0, #SMCR_ELx_LEN_MASK	// Enable full SME vector
33462306a36Sopenharmony_ci	msr_s	SYS_SMCR_EL2, x0		// length for EL1.
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	mrs_s	x1, SYS_SMIDR_EL1		// Priority mapping supported?
33762306a36Sopenharmony_ci	ubfx    x1, x1, #SMIDR_EL1_SMPS_SHIFT, #1
33862306a36Sopenharmony_ci	cbz     x1, .Lskip_sme_\@
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	msr_s	SYS_SMPRIMAP_EL2, xzr		// Make all priorities equal
34162306a36Sopenharmony_ci.Lskip_sme_\@:
34262306a36Sopenharmony_ci.endm
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci#endif /* __ARM_KVM_INIT_H__ */
345