2019-06-03 13:44:50 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2012-03-05 19:49:28 +08:00
|
|
|
/*
|
|
|
|
* Based on arch/arm/mm/proc.S
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001 Deep Blue Solutions Ltd.
|
|
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
|
|
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <asm/assembler.h>
|
|
|
|
#include <asm/asm-offsets.h>
|
2020-03-13 17:05:01 +08:00
|
|
|
#include <asm/asm_pointer_auth.h>
|
2012-03-05 19:49:28 +08:00
|
|
|
#include <asm/hwcap.h>
|
|
|
|
#include <asm/pgtable.h>
|
2016-04-28 00:47:07 +08:00
|
|
|
#include <asm/pgtable-hwdef.h>
|
2016-02-25 09:44:57 +08:00
|
|
|
#include <asm/cpufeature.h>
|
|
|
|
#include <asm/alternative.h>
|
2020-03-13 17:04:55 +08:00
|
|
|
#include <asm/smp.h>
|
2012-03-05 19:49:28 +08:00
|
|
|
|
2014-04-03 00:55:40 +08:00
|
|
|
#ifdef CONFIG_ARM64_64K_PAGES
|
|
|
|
#define TCR_TG_FLAGS TCR_TG0_64K | TCR_TG1_64K
|
2015-10-19 21:19:37 +08:00
|
|
|
#elif defined(CONFIG_ARM64_16K_PAGES)
|
|
|
|
#define TCR_TG_FLAGS TCR_TG0_16K | TCR_TG1_16K
|
|
|
|
#else /* CONFIG_ARM64_4K_PAGES */
|
2014-04-03 00:55:40 +08:00
|
|
|
#define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K
|
|
|
|
#endif
|
|
|
|
|
2018-02-27 22:15:49 +08:00
|
|
|
#ifdef CONFIG_RANDOMIZE_BASE
|
|
|
|
#define TCR_KASLR_FLAGS TCR_NFD1
|
|
|
|
#else
|
|
|
|
#define TCR_KASLR_FLAGS 0
|
|
|
|
#endif
|
|
|
|
|
2014-04-03 00:55:40 +08:00
|
|
|
#define TCR_SMP_FLAGS TCR_SHARED
|
2012-03-05 19:49:28 +08:00
|
|
|
|
2014-04-03 00:55:40 +08:00
|
|
|
/* PTWs cacheable, inner/outer WBWA */
|
|
|
|
#define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA
|
|
|
|
|
2018-12-28 16:30:31 +08:00
|
|
|
#ifdef CONFIG_KASAN_SW_TAGS
|
|
|
|
#define TCR_KASAN_FLAGS TCR_TBI1
|
|
|
|
#else
|
|
|
|
#define TCR_KASAN_FLAGS 0
|
|
|
|
#endif
|
|
|
|
|
2019-12-12 02:40:09 +08:00
|
|
|
/* Default MAIR_EL1 */
|
|
|
|
#define MAIR_EL1_SET \
|
|
|
|
(MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \
|
|
|
|
MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \
|
|
|
|
MAIR_ATTRIDX(MAIR_ATTR_DEVICE_GRE, MT_DEVICE_GRE) | \
|
|
|
|
MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \
|
|
|
|
MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \
|
|
|
|
MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT))
|
2012-03-05 19:49:28 +08:00
|
|
|
|
2015-01-27 02:33:44 +08:00
|
|
|
#ifdef CONFIG_CPU_PM
|
2013-07-17 17:14:45 +08:00
|
|
|
/**
|
|
|
|
* cpu_do_suspend - save CPU registers context
|
|
|
|
*
|
|
|
|
* x0: virtual address of context pointer
|
|
|
|
*/
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_START(cpu_do_suspend)
|
2013-07-17 17:14:45 +08:00
|
|
|
mrs x2, tpidr_el0
|
|
|
|
mrs x3, tpidrro_el0
|
|
|
|
mrs x4, contextidr_el1
|
2019-04-09 01:17:19 +08:00
|
|
|
mrs x5, osdlr_el1
|
|
|
|
mrs x6, cpacr_el1
|
|
|
|
mrs x7, tcr_el1
|
|
|
|
mrs x8, vbar_el1
|
|
|
|
mrs x9, mdscr_el1
|
|
|
|
mrs x10, oslsr_el1
|
|
|
|
mrs x11, sctlr_el1
|
2018-01-08 23:38:06 +08:00
|
|
|
alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
|
2019-04-09 01:17:19 +08:00
|
|
|
mrs x12, tpidr_el1
|
2018-01-08 23:38:06 +08:00
|
|
|
alternative_else
|
2019-04-09 01:17:19 +08:00
|
|
|
mrs x12, tpidr_el2
|
2018-01-08 23:38:06 +08:00
|
|
|
alternative_endif
|
2019-04-09 01:17:19 +08:00
|
|
|
mrs x13, sp_el0
|
2013-07-17 17:14:45 +08:00
|
|
|
stp x2, x3, [x0]
|
2019-04-09 01:17:19 +08:00
|
|
|
stp x4, x5, [x0, #16]
|
|
|
|
stp x6, x7, [x0, #32]
|
|
|
|
stp x8, x9, [x0, #48]
|
|
|
|
stp x10, x11, [x0, #64]
|
|
|
|
stp x12, x13, [x0, #80]
|
2013-07-17 17:14:45 +08:00
|
|
|
ret
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_END(cpu_do_suspend)
|
2013-07-17 17:14:45 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* cpu_do_resume - restore CPU register context
|
|
|
|
*
|
2016-04-28 00:47:07 +08:00
|
|
|
* x0: Address of context pointer
|
2013-07-17 17:14:45 +08:00
|
|
|
*/
|
2018-01-29 20:00:00 +08:00
|
|
|
.pushsection ".idmap.text", "awx"
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_START(cpu_do_resume)
|
2013-07-17 17:14:45 +08:00
|
|
|
ldp x2, x3, [x0]
|
|
|
|
ldp x4, x5, [x0, #16]
|
2016-04-28 00:47:07 +08:00
|
|
|
ldp x6, x8, [x0, #32]
|
|
|
|
ldp x9, x10, [x0, #48]
|
|
|
|
ldp x11, x12, [x0, #64]
|
2016-11-04 04:23:09 +08:00
|
|
|
ldp x13, x14, [x0, #80]
|
2013-07-17 17:14:45 +08:00
|
|
|
msr tpidr_el0, x2
|
|
|
|
msr tpidrro_el0, x3
|
|
|
|
msr contextidr_el1, x4
|
|
|
|
msr cpacr_el1, x6
|
2016-04-28 00:47:07 +08:00
|
|
|
|
|
|
|
/* Don't change t0sz here, mask those bits when restoring */
|
2019-04-09 01:17:19 +08:00
|
|
|
mrs x7, tcr_el1
|
|
|
|
bfi x8, x7, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
|
2016-04-28 00:47:07 +08:00
|
|
|
|
2013-07-17 17:14:45 +08:00
|
|
|
msr tcr_el1, x8
|
|
|
|
msr vbar_el1, x9
|
2016-08-26 23:03:42 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* __cpu_setup() cleared MDSCR_EL1.MDE and friends, before unmasking
|
|
|
|
* debug exceptions. By restoring MDSCR_EL1 here, we may take a debug
|
2017-11-02 20:12:34 +08:00
|
|
|
* exception. Mask them until local_daif_restore() in cpu_suspend()
|
2016-08-26 23:03:42 +08:00
|
|
|
* resets them.
|
|
|
|
*/
|
2017-11-02 20:12:34 +08:00
|
|
|
disable_daif
|
2013-07-17 17:14:45 +08:00
|
|
|
msr mdscr_el1, x10
|
2016-08-26 23:03:42 +08:00
|
|
|
|
2016-04-28 00:47:07 +08:00
|
|
|
msr sctlr_el1, x12
|
2018-01-08 23:38:06 +08:00
|
|
|
alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
|
2016-11-04 04:23:09 +08:00
|
|
|
msr tpidr_el1, x13
|
2018-01-08 23:38:06 +08:00
|
|
|
alternative_else
|
|
|
|
msr tpidr_el2, x13
|
|
|
|
alternative_endif
|
2016-11-04 04:23:09 +08:00
|
|
|
msr sp_el0, x14
|
2013-07-17 17:14:45 +08:00
|
|
|
/*
|
|
|
|
* Restore oslsr_el1 by writing oslar_el1
|
|
|
|
*/
|
2019-04-09 01:17:19 +08:00
|
|
|
msr osdlr_el1, x5
|
2013-07-17 17:14:45 +08:00
|
|
|
ubfx x11, x11, #1, #1
|
|
|
|
msr oslar_el1, x11
|
2016-01-13 22:50:03 +08:00
|
|
|
reset_pmuserenr_el0 x0 // Disable PMU access from EL0
|
2020-03-05 17:06:22 +08:00
|
|
|
reset_amuserenr_el0 x0 // Disable AMU access from EL0
|
2018-01-16 03:38:59 +08:00
|
|
|
|
|
|
|
alternative_if ARM64_HAS_RAS_EXTN
|
|
|
|
msr_s SYS_DISR_EL1, xzr
|
|
|
|
alternative_else_nop_endif
|
|
|
|
|
2020-03-13 17:05:01 +08:00
|
|
|
ptrauth_keys_install_kernel x14, 0, x1, x2, x3
|
2013-07-17 17:14:45 +08:00
|
|
|
isb
|
|
|
|
ret
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_END(cpu_do_resume)
|
2016-08-25 01:27:29 +08:00
|
|
|
.popsection
|
2013-07-17 17:14:45 +08:00
|
|
|
#endif
|
|
|
|
|
2018-01-29 20:00:00 +08:00
|
|
|
.pushsection ".idmap.text", "awx"
|
2018-02-07 06:22:50 +08:00
|
|
|
|
|
|
|
.macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2
|
|
|
|
adrp \tmp1, empty_zero_page
|
2018-01-29 19:59:57 +08:00
|
|
|
phys_to_ttbr \tmp2, \tmp1
|
2019-08-07 23:55:19 +08:00
|
|
|
offset_ttbr1 \tmp2, \tmp1
|
2018-02-07 06:22:50 +08:00
|
|
|
msr ttbr1_el1, \tmp2
|
|
|
|
isb
|
|
|
|
tlbi vmalle1
|
|
|
|
dsb nsh
|
|
|
|
isb
|
|
|
|
.endm
|
|
|
|
|
arm64: mm: add code to safely replace TTBR1_EL1
If page tables are modified without suitable TLB maintenance, the ARM
architecture permits multiple TLB entries to be allocated for the same
VA. When this occurs, it is permitted that TLB conflict aborts are
raised in response to synchronous data/instruction accesses, and/or and
amalgamation of the TLB entries may be used as a result of a TLB lookup.
The presence of conflicting TLB entries may result in a variety of
behaviours detrimental to the system (e.g. erroneous physical addresses
may be used by I-cache fetches and/or page table walks). Some of these
cases may result in unexpected changes of hardware state, and/or result
in the (asynchronous) delivery of SError.
To avoid these issues, we must avoid situations where conflicting
entries may be allocated into TLBs. For user and module mappings we can
follow a strict break-before-make approach, but this cannot work for
modifications to the swapper page tables that cover the kernel text and
data.
Instead, this patch adds code which is intended to be executed from the
idmap, which can safely unmap the swapper page tables as it only
requires the idmap to be active. This enables us to uninstall the active
TTBR1_EL1 entry, invalidate TLBs, then install a new TTBR1_EL1 entry
without potentially unmapping code or data required for the sequence.
This avoids the risk of conflict, but requires that updates are staged
in a copy of the swapper page tables prior to being installed.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Cc: Laura Abbott <labbott@fedoraproject.org>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2016-01-25 19:45:01 +08:00
|
|
|
/*
|
2018-07-31 21:08:56 +08:00
|
|
|
* void idmap_cpu_replace_ttbr1(phys_addr_t ttbr1)
|
arm64: mm: add code to safely replace TTBR1_EL1
If page tables are modified without suitable TLB maintenance, the ARM
architecture permits multiple TLB entries to be allocated for the same
VA. When this occurs, it is permitted that TLB conflict aborts are
raised in response to synchronous data/instruction accesses, and/or and
amalgamation of the TLB entries may be used as a result of a TLB lookup.
The presence of conflicting TLB entries may result in a variety of
behaviours detrimental to the system (e.g. erroneous physical addresses
may be used by I-cache fetches and/or page table walks). Some of these
cases may result in unexpected changes of hardware state, and/or result
in the (asynchronous) delivery of SError.
To avoid these issues, we must avoid situations where conflicting
entries may be allocated into TLBs. For user and module mappings we can
follow a strict break-before-make approach, but this cannot work for
modifications to the swapper page tables that cover the kernel text and
data.
Instead, this patch adds code which is intended to be executed from the
idmap, which can safely unmap the swapper page tables as it only
requires the idmap to be active. This enables us to uninstall the active
TTBR1_EL1 entry, invalidate TLBs, then install a new TTBR1_EL1 entry
without potentially unmapping code or data required for the sequence.
This avoids the risk of conflict, but requires that updates are staged
in a copy of the swapper page tables prior to being installed.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Cc: Laura Abbott <labbott@fedoraproject.org>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2016-01-25 19:45:01 +08:00
|
|
|
*
|
|
|
|
* This is the low-level counterpart to cpu_replace_ttbr1, and should not be
|
|
|
|
* called by anything else. It can only be executed from a TTBR0 mapping.
|
|
|
|
*/
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_START(idmap_cpu_replace_ttbr1)
|
2017-11-02 20:12:34 +08:00
|
|
|
save_and_disable_daif flags=x2
|
arm64: mm: add code to safely replace TTBR1_EL1
If page tables are modified without suitable TLB maintenance, the ARM
architecture permits multiple TLB entries to be allocated for the same
VA. When this occurs, it is permitted that TLB conflict aborts are
raised in response to synchronous data/instruction accesses, and/or and
amalgamation of the TLB entries may be used as a result of a TLB lookup.
The presence of conflicting TLB entries may result in a variety of
behaviours detrimental to the system (e.g. erroneous physical addresses
may be used by I-cache fetches and/or page table walks). Some of these
cases may result in unexpected changes of hardware state, and/or result
in the (asynchronous) delivery of SError.
To avoid these issues, we must avoid situations where conflicting
entries may be allocated into TLBs. For user and module mappings we can
follow a strict break-before-make approach, but this cannot work for
modifications to the swapper page tables that cover the kernel text and
data.
Instead, this patch adds code which is intended to be executed from the
idmap, which can safely unmap the swapper page tables as it only
requires the idmap to be active. This enables us to uninstall the active
TTBR1_EL1 entry, invalidate TLBs, then install a new TTBR1_EL1 entry
without potentially unmapping code or data required for the sequence.
This avoids the risk of conflict, but requires that updates are staged
in a copy of the swapper page tables prior to being installed.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Cc: Laura Abbott <labbott@fedoraproject.org>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2016-01-25 19:45:01 +08:00
|
|
|
|
2018-02-07 06:22:50 +08:00
|
|
|
__idmap_cpu_set_reserved_ttbr1 x1, x3
|
arm64: mm: add code to safely replace TTBR1_EL1
If page tables are modified without suitable TLB maintenance, the ARM
architecture permits multiple TLB entries to be allocated for the same
VA. When this occurs, it is permitted that TLB conflict aborts are
raised in response to synchronous data/instruction accesses, and/or and
amalgamation of the TLB entries may be used as a result of a TLB lookup.
The presence of conflicting TLB entries may result in a variety of
behaviours detrimental to the system (e.g. erroneous physical addresses
may be used by I-cache fetches and/or page table walks). Some of these
cases may result in unexpected changes of hardware state, and/or result
in the (asynchronous) delivery of SError.
To avoid these issues, we must avoid situations where conflicting
entries may be allocated into TLBs. For user and module mappings we can
follow a strict break-before-make approach, but this cannot work for
modifications to the swapper page tables that cover the kernel text and
data.
Instead, this patch adds code which is intended to be executed from the
idmap, which can safely unmap the swapper page tables as it only
requires the idmap to be active. This enables us to uninstall the active
TTBR1_EL1 entry, invalidate TLBs, then install a new TTBR1_EL1 entry
without potentially unmapping code or data required for the sequence.
This avoids the risk of conflict, but requires that updates are staged
in a copy of the swapper page tables prior to being installed.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Cc: Laura Abbott <labbott@fedoraproject.org>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2016-01-25 19:45:01 +08:00
|
|
|
|
2019-08-07 23:55:19 +08:00
|
|
|
offset_ttbr1 x0, x3
|
2018-07-31 21:08:56 +08:00
|
|
|
msr ttbr1_el1, x0
|
arm64: mm: add code to safely replace TTBR1_EL1
If page tables are modified without suitable TLB maintenance, the ARM
architecture permits multiple TLB entries to be allocated for the same
VA. When this occurs, it is permitted that TLB conflict aborts are
raised in response to synchronous data/instruction accesses, and/or and
amalgamation of the TLB entries may be used as a result of a TLB lookup.
The presence of conflicting TLB entries may result in a variety of
behaviours detrimental to the system (e.g. erroneous physical addresses
may be used by I-cache fetches and/or page table walks). Some of these
cases may result in unexpected changes of hardware state, and/or result
in the (asynchronous) delivery of SError.
To avoid these issues, we must avoid situations where conflicting
entries may be allocated into TLBs. For user and module mappings we can
follow a strict break-before-make approach, but this cannot work for
modifications to the swapper page tables that cover the kernel text and
data.
Instead, this patch adds code which is intended to be executed from the
idmap, which can safely unmap the swapper page tables as it only
requires the idmap to be active. This enables us to uninstall the active
TTBR1_EL1 entry, invalidate TLBs, then install a new TTBR1_EL1 entry
without potentially unmapping code or data required for the sequence.
This avoids the risk of conflict, but requires that updates are staged
in a copy of the swapper page tables prior to being installed.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Cc: Laura Abbott <labbott@fedoraproject.org>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2016-01-25 19:45:01 +08:00
|
|
|
isb
|
|
|
|
|
2017-11-02 20:12:34 +08:00
|
|
|
restore_daif x2
|
arm64: mm: add code to safely replace TTBR1_EL1
If page tables are modified without suitable TLB maintenance, the ARM
architecture permits multiple TLB entries to be allocated for the same
VA. When this occurs, it is permitted that TLB conflict aborts are
raised in response to synchronous data/instruction accesses, and/or and
amalgamation of the TLB entries may be used as a result of a TLB lookup.
The presence of conflicting TLB entries may result in a variety of
behaviours detrimental to the system (e.g. erroneous physical addresses
may be used by I-cache fetches and/or page table walks). Some of these
cases may result in unexpected changes of hardware state, and/or result
in the (asynchronous) delivery of SError.
To avoid these issues, we must avoid situations where conflicting
entries may be allocated into TLBs. For user and module mappings we can
follow a strict break-before-make approach, but this cannot work for
modifications to the swapper page tables that cover the kernel text and
data.
Instead, this patch adds code which is intended to be executed from the
idmap, which can safely unmap the swapper page tables as it only
requires the idmap to be active. This enables us to uninstall the active
TTBR1_EL1 entry, invalidate TLBs, then install a new TTBR1_EL1 entry
without potentially unmapping code or data required for the sequence.
This avoids the risk of conflict, but requires that updates are staged
in a copy of the swapper page tables prior to being installed.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Cc: Laura Abbott <labbott@fedoraproject.org>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2016-01-25 19:45:01 +08:00
|
|
|
|
|
|
|
ret
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_END(idmap_cpu_replace_ttbr1)
|
arm64: mm: add code to safely replace TTBR1_EL1
If page tables are modified without suitable TLB maintenance, the ARM
architecture permits multiple TLB entries to be allocated for the same
VA. When this occurs, it is permitted that TLB conflict aborts are
raised in response to synchronous data/instruction accesses, and/or and
amalgamation of the TLB entries may be used as a result of a TLB lookup.
The presence of conflicting TLB entries may result in a variety of
behaviours detrimental to the system (e.g. erroneous physical addresses
may be used by I-cache fetches and/or page table walks). Some of these
cases may result in unexpected changes of hardware state, and/or result
in the (asynchronous) delivery of SError.
To avoid these issues, we must avoid situations where conflicting
entries may be allocated into TLBs. For user and module mappings we can
follow a strict break-before-make approach, but this cannot work for
modifications to the swapper page tables that cover the kernel text and
data.
Instead, this patch adds code which is intended to be executed from the
idmap, which can safely unmap the swapper page tables as it only
requires the idmap to be active. This enables us to uninstall the active
TTBR1_EL1 entry, invalidate TLBs, then install a new TTBR1_EL1 entry
without potentially unmapping code or data required for the sequence.
This avoids the risk of conflict, but requires that updates are staged
in a copy of the swapper page tables prior to being installed.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Jeremy Linton <jeremy.linton@arm.com>
Cc: Laura Abbott <labbott@fedoraproject.org>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2016-01-25 19:45:01 +08:00
|
|
|
.popsection
|
|
|
|
|
2018-02-07 06:22:50 +08:00
|
|
|
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
2018-01-29 20:00:00 +08:00
|
|
|
.pushsection ".idmap.text", "awx"
|
2018-02-07 06:22:50 +08:00
|
|
|
|
|
|
|
.macro __idmap_kpti_get_pgtable_ent, type
|
|
|
|
dc cvac, cur_\()\type\()p // Ensure any existing dirty
|
|
|
|
dmb sy // lines are written back before
|
|
|
|
ldr \type, [cur_\()\type\()p] // loading the entry
|
2018-02-13 21:14:09 +08:00
|
|
|
tbz \type, #0, skip_\()\type // Skip invalid and
|
|
|
|
tbnz \type, #11, skip_\()\type // non-global entries
|
2018-02-07 06:22:50 +08:00
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro __idmap_kpti_put_pgtable_ent_ng, type
|
|
|
|
orr \type, \type, #PTE_NG // Same bit for blocks and pages
|
2018-06-22 23:23:45 +08:00
|
|
|
str \type, [cur_\()\type\()p] // Update the entry and ensure
|
|
|
|
dmb sy // that it is visible to all
|
|
|
|
dc civac, cur_\()\type\()p // CPUs.
|
2018-02-07 06:22:50 +08:00
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* void __kpti_install_ng_mappings(int cpu, int num_cpus, phys_addr_t swapper)
|
|
|
|
*
|
|
|
|
* Called exactly once from stop_machine context by each CPU found during boot.
|
|
|
|
*/
|
|
|
|
__idmap_kpti_flag:
|
|
|
|
.long 1
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_START(idmap_kpti_install_ng_mappings)
|
2018-02-07 06:22:50 +08:00
|
|
|
cpu .req w0
|
|
|
|
num_cpus .req w1
|
|
|
|
swapper_pa .req x2
|
|
|
|
swapper_ttb .req x3
|
|
|
|
flag_ptr .req x4
|
|
|
|
cur_pgdp .req x5
|
|
|
|
end_pgdp .req x6
|
|
|
|
pgd .req x7
|
|
|
|
cur_pudp .req x8
|
|
|
|
end_pudp .req x9
|
|
|
|
pud .req x10
|
|
|
|
cur_pmdp .req x11
|
|
|
|
end_pmdp .req x12
|
|
|
|
pmd .req x13
|
|
|
|
cur_ptep .req x14
|
|
|
|
end_ptep .req x15
|
|
|
|
pte .req x16
|
|
|
|
|
|
|
|
mrs swapper_ttb, ttbr1_el1
|
arm64: mm: Offset TTBR1 to allow 52-bit PTRS_PER_PGD
Enabling 52-bit VAs on arm64 requires that the PGD table expands from 64
entries (for the 48-bit case) to 1024 entries. This quantity,
PTRS_PER_PGD is used as follows to compute which PGD entry corresponds
to a given virtual address, addr:
pgd_index(addr) -> (addr >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)
Userspace addresses are prefixed by 0's, so for a 48-bit userspace
address, uva, the following is true:
(uva >> PGDIR_SHIFT) & (1024 - 1) == (uva >> PGDIR_SHIFT) & (64 - 1)
In other words, a 48-bit userspace address will have the same pgd_index
when using PTRS_PER_PGD = 64 and 1024.
Kernel addresses are prefixed by 1's so, given a 48-bit kernel address,
kva, we have the following inequality:
(kva >> PGDIR_SHIFT) & (1024 - 1) != (kva >> PGDIR_SHIFT) & (64 - 1)
In other words a 48-bit kernel virtual address will have a different
pgd_index when using PTRS_PER_PGD = 64 and 1024.
If, however, we note that:
kva = 0xFFFF << 48 + lower (where lower[63:48] == 0b)
and, PGDIR_SHIFT = 42 (as we are dealing with 64KB PAGE_SIZE)
We can consider:
(kva >> PGDIR_SHIFT) & (1024 - 1) - (kva >> PGDIR_SHIFT) & (64 - 1)
= (0xFFFF << 6) & 0x3FF - (0xFFFF << 6) & 0x3F // "lower" cancels out
= 0x3C0
In other words, one can switch PTRS_PER_PGD to the 52-bit value globally
provided that they increment ttbr1_el1 by 0x3C0 * 8 = 0x1E00 bytes when
running with 48-bit kernel VAs (TCR_EL1.T1SZ = 16).
For kernel configuration where 52-bit userspace VAs are possible, this
patch offsets ttbr1_el1 and sets PTRS_PER_PGD corresponding to the
52-bit value.
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Steve Capper <steve.capper@arm.com>
[will: added comment to TTBR1_BADDR_4852_OFFSET calculation]
Signed-off-by: Will Deacon <will.deacon@arm.com>
2018-12-07 06:50:39 +08:00
|
|
|
restore_ttbr1 swapper_ttb
|
2018-02-07 06:22:50 +08:00
|
|
|
adr flag_ptr, __idmap_kpti_flag
|
|
|
|
|
|
|
|
cbnz cpu, __idmap_kpti_secondary
|
|
|
|
|
|
|
|
/* We're the boot CPU. Wait for the others to catch up */
|
|
|
|
sevl
|
|
|
|
1: wfe
|
2019-12-07 06:13:37 +08:00
|
|
|
ldaxr w17, [flag_ptr]
|
|
|
|
eor w17, w17, num_cpus
|
|
|
|
cbnz w17, 1b
|
2018-02-07 06:22:50 +08:00
|
|
|
|
|
|
|
/* We need to walk swapper, so turn off the MMU. */
|
|
|
|
pre_disable_mmu_workaround
|
2019-12-07 06:13:37 +08:00
|
|
|
mrs x17, sctlr_el1
|
|
|
|
bic x17, x17, #SCTLR_ELx_M
|
|
|
|
msr sctlr_el1, x17
|
2018-02-07 06:22:50 +08:00
|
|
|
isb
|
|
|
|
|
|
|
|
/* Everybody is enjoying the idmap, so we can rewrite swapper. */
|
|
|
|
/* PGD */
|
|
|
|
mov cur_pgdp, swapper_pa
|
|
|
|
add end_pgdp, cur_pgdp, #(PTRS_PER_PGD * 8)
|
|
|
|
do_pgd: __idmap_kpti_get_pgtable_ent pgd
|
|
|
|
tbnz pgd, #1, walk_puds
|
|
|
|
next_pgd:
|
2018-02-13 21:14:09 +08:00
|
|
|
__idmap_kpti_put_pgtable_ent_ng pgd
|
|
|
|
skip_pgd:
|
2018-02-07 06:22:50 +08:00
|
|
|
add cur_pgdp, cur_pgdp, #8
|
|
|
|
cmp cur_pgdp, end_pgdp
|
|
|
|
b.ne do_pgd
|
|
|
|
|
|
|
|
/* Publish the updated tables and nuke all the TLBs */
|
|
|
|
dsb sy
|
|
|
|
tlbi vmalle1is
|
|
|
|
dsb ish
|
|
|
|
isb
|
|
|
|
|
|
|
|
/* We're done: fire up the MMU again */
|
2019-12-07 06:13:37 +08:00
|
|
|
mrs x17, sctlr_el1
|
|
|
|
orr x17, x17, #SCTLR_ELx_M
|
|
|
|
msr sctlr_el1, x17
|
2018-02-07 06:22:50 +08:00
|
|
|
isb
|
|
|
|
|
2019-08-28 01:12:57 +08:00
|
|
|
/*
|
|
|
|
* Invalidate the local I-cache so that any instructions fetched
|
|
|
|
* speculatively from the PoC are discarded, since they may have
|
|
|
|
* been dynamically patched at the PoU.
|
|
|
|
*/
|
|
|
|
ic iallu
|
|
|
|
dsb nsh
|
|
|
|
isb
|
|
|
|
|
2018-02-07 06:22:50 +08:00
|
|
|
/* Set the flag to zero to indicate that we're all done */
|
|
|
|
str wzr, [flag_ptr]
|
|
|
|
ret
|
|
|
|
|
|
|
|
/* PUD */
|
|
|
|
walk_puds:
|
|
|
|
.if CONFIG_PGTABLE_LEVELS > 3
|
|
|
|
pte_to_phys cur_pudp, pgd
|
|
|
|
add end_pudp, cur_pudp, #(PTRS_PER_PUD * 8)
|
|
|
|
do_pud: __idmap_kpti_get_pgtable_ent pud
|
|
|
|
tbnz pud, #1, walk_pmds
|
|
|
|
next_pud:
|
2018-02-13 21:14:09 +08:00
|
|
|
__idmap_kpti_put_pgtable_ent_ng pud
|
|
|
|
skip_pud:
|
2018-02-07 06:22:50 +08:00
|
|
|
add cur_pudp, cur_pudp, 8
|
|
|
|
cmp cur_pudp, end_pudp
|
|
|
|
b.ne do_pud
|
|
|
|
b next_pgd
|
|
|
|
.else /* CONFIG_PGTABLE_LEVELS <= 3 */
|
|
|
|
mov pud, pgd
|
|
|
|
b walk_pmds
|
|
|
|
next_pud:
|
|
|
|
b next_pgd
|
|
|
|
.endif
|
|
|
|
|
|
|
|
/* PMD */
|
|
|
|
walk_pmds:
|
|
|
|
.if CONFIG_PGTABLE_LEVELS > 2
|
|
|
|
pte_to_phys cur_pmdp, pud
|
|
|
|
add end_pmdp, cur_pmdp, #(PTRS_PER_PMD * 8)
|
|
|
|
do_pmd: __idmap_kpti_get_pgtable_ent pmd
|
|
|
|
tbnz pmd, #1, walk_ptes
|
|
|
|
next_pmd:
|
2018-02-13 21:14:09 +08:00
|
|
|
__idmap_kpti_put_pgtable_ent_ng pmd
|
|
|
|
skip_pmd:
|
2018-02-07 06:22:50 +08:00
|
|
|
add cur_pmdp, cur_pmdp, #8
|
|
|
|
cmp cur_pmdp, end_pmdp
|
|
|
|
b.ne do_pmd
|
|
|
|
b next_pud
|
|
|
|
.else /* CONFIG_PGTABLE_LEVELS <= 2 */
|
|
|
|
mov pmd, pud
|
|
|
|
b walk_ptes
|
|
|
|
next_pmd:
|
|
|
|
b next_pud
|
|
|
|
.endif
|
|
|
|
|
|
|
|
/* PTE */
|
|
|
|
walk_ptes:
|
|
|
|
pte_to_phys cur_ptep, pmd
|
|
|
|
add end_ptep, cur_ptep, #(PTRS_PER_PTE * 8)
|
|
|
|
do_pte: __idmap_kpti_get_pgtable_ent pte
|
|
|
|
__idmap_kpti_put_pgtable_ent_ng pte
|
2018-02-13 21:14:09 +08:00
|
|
|
skip_pte:
|
2018-02-07 06:22:50 +08:00
|
|
|
add cur_ptep, cur_ptep, #8
|
|
|
|
cmp cur_ptep, end_ptep
|
|
|
|
b.ne do_pte
|
|
|
|
b next_pmd
|
|
|
|
|
2019-12-07 06:13:37 +08:00
|
|
|
.unreq cpu
|
|
|
|
.unreq num_cpus
|
|
|
|
.unreq swapper_pa
|
|
|
|
.unreq cur_pgdp
|
|
|
|
.unreq end_pgdp
|
|
|
|
.unreq pgd
|
|
|
|
.unreq cur_pudp
|
|
|
|
.unreq end_pudp
|
|
|
|
.unreq pud
|
|
|
|
.unreq cur_pmdp
|
|
|
|
.unreq end_pmdp
|
|
|
|
.unreq pmd
|
|
|
|
.unreq cur_ptep
|
|
|
|
.unreq end_ptep
|
|
|
|
.unreq pte
|
|
|
|
|
2018-02-07 06:22:50 +08:00
|
|
|
/* Secondary CPUs end up here */
|
|
|
|
__idmap_kpti_secondary:
|
|
|
|
/* Uninstall swapper before surgery begins */
|
2019-12-07 06:13:37 +08:00
|
|
|
__idmap_cpu_set_reserved_ttbr1 x16, x17
|
2018-02-07 06:22:50 +08:00
|
|
|
|
|
|
|
/* Increment the flag to let the boot CPU we're ready */
|
2019-12-07 06:13:37 +08:00
|
|
|
1: ldxr w16, [flag_ptr]
|
|
|
|
add w16, w16, #1
|
|
|
|
stxr w17, w16, [flag_ptr]
|
2018-02-07 06:22:50 +08:00
|
|
|
cbnz w17, 1b
|
|
|
|
|
|
|
|
/* Wait for the boot CPU to finish messing around with swapper */
|
|
|
|
sevl
|
|
|
|
1: wfe
|
2019-12-07 06:13:37 +08:00
|
|
|
ldxr w16, [flag_ptr]
|
|
|
|
cbnz w16, 1b
|
2018-02-07 06:22:50 +08:00
|
|
|
|
|
|
|
/* All done, act like nothing happened */
|
2019-12-07 06:13:37 +08:00
|
|
|
offset_ttbr1 swapper_ttb, x16
|
2018-02-07 06:22:50 +08:00
|
|
|
msr ttbr1_el1, swapper_ttb
|
|
|
|
isb
|
|
|
|
ret
|
|
|
|
|
|
|
|
.unreq swapper_ttb
|
|
|
|
.unreq flag_ptr
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_END(idmap_kpti_install_ng_mappings)
|
2018-02-07 06:22:50 +08:00
|
|
|
.popsection
|
|
|
|
#endif
|
|
|
|
|
2012-03-05 19:49:28 +08:00
|
|
|
/*
|
|
|
|
* __cpu_setup
|
|
|
|
*
|
2020-03-13 17:04:52 +08:00
|
|
|
* Initialise the processor for turning the MMU on.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* x0 with a flag ARM64_CPU_BOOT_PRIMARY/ARM64_CPU_BOOT_SECONDARY/ARM64_CPU_RUNTIME.
|
|
|
|
* Output:
|
|
|
|
* Return in x0 the value of the SCTLR_EL1 register.
|
2012-03-05 19:49:28 +08:00
|
|
|
*/
|
2018-01-29 20:00:00 +08:00
|
|
|
.pushsection ".idmap.text", "awx"
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_START(__cpu_setup)
|
2015-10-07 01:46:22 +08:00
|
|
|
tlbi vmalle1 // Invalidate local TLB
|
|
|
|
dsb nsh
|
2012-03-05 19:49:28 +08:00
|
|
|
|
2020-03-13 17:04:52 +08:00
|
|
|
mov x1, #3 << 20
|
|
|
|
msr cpacr_el1, x1 // Enable FP/ASIMD
|
|
|
|
mov x1, #1 << 12 // Reset mdscr_el1 and disable
|
|
|
|
msr mdscr_el1, x1 // access to the DCC from EL0
|
arm64: debug: unmask PSTATE.D earlier
Clearing PSTATE.D is one of the requirements for generating a debug
exception. The arm64 booting protocol requires that PSTATE.D is set,
since many of the debug registers (for example, the hw_breakpoint
registers) are UNKNOWN out of reset and could potentially generate
spurious, fatal debug exceptions in early boot code if PSTATE.D was
clear. Once the debug registers have been safely initialised, PSTATE.D
is cleared, however this is currently broken for two reasons:
(1) The boot CPU clears PSTATE.D in a postcore_initcall and secondary
CPUs clear PSTATE.D in secondary_start_kernel. Since the initcall
runs after SMP (and the scheduler) have been initialised, there is
no guarantee that it is actually running on the boot CPU. In this
case, the boot CPU is left with PSTATE.D set and is not capable of
generating debug exceptions.
(2) In a preemptible kernel, we may explicitly schedule on the IRQ
return path to EL1. If an IRQ occurs with PSTATE.D set in the idle
thread, then we may schedule the kthread_init thread, run the
postcore_initcall to clear PSTATE.D and then context switch back
to the idle thread before returning from the IRQ. The exception
return path will then restore PSTATE.D from the stack, and set it
again.
This patch fixes the problem by moving the clearing of PSTATE.D earlier
to proc.S. This has the desirable effect of clearing it in one place for
all CPUs, long before we have to worry about the scheduler or any
exception handling. We ensure that the previous reset of MDSCR_EL1 has
completed before unmasking the exception, so that any spurious
exceptions resulting from UNKNOWN debug registers are not generated.
Without this patch applied, the kprobes selftests have been seen to fail
under KVM, where we end up attempting to step the OOL instruction buffer
with PSTATE.D set and therefore fail to complete the step.
Cc: <stable@vger.kernel.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Reported-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2016-07-19 22:07:37 +08:00
|
|
|
isb // Unmask debug exceptions now,
|
|
|
|
enable_dbg // since this is per-cpu
|
2020-03-13 17:04:52 +08:00
|
|
|
reset_pmuserenr_el0 x1 // Disable PMU access from EL0
|
2020-03-25 19:11:08 +08:00
|
|
|
reset_amuserenr_el0 x1 // Disable AMU access from EL0
|
2020-03-05 17:06:22 +08:00
|
|
|
|
2012-03-05 19:49:28 +08:00
|
|
|
/*
|
2019-12-12 02:40:09 +08:00
|
|
|
* Memory region attributes
|
2012-03-05 19:49:28 +08:00
|
|
|
*/
|
2019-12-12 02:40:09 +08:00
|
|
|
mov_q x5, MAIR_EL1_SET
|
2012-03-05 19:49:28 +08:00
|
|
|
msr mair_el1, x5
|
|
|
|
/*
|
|
|
|
* Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for
|
|
|
|
* both user and kernel.
|
|
|
|
*/
|
2020-03-04 17:36:31 +08:00
|
|
|
mov_q x10, TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \
|
2018-02-27 22:15:49 +08:00
|
|
|
TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \
|
2018-12-28 16:30:31 +08:00
|
|
|
TCR_TBI0 | TCR_A1 | TCR_KASAN_FLAGS
|
2019-02-27 02:43:41 +08:00
|
|
|
tcr_clear_errata_bits x10, x9, x5
|
2018-12-07 06:50:41 +08:00
|
|
|
|
2019-08-07 23:55:22 +08:00
|
|
|
#ifdef CONFIG_ARM64_VA_BITS_52
|
2019-08-07 23:55:23 +08:00
|
|
|
ldr_l x9, vabits_actual
|
2018-12-07 06:50:41 +08:00
|
|
|
sub x9, xzr, x9
|
|
|
|
add x9, x9, #64
|
2019-08-07 23:55:22 +08:00
|
|
|
tcr_set_t1sz x10, x9
|
2018-12-07 06:50:41 +08:00
|
|
|
#else
|
|
|
|
ldr_l x9, idmap_t0sz
|
|
|
|
#endif
|
|
|
|
tcr_set_t0sz x10, x9
|
arm64: mm: increase VA range of identity map
The page size and the number of translation levels, and hence the supported
virtual address range, are build-time configurables on arm64 whose optimal
values are use case dependent. However, in the current implementation, if
the system's RAM is located at a very high offset, the virtual address range
needs to reflect that merely because the identity mapping, which is only used
to enable or disable the MMU, requires the extended virtual range to map the
physical memory at an equal virtual offset.
This patch relaxes that requirement, by increasing the number of translation
levels for the identity mapping only, and only when actually needed, i.e.,
when system RAM's offset is found to be out of reach at runtime.
Tested-by: Laura Abbott <lauraa@codeaurora.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2015-03-20 00:42:27 +08:00
|
|
|
|
2014-03-07 16:49:25 +08:00
|
|
|
/*
|
2017-12-14 01:07:17 +08:00
|
|
|
* Set the IPS bits in TCR_EL1.
|
2014-03-07 16:49:25 +08:00
|
|
|
*/
|
2017-12-14 01:07:17 +08:00
|
|
|
tcr_compute_pa_size x10, #TCR_IPS_SHIFT, x5, x6
|
2015-07-11 00:24:28 +08:00
|
|
|
#ifdef CONFIG_ARM64_HW_AFDBM
|
|
|
|
/*
|
2018-03-26 22:12:48 +08:00
|
|
|
* Enable hardware update of the Access Flags bit.
|
|
|
|
* Hardware dirty bit management is enabled later,
|
|
|
|
* via capabilities.
|
2015-07-11 00:24:28 +08:00
|
|
|
*/
|
|
|
|
mrs x9, ID_AA64MMFR1_EL1
|
|
|
|
and x9, x9, #0xf
|
2018-03-26 22:12:48 +08:00
|
|
|
cbz x9, 1f
|
|
|
|
orr x10, x10, #TCR_HA // hardware Access flag update
|
|
|
|
1:
|
2015-07-11 00:24:28 +08:00
|
|
|
#endif /* CONFIG_ARM64_HW_AFDBM */
|
2012-03-05 19:49:28 +08:00
|
|
|
msr tcr_el1, x10
|
2020-03-13 17:04:55 +08:00
|
|
|
mov x1, x0
|
2020-03-13 17:04:52 +08:00
|
|
|
/*
|
|
|
|
* Prepare SCTLR
|
|
|
|
*/
|
|
|
|
mov_q x0, SCTLR_EL1_SET
|
2020-03-13 17:04:55 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_ARM64_PTR_AUTH
|
|
|
|
/* No ptrauth setup for run time cpus */
|
|
|
|
cmp x1, #ARM64_CPU_RUNTIME
|
|
|
|
b.eq 3f
|
|
|
|
|
|
|
|
/* Check if the CPU supports ptrauth */
|
|
|
|
mrs x2, id_aa64isar1_el1
|
|
|
|
ubfx x2, x2, #ID_AA64ISAR1_APA_SHIFT, #8
|
|
|
|
cbz x2, 3f
|
|
|
|
|
2020-03-13 17:04:56 +08:00
|
|
|
/*
|
|
|
|
* The primary cpu keys are reset here and can be
|
|
|
|
* re-initialised with some proper values later.
|
|
|
|
*/
|
2020-03-13 17:04:55 +08:00
|
|
|
msr_s SYS_APIAKEYLO_EL1, xzr
|
|
|
|
msr_s SYS_APIAKEYHI_EL1, xzr
|
|
|
|
|
|
|
|
/* Just enable ptrauth for primary cpu */
|
|
|
|
cmp x1, #ARM64_CPU_BOOT_PRIMARY
|
|
|
|
b.eq 2f
|
|
|
|
|
|
|
|
/* if !system_supports_address_auth() then skip enable */
|
|
|
|
alternative_if_not ARM64_HAS_ADDRESS_AUTH
|
|
|
|
b 3f
|
|
|
|
alternative_else_nop_endif
|
|
|
|
|
2020-03-13 17:04:56 +08:00
|
|
|
/* Install ptrauth key for secondary cpus */
|
|
|
|
adr_l x2, secondary_data
|
|
|
|
ldr x3, [x2, #CPU_BOOT_TASK] // get secondary_data.task
|
|
|
|
cbz x3, 2f // check for slow booting cpus
|
|
|
|
ldp x3, x4, [x2, #CPU_BOOT_PTRAUTH_KEY]
|
|
|
|
msr_s SYS_APIAKEYLO_EL1, x3
|
|
|
|
msr_s SYS_APIAKEYHI_EL1, x4
|
|
|
|
|
2020-03-13 17:04:55 +08:00
|
|
|
2: /* Enable ptrauth instructions */
|
|
|
|
ldr x2, =SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \
|
|
|
|
SCTLR_ELx_ENDA | SCTLR_ELx_ENDB
|
|
|
|
orr x0, x0, x2
|
|
|
|
3:
|
|
|
|
#endif
|
2012-03-05 19:49:28 +08:00
|
|
|
ret // return to head.S
|
2020-01-07 03:58:18 +08:00
|
|
|
SYM_FUNC_END(__cpu_setup)
|