mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-26 03:25:20 +07:00
6b88a32c7a
With ARM64_SW_TTBR0_PAN enabled, the exception entry code checks the active ASID to decide whether user access was enabled (non-zero ASID) when the exception was taken. On return from exception, if user access was previously disabled, it re-instates TTBR0_EL1 from the per-thread saved value (updated in switch_mm() or efi_set_pgd()). Commit7655abb953
("arm64: mm: Move ASID from TTBR0 to TTBR1") makes a TTBR0_EL1 + ASID switching non-atomic. Subsequently, commit27a921e757
("arm64: mm: Fix and re-enable ARM64_SW_TTBR0_PAN") changes the __uaccess_ttbr0_disable() function and asm macro to first write the reserved TTBR0_EL1 followed by the ASID=0 update in TTBR1_EL1. If an exception occurs between these two, the exception return code will re-instate a valid TTBR0_EL1. Similar scenario can happen in cpu_switch_mm() between setting the reserved TTBR0_EL1 and the ASID update in cpu_do_switch_mm(). This patch reverts the entry.S check for ASID == 0 to TTBR0_EL1 and disables the interrupts around the TTBR0_EL1 and ASID switching code in __uaccess_ttbr0_disable(). It also ensures that, when returning from the EFI runtime services, efi_set_pgd() doesn't leave a non-zero ASID in TTBR1_EL1 by using uaccess_ttbr0_{enable,disable}. The accesses to current_thread_info()->ttbr0 are updated to use READ_ONCE/WRITE_ONCE. As a safety measure, __uaccess_ttbr0_enable() always masks out any existing non-zero ASID TTBR1_EL1 before writing in the new ASID. Fixes:27a921e757
("arm64: mm: Fix and re-enable ARM64_SW_TTBR0_PAN") Acked-by: Will Deacon <will.deacon@arm.com> Reported-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: James Morse <james.morse@arm.com> Tested-by: James Morse <james.morse@arm.com> Co-developed-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
88 lines
2.1 KiB
C
88 lines
2.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __ASM_ASM_UACCESS_H
|
|
#define __ASM_ASM_UACCESS_H
|
|
|
|
#include <asm/alternative.h>
|
|
#include <asm/kernel-pgtable.h>
|
|
#include <asm/mmu.h>
|
|
#include <asm/sysreg.h>
|
|
#include <asm/assembler.h>
|
|
|
|
/*
|
|
* User access enabling/disabling macros.
|
|
*/
|
|
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
|
.macro __uaccess_ttbr0_disable, tmp1
|
|
mrs \tmp1, ttbr1_el1 // swapper_pg_dir
|
|
bic \tmp1, \tmp1, #TTBR_ASID_MASK
|
|
sub \tmp1, \tmp1, #RESERVED_TTBR0_SIZE // reserved_ttbr0 just before swapper_pg_dir
|
|
msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1
|
|
isb
|
|
add \tmp1, \tmp1, #RESERVED_TTBR0_SIZE
|
|
msr ttbr1_el1, \tmp1 // set reserved ASID
|
|
isb
|
|
.endm
|
|
|
|
.macro __uaccess_ttbr0_enable, tmp1, tmp2
|
|
get_thread_info \tmp1
|
|
ldr \tmp1, [\tmp1, #TSK_TI_TTBR0] // load saved TTBR0_EL1
|
|
mrs \tmp2, ttbr1_el1
|
|
extr \tmp2, \tmp2, \tmp1, #48
|
|
ror \tmp2, \tmp2, #16
|
|
msr ttbr1_el1, \tmp2 // set the active ASID
|
|
isb
|
|
msr ttbr0_el1, \tmp1 // set the non-PAN TTBR0_EL1
|
|
isb
|
|
.endm
|
|
|
|
.macro uaccess_ttbr0_disable, tmp1, tmp2
|
|
alternative_if_not ARM64_HAS_PAN
|
|
save_and_disable_irq \tmp2 // avoid preemption
|
|
__uaccess_ttbr0_disable \tmp1
|
|
restore_irq \tmp2
|
|
alternative_else_nop_endif
|
|
.endm
|
|
|
|
.macro uaccess_ttbr0_enable, tmp1, tmp2, tmp3
|
|
alternative_if_not ARM64_HAS_PAN
|
|
save_and_disable_irq \tmp3 // avoid preemption
|
|
__uaccess_ttbr0_enable \tmp1, \tmp2
|
|
restore_irq \tmp3
|
|
alternative_else_nop_endif
|
|
.endm
|
|
#else
|
|
.macro uaccess_ttbr0_disable, tmp1, tmp2
|
|
.endm
|
|
|
|
.macro uaccess_ttbr0_enable, tmp1, tmp2, tmp3
|
|
.endm
|
|
#endif
|
|
|
|
/*
|
|
* These macros are no-ops when UAO is present.
|
|
*/
|
|
.macro uaccess_disable_not_uao, tmp1, tmp2
|
|
uaccess_ttbr0_disable \tmp1, \tmp2
|
|
alternative_if ARM64_ALT_PAN_NOT_UAO
|
|
SET_PSTATE_PAN(1)
|
|
alternative_else_nop_endif
|
|
.endm
|
|
|
|
.macro uaccess_enable_not_uao, tmp1, tmp2, tmp3
|
|
uaccess_ttbr0_enable \tmp1, \tmp2, \tmp3
|
|
alternative_if ARM64_ALT_PAN_NOT_UAO
|
|
SET_PSTATE_PAN(0)
|
|
alternative_else_nop_endif
|
|
.endm
|
|
|
|
/*
|
|
* Remove the address tag from a virtual address, if present.
|
|
*/
|
|
.macro clear_address_tag, dst, addr
|
|
tst \addr, #(1 << 55)
|
|
bic \dst, \addr, #(0xff << 56)
|
|
csel \dst, \dst, \addr, eq
|
|
.endm
|
|
|
|
#endif
|