2019-06-03 07:44:50 +02:00
/* SPDX-License-Identifier: GPL-2.0-only */
2012-03-05 11:49:28 +00:00
/ *
* Based o n a r c h / a r m / m m / p r o c . S
*
* Copyright ( C ) 2 0 0 1 D e e p B l u e S o l u t i o n s L t d .
* Copyright ( C ) 2 0 1 2 A R M L t d .
* Author : Catalin M a r i n a s < c a t a l i n . m a r i n a s @arm.com>
* /
# include < l i n u x / i n i t . h >
# include < l i n u x / l i n k a g e . h >
2020-06-08 21:32:42 -07:00
# include < l i n u x / p g t a b l e . h >
2012-03-05 11:49:28 +00:00
# include < a s m / a s s e m b l e r . h >
# include < a s m / a s m - o f f s e t s . h >
2020-03-13 14:35:01 +05:30
# include < a s m / a s m _ p o i n t e r _ a u t h . h >
2012-03-05 11:49:28 +00:00
# include < a s m / h w c a p . h >
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
# include < a s m / k e r n e l - p g t a b l e . h >
2016-04-27 17:47:07 +01:00
# include < a s m / p g t a b l e - h w d e f . h >
2016-02-24 17:44:57 -08:00
# include < a s m / c p u f e a t u r e . h >
# include < a s m / a l t e r n a t i v e . h >
2020-03-13 14:34:55 +05:30
# include < a s m / s m p . h >
2019-09-06 10:58:01 +01:00
# include < a s m / s y s r e g . h >
2012-03-05 11:49:28 +00:00
2014-04-02 17:55:40 +01:00
# ifdef C O N F I G _ A R M 6 4 _ 6 4 K _ P A G E S
# define T C R _ T G _ F L A G S T C R _ T G 0 _ 6 4 K | T C R _ T G 1 _ 6 4 K
2015-10-19 14:19:37 +01:00
# elif d e f i n e d ( C O N F I G _ A R M 6 4 _ 1 6 K _ P A G E S )
# define T C R _ T G _ F L A G S T C R _ T G 0 _ 1 6 K | T C R _ T G 1 _ 1 6 K
# else / * C O N F I G _ A R M 6 4 _ 4 K _ P A G E S * /
2014-04-02 17:55:40 +01:00
# define T C R _ T G _ F L A G S T C R _ T G 0 _ 4 K | T C R _ T G 1 _ 4 K
# endif
2018-02-27 14:15:49 +00:00
# ifdef C O N F I G _ R A N D O M I Z E _ B A S E
# define T C R _ K A S L R _ F L A G S T C R _ N F D 1
# else
# define T C R _ K A S L R _ F L A G S 0
# endif
2014-04-02 17:55:40 +01:00
# define T C R _ S M P _ F L A G S T C R _ S H A R E D
2012-03-05 11:49:28 +00:00
2014-04-02 17:55:40 +01:00
/* PTWs cacheable, inner/outer WBWA */
# define T C R _ C A C H E _ F L A G S T C R _ I R G N _ W B W A | T C R _ O R G N _ W B W A
2018-12-28 00:30:31 -08:00
# ifdef C O N F I G _ K A S A N _ S W _ T A G S
2020-12-22 12:01:38 -08:00
# define T C R _ K A S A N _ S W _ F L A G S T C R _ T B I 1 | T C R _ T B I D 1
2018-12-28 00:30:31 -08:00
# else
2020-12-22 12:01:38 -08:00
# define T C R _ K A S A N _ S W _ F L A G S 0
# endif
# ifdef C O N F I G _ K A S A N _ H W _ T A G S
2022-01-25 20:08:33 +05:30
# define T C R _ M T E _ F L A G S T C R _ T C M A 1 | T C R _ T B I 1 | T C R _ T B I D 1
2020-12-22 12:01:38 -08:00
# else
2021-06-02 16:52:29 -07:00
/ *
* The m t e _ z e r o _ c l e a r _ p a g e _ t a g s ( ) i m p l e m e n t a t i o n u s e s D C G Z V A , w h i c h r e l i e s o n
* TBI b e i n g e n a b l e d a t E L 1 .
* /
# define T C R _ M T E _ F L A G S T C R _ T B I 1 | T C R _ T B I D 1
2018-12-28 00:30:31 -08:00
# endif
2019-11-27 09:51:13 +00:00
/ *
* Default M A I R _ E L 1 . M T _ N O R M A L _ T A G G E D i s i n i t i a l l y m a p p e d a s N o r m a l m e m o r y a n d
* changed d u r i n g _ _ c p u _ s e t u p t o N o r m a l T a g g e d i f t h e s y s t e m s u p p o r t s M T E .
* /
2019-12-11 18:40:09 +00:00
# define M A I R _ E L 1 _ S E T \
( MAIR_ A T T R I D X ( M A I R _ A T T R _ D E V I C E _ n G n R n E , M T _ D E V I C E _ n G n R n E ) | \
MAIR_ A T T R I D X ( M A I R _ A T T R _ D E V I C E _ n G n R E , M T _ D E V I C E _ n G n R E ) | \
MAIR_ A T T R I D X ( M A I R _ A T T R _ N O R M A L _ N C , M T _ N O R M A L _ N C ) | \
MAIR_ A T T R I D X ( M A I R _ A T T R _ N O R M A L , M T _ N O R M A L ) | \
2019-11-27 09:51:13 +00:00
MAIR_ A T T R I D X ( M A I R _ A T T R _ N O R M A L , M T _ N O R M A L _ T A G G E D ) )
2012-03-05 11:49:28 +00:00
2015-01-26 18:33:44 +00:00
# ifdef C O N F I G _ C P U _ P M
2013-07-17 10:14:45 +01:00
/ * *
* cpu_ d o _ s u s p e n d - s a v e C P U r e g i s t e r s c o n t e x t
*
* x0 : virtual a d d r e s s o f c o n t e x t p o i n t e r
2020-04-27 09:00:12 -07:00
*
* This m u s t b e k e p t i n s y n c w i t h s t r u c t c p u _ s u s p e n d _ c t x i n < a s m / s u s p e n d . h > .
2013-07-17 10:14:45 +01:00
* /
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ S T A R T ( c p u _ d o _ s u s p e n d )
2013-07-17 10:14:45 +01:00
mrs x2 , t p i d r _ e l 0
mrs x3 , t p i d r r o _ e l 0
mrs x4 , c o n t e x t i d r _ e l 1
2019-04-08 18:17:19 +01:00
mrs x5 , o s d l r _ e l 1
mrs x6 , c p a c r _ e l 1
mrs x7 , t c r _ e l 1
mrs x8 , v b a r _ e l 1
mrs x9 , m d s c r _ e l 1
mrs x10 , o s l s r _ e l 1
mrs x11 , s c t l r _ e l 1
2021-05-20 12:50:27 +01:00
get_ t h i s _ c p u _ o f f s e t x12
2019-04-08 18:17:19 +01:00
mrs x13 , s p _ e l 0
2013-07-17 10:14:45 +01:00
stp x2 , x3 , [ x0 ]
2019-04-08 18:17:19 +01: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 ]
2020-04-27 09:00:12 -07:00
/ *
* Save x18 a s i t m a y b e u s e d a s a p l a t f o r m r e g i s t e r , e . g . b y s h a d o w
* call s t a c k .
* /
str x18 , [ x0 , #96 ]
2013-07-17 10:14:45 +01:00
ret
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ E N D ( c p u _ d o _ s u s p e n d )
2013-07-17 10:14:45 +01:00
/ * *
* cpu_ d o _ r e s u m e - r e s t o r e C P U r e g i s t e r c o n t e x t
*
2016-04-27 17:47:07 +01:00
* x0 : Address o f c o n t e x t p o i n t e r
2013-07-17 10:14:45 +01:00
* /
2018-01-29 12:00:00 +00:00
.pushsection " .idmap .text " , " awx"
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ S T A R T ( c p u _ d o _ r e s u m e )
2013-07-17 10:14:45 +01:00
ldp x2 , x3 , [ x0 ]
ldp x4 , x5 , [ x0 , #16 ]
2016-04-27 17:47:07 +01:00
ldp x6 , x8 , [ x0 , #32 ]
ldp x9 , x10 , [ x0 , #48 ]
ldp x11 , x12 , [ x0 , #64 ]
2016-11-03 20:23:09 +00:00
ldp x13 , x14 , [ x0 , #80 ]
2020-04-27 09:00:12 -07:00
/ *
* Restore x18 , a s i t m a y b e u s e d a s a p l a t f o r m r e g i s t e r , a n d c l e a r
* the b u f f e r t o m i n i m i z e t h e r i s k o f e x p o s u r e w h e n u s e d f o r s h a d o w
* call s t a c k .
* /
ldr x18 , [ x0 , #96 ]
str x z r , [ x0 , #96 ]
2013-07-17 10:14:45 +01:00
msr t p i d r _ e l 0 , x2
msr t p i d r r o _ e l 0 , x3
msr c o n t e x t i d r _ e l 1 , x4
msr c p a c r _ e l 1 , x6
2016-04-27 17:47:07 +01:00
/* Don't change t0sz here, mask those bits when restoring */
2019-04-08 18:17:19 +01:00
mrs x7 , t c r _ e l 1
bfi x8 , x7 , T C R _ T 0 S Z _ O F F S E T , T C R _ T x S Z _ W I D T H
2016-04-27 17:47:07 +01:00
2013-07-17 10:14:45 +01:00
msr t c r _ e l 1 , x8
msr v b a r _ e l 1 , x9
2016-08-26 16:03:42 +01:00
/ *
* _ _ cpu_ s e t u p ( ) c l e a r e d M D S C R _ E L 1 . M D E a n d f r i e n d s , b e f o r e u n m a s k i n g
* debug e x c e p t i o n s . B y r e s t o r i n g M D S C R _ E L 1 h e r e , w e m a y t a k e a d e b u g
2017-11-02 12:12:34 +00:00
* exception. M a s k t h e m u n t i l l o c a l _ d a i f _ r e s t o r e ( ) i n c p u _ s u s p e n d ( )
2016-08-26 16:03:42 +01:00
* resets t h e m .
* /
2017-11-02 12:12:34 +00:00
disable_ d a i f
2013-07-17 10:14:45 +01:00
msr m d s c r _ e l 1 , x10
2016-08-26 16:03:42 +01:00
2016-04-27 17:47:07 +01:00
msr s c t l r _ e l 1 , x12
2021-05-20 12:50:27 +01:00
set_ t h i s _ c p u _ o f f s e t x13
2016-11-03 20:23:09 +00:00
msr s p _ e l 0 , x14
2013-07-17 10:14:45 +01:00
/ *
* Restore o s l s r _ e l 1 b y w r i t i n g o s l a r _ e l 1
* /
2019-04-08 18:17:19 +01:00
msr o s d l r _ e l 1 , x5
2013-07-17 10:14:45 +01:00
ubfx x11 , x11 , #1 , #1
msr o s l a r _ e l 1 , x11
2016-01-13 14:50:03 +00:00
reset_ p m u s e r e n r _ e l 0 x0 / / D i s a b l e P M U a c c e s s f r o m E L 0
2020-03-05 09:06:22 +00:00
reset_ a m u s e r e n r _ e l 0 x0 / / D i s a b l e A M U a c c e s s f r o m E L 0
2018-01-15 19:38:59 +00:00
alternative_ i f A R M 6 4 _ H A S _ R A S _ E X T N
msr_ s S Y S _ D I S R _ E L 1 , x z r
alternative_ e l s e _ n o p _ e n d i f
2020-04-23 11:16:05 +01:00
ptrauth_ k e y s _ i n s t a l l _ k e r n e l _ n o s y n c x14 , x1 , x2 , x3
2013-07-17 10:14:45 +01:00
isb
ret
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ E N D ( c p u _ d o _ r e s u m e )
2016-08-24 18:27:29 +01:00
.popsection
2013-07-17 10:14:45 +01:00
# endif
2018-01-29 12:00:00 +00:00
.pushsection " .idmap .text " , " awx"
2018-02-06 22:22:50 +00:00
.macro _ _ idmap_ c p u _ s e t _ r e s e r v e d _ t t b r1 , t m p1 , t m p2
2020-11-03 10:22:29 +00:00
adrp \ t m p1 , r e s e r v e d _ p g _ d i r
2018-01-29 11:59:57 +00:00
phys_ t o _ t t b r \ t m p2 , \ t m p1
2019-08-07 16:55:19 +01:00
offset_ t t b r1 \ t m p2 , \ t m p1
2018-02-06 22:22:50 +00:00
msr t t b r1 _ e l 1 , \ t m p2
isb
tlbi v m a l l e 1
dsb n s h
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 11:45:01 +00:00
/ *
2018-07-31 14:08:56 +01:00
* void i d m a p _ c p u _ r e p l a c e _ t t b r1 ( p h y s _ a d d r _ t t t b r1 )
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 11:45:01 +00:00
*
* This i s t h e l o w - l e v e l c o u n t e r p a r t t o c p u _ r e p l a c e _ t t b r1 , a n d s h o u l d n o t b e
* called b y a n y t h i n g e l s e . I t c a n o n l y b e e x e c u t e d f r o m a T T B R 0 m a p p i n g .
* /
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ S T A R T ( i d m a p _ c p u _ r e p l a c e _ t t b r1 )
2017-11-02 12:12:34 +00:00
save_ a n d _ d i s a b l e _ d a i f f l a g s =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 11:45:01 +00:00
2018-02-06 22:22:50 +00:00
_ _ idmap_ c p u _ s e t _ r e s e r v e d _ t t b r1 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 11:45:01 +00:00
2019-08-07 16:55:19 +01:00
offset_ t t b r1 x0 , x3
2018-07-31 14:08:56 +01:00
msr t t b r1 _ e l 1 , 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 11:45:01 +00:00
isb
2017-11-02 12:12:34 +00:00
restore_ d a i f 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 11:45:01 +00:00
ret
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ E N D ( i d m a p _ c p u _ r e p l a c e _ t t b r1 )
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 11:45:01 +00:00
.popsection
2018-02-06 22:22:50 +00:00
# ifdef C O N F I G _ U N M A P _ K E R N E L _ A T _ E L 0
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
# define K P T I _ N G _ P T E _ F L A G S ( P T E _ A T T R I N D X ( M T _ N O R M A L ) | S W A P P E R _ P T E _ F L A G S )
2018-01-29 12:00:00 +00:00
.pushsection " .idmap .text " , " awx"
2018-02-06 22:22:50 +00:00
2022-06-09 19:43:19 +02:00
.macro kpti_ m k _ t b l _ n g , t y p e , n u m _ e n t r i e s
add e n d _ \ t y p e \ ( ) p , c u r _ \ t y p e \ ( ) p , #\ n u m _ e n t r i e s * 8
.Ldo_ \ type :
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
ldr \ t y p e , [ c u r _ \ t y p e \ ( ) p ] / / L o a d t h e e n t r y
2022-06-09 19:43:19 +02:00
tbz \ t y p e , #0 , . L n e x t _ \ t y p e / / S k i p i n v a l i d a n d
tbnz \ t y p e , #11 , . L n e x t _ \ t y p e / / n o n - g l o b a l e n t r i e s
2018-02-06 22:22:50 +00:00
orr \ t y p e , \ t y p e , #P T E _ N G / / S a m e b i t f o r b l o c k s a n d p a g e s
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
str \ t y p e , [ c u r _ \ t y p e \ ( ) p ] / / U p d a t e t h e e n t r y
2022-06-09 19:43:19 +02:00
.ifnc \ type, p t e
tbnz \ t y p e , #1 , . L d e r e f _ \ t y p e
.endif
.Lnext_ \ type :
add c u r _ \ t y p e \ ( ) p , c u r _ \ t y p e \ ( ) p , #8
cmp c u r _ \ t y p e \ ( ) p , e n d _ \ t y p e \ ( ) p
b. n e . L d o _ \ t y p e
2018-02-06 22:22:50 +00:00
.endm
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
/ *
* Dereference t h e c u r r e n t t a b l e e n t r y a n d m a p i t i n t o t h e t e m p o r a r y
* fixmap s l o t a s s o c i a t e d w i t h t h e c u r r e n t l e v e l .
* /
.macro kpti_ m a p _ p g t b l , t y p e , l e v e l
str x z r , [ t e m p _ p t e , #8 * ( \ l e v e l + 1 ) ] / / b r e a k b e f o r e m a k e
dsb n s h s t
add p t e , t e m p _ p t e , #P A G E _ S I Z E * ( \ l e v e l + 1 )
lsr p t e , p t e , #12
tlbi v a a e 1 , p t e
dsb n s h
isb
phys_ t o _ p t e p t e , c u r _ \ t y p e \ ( ) p
add c u r _ \ t y p e \ ( ) p , t e m p _ p t e , #P A G E _ S I Z E * ( \ l e v e l + 1 )
orr p t e , p t e , p t e _ f l a g s
str p t e , [ t e m p _ p t e , #8 * ( \ l e v e l + 1 ) ]
dsb n s h s t
.endm
2018-02-06 22:22:50 +00:00
/ *
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
* void _ _ k p t i _ i n s t a l l _ n g _ m a p p i n g s ( i n t c p u , i n t n u m _ s e c o n d a r i e s , p h y s _ a d d r _ t t e m p _ p g d ,
* unsigned l o n g t e m p _ p t e _ v a )
2018-02-06 22:22:50 +00:00
*
* Called e x a c t l y o n c e f r o m s t o p _ m a c h i n e c o n t e x t b y e a c h C P U f o u n d d u r i n g b o o t .
* /
2022-06-24 17:06:42 +02:00
.pushsection " .data " , " aw" , % p r o g b i t s
SYM_ D A T A ( _ _ i d m a p _ k p t i _ f l a g , . l o n g 1 )
.popsection
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ S T A R T ( i d m a p _ k p t i _ i n s t a l l _ n g _ m a p p i n g s )
2018-02-06 22:22:50 +00:00
cpu . r e q w0
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
temp_ p t e . r e q x0
2018-02-06 22:22:50 +00:00
num_ c p u s . r e q w1
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
pte_ f l a g s . r e q x1
temp_ p g d _ p h y s . r e q x2
2018-02-06 22:22:50 +00:00
swapper_ t t b . r e q x3
flag_ p t r . r e q x4
cur_ p g d p . r e q x5
end_ p g d p . r e q x6
pgd . r e q x7
cur_ p u d p . r e q x8
end_ p u d p . r e q x9
cur_ p m d p . r e q x11
end_ p m d p . r e q x12
cur_ p t e p . r e q x14
end_ p t e p . r e q x15
pte . r e q x16
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
valid . r e q x17
2018-02-06 22:22:50 +00:00
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
mov x5 , x3 / / p r e s e r v e t e m p _ p t e a r g
2018-02-06 22:22:50 +00:00
mrs s w a p p e r _ t t b , t t b r1 _ e l 1
2022-06-24 17:06:42 +02:00
adr_ l f l a g _ p t r , _ _ i d m a p _ k p t i _ f l a g
2018-02-06 22:22:50 +00:00
cbnz c p u , _ _ i d m a p _ k p t i _ s e c o n d a r y
/* We're the boot CPU. Wait for the others to catch up */
sevl
1 : wfe
2019-12-06 14:13:37 -08:00
ldaxr w17 , [ f l a g _ p t r ]
eor w17 , w17 , n u m _ c p u s
cbnz w17 , 1 b
2018-02-06 22:22:50 +00:00
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
/* Switch to the temporary page tables on this CPU only */
_ _ idmap_ c p u _ s e t _ r e s e r v e d _ t t b r1 x8 , x9
offset_ t t b r1 t e m p _ p g d _ p h y s , x8
msr t t b r1 _ e l 1 , t e m p _ p g d _ p h y s
2018-02-06 22:22:50 +00:00
isb
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
mov t e m p _ p t e , x5
mov p t e _ f l a g s , #K P T I _ N G _ P T E _ F L A G S
2018-02-06 22:22:50 +00:00
/* Everybody is enjoying the idmap, so we can rewrite swapper. */
/* PGD */
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
adrp c u r _ p g d p , s w a p p e r _ p g _ d i r
kpti_ m a p _ p g t b l p g d , 0
2022-06-09 19:43:19 +02:00
kpti_ m k _ t b l _ n g p g d , P T R S _ P E R _ P G D
2018-02-06 22:22:50 +00:00
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
/* Ensure all the updated entries are visible to secondary CPUs */
dsb i s h s t
2018-02-06 22:22:50 +00:00
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
/* We're done: fire up swapper_pg_dir again */
_ _ idmap_ c p u _ s e t _ r e s e r v e d _ t t b r1 x8 , x9
msr t t b r1 _ e l 1 , s w a p p e r _ t t b
isb
2019-08-27 18:12:57 +01:00
2018-02-06 22:22:50 +00:00
/* Set the flag to zero to indicate that we're all done */
str w z r , [ f l a g _ p t r ]
ret
2022-06-09 19:43:19 +02:00
.Lderef_pgd :
2018-02-06 22:22:50 +00:00
/* PUD */
2022-06-09 19:43:19 +02:00
.if CONFIG_PGTABLE_LEVELS > 3
pud . r e q x10
2018-02-06 22:22:50 +00:00
pte_ t o _ p h y s c u r _ p u d p , p g d
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
kpti_ m a p _ p g t b l p u d , 1
2022-06-09 19:43:19 +02:00
kpti_ m k _ t b l _ n g p u d , P T R S _ P E R _ P U D
b . L n e x t _ p g d
.else /* CONFIG_PGTABLE_LEVELS <= 3 */
pud . r e q p g d
.set .Lnext_pud , .Lnext_pgd
2018-02-06 22:22:50 +00:00
.endif
2022-06-09 19:43:19 +02:00
.Lderef_pud :
2018-02-06 22:22:50 +00:00
/* PMD */
2022-06-09 19:43:19 +02:00
.if CONFIG_PGTABLE_LEVELS > 2
pmd . r e q x13
2018-02-06 22:22:50 +00:00
pte_ t o _ p h y s c u r _ p m d p , p u d
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
kpti_ m a p _ p g t b l p m d , 2
2022-06-09 19:43:19 +02:00
kpti_ m k _ t b l _ n g p m d , P T R S _ P E R _ P M D
b . L n e x t _ p u d
.else /* CONFIG_PGTABLE_LEVELS <= 2 */
pmd . r e q p g d
.set .Lnext_pmd , .Lnext_pgd
2018-02-06 22:22:50 +00:00
.endif
2022-06-09 19:43:19 +02:00
.Lderef_pmd :
2018-02-06 22:22:50 +00:00
/* PTE */
pte_ t o _ p h y s c u r _ p t e p , p m d
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
kpti_ m a p _ p g t b l p t e , 3
2022-06-09 19:43:19 +02:00
kpti_ m k _ t b l _ n g p t e , P T R S _ P E R _ P T E
b . L n e x t _ p m d
2018-02-06 22:22:50 +00:00
2019-12-06 14:13:37 -08:00
.unreq cpu
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
.unreq temp_pte
2019-12-06 14:13:37 -08:00
.unreq num_cpus
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
.unreq pte_flags
.unreq temp_pgd_phys
2019-12-06 14:13:37 -08:00
.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
arm64: mm: install KPTI nG mappings with MMU enabled
In cases where we unmap the kernel while running in user space, we rely
on ASIDs to distinguish the minimal trampoline from the full kernel
mapping, and this means we must use non-global attributes for those
mappings, to ensure they are scoped by ASID and will not hit in the TLB
inadvertently.
We only do this when needed, as this is generally more costly in terms
of TLB pressure, and so we boot without these non-global attributes, and
apply them to all existing kernel mappings once all CPUs are up and we
know whether or not the non-global attributes are needed. At this point,
we cannot simply unmap and remap the entire address space, so we have to
update all existing block and page descriptors in place.
Currently, we go through a lot of trouble to perform these updates with
the MMU and caches off, to avoid violating break before make (BBM) rules
imposed by the architecture. Since we make changes to page tables that
are not covered by the ID map, we gain access to those descriptors by
disabling translations altogether. This means that the stores to memory
are issued with device attributes, and require extra care in terms of
coherency, which is costly. We also rely on the ID map to access a
shared flag, which requires the ID map to be executable and writable at
the same time, which is another thing we'd prefer to avoid.
So let's switch to an approach where we replace the kernel mapping with
a minimal mapping of a few pages that can be used for a minimal, ad-hoc
fixmap that we can use to map each page table in turn as we traverse the
hierarchy.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220609174320.4035379-3-ardb@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
2022-06-09 19:43:20 +02:00
.unreq valid
2019-12-06 14:13:37 -08:00
2018-02-06 22:22:50 +00:00
/* Secondary CPUs end up here */
__idmap_kpti_secondary :
/* Uninstall swapper before surgery begins */
2019-12-06 14:13:37 -08:00
_ _ idmap_ c p u _ s e t _ r e s e r v e d _ t t b r1 x16 , x17
2018-02-06 22:22:50 +00:00
/* Increment the flag to let the boot CPU we're ready */
2019-12-06 14:13:37 -08:00
1 : ldxr w16 , [ f l a g _ p t r ]
add w16 , w16 , #1
stxr w17 , w16 , [ f l a g _ p t r ]
2018-02-06 22:22:50 +00:00
cbnz w17 , 1 b
/* Wait for the boot CPU to finish messing around with swapper */
sevl
1 : wfe
2019-12-06 14:13:37 -08:00
ldxr w16 , [ f l a g _ p t r ]
cbnz w16 , 1 b
2018-02-06 22:22:50 +00:00
/* All done, act like nothing happened */
msr t t b r1 _ e l 1 , s w a p p e r _ t t b
isb
ret
.unreq swapper_ttb
.unreq flag_ptr
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ E N D ( i d m a p _ k p t i _ i n s t a l l _ n g _ m a p p i n g s )
2018-02-06 22:22:50 +00:00
.popsection
# endif
2012-03-05 11:49:28 +00:00
/ *
* _ _ cpu_ s e t u p
*
2020-03-13 14:34:52 +05:30
* Initialise t h e p r o c e s s o r f o r t u r n i n g t h e M M U o n .
*
2022-07-01 13:10:45 +02:00
* Input :
* x0 - a c t u a l n u m b e r o f V A b i t s ( i g n o r e d u n l e s s V A _ B I T S > 4 8 )
2020-03-13 14:34:52 +05:30
* Output :
* Return i n x0 t h e v a l u e o f t h e S C T L R _ E L 1 r e g i s t e r .
2012-03-05 11:49:28 +00:00
* /
2018-01-29 12:00:00 +00:00
.pushsection " .idmap .text " , " awx"
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ S T A R T ( _ _ c p u _ s e t u p )
2015-10-06 18:46:22 +01:00
tlbi v m a l l e 1 / / I n v a l i d a t e l o c a l T L B
dsb n s h
2012-03-05 11:49:28 +00:00
2020-03-13 14:34:52 +05:30
mov x1 , #3 < < 2 0
msr c p a c r _ e l 1 , x1 / / E n a b l e F P / A S I M D
mov x1 , #1 < < 1 2 / / R e s e t m d s c r _ e l 1 a n d d i s a b l e
msr m d s c r _ e l 1 , x1 / / a c c e s s t o t h e D C C f r o m E L 0
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 15:07:37 +01:00
isb / / U n m a s k d e b u g e x c e p t i o n s n o w ,
enable_ d b g / / s i n c e t h i s i s p e r - c p u
2020-03-13 14:34:52 +05:30
reset_ p m u s e r e n r _ e l 0 x1 / / D i s a b l e P M U a c c e s s f r o m E L 0
2020-03-25 11:11:08 +00:00
reset_ a m u s e r e n r _ e l 0 x1 / / D i s a b l e A M U a c c e s s f r o m E L 0
2020-03-05 09:06:22 +00:00
2012-03-05 11:49:28 +00:00
/ *
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
* Default v a l u e s f o r V M S A c o n t r o l r e g i s t e r s . T h e s e w i l l b e a d j u s t e d
* below d e p e n d i n g o n d e t e c t e d C P U f e a t u r e s .
2012-03-05 11:49:28 +00:00
* /
2021-03-26 18:01:36 +00:00
mair . r e q x17
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
tcr . r e q x16
2021-03-26 18:01:36 +00:00
mov_ q m a i r , M A I R _ E L 1 _ S E T
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
mov_ q t c r , T C R _ T x S Z ( V A _ B I T S ) | T C R _ C A C H E _ F L A G S | T C R _ S M P _ F L A G S | \
TCR_ T G _ F L A G S | T C R _ K A S L R _ F L A G S | T C R _ A S I D 1 6 | \
TCR_ T B I 0 | T C R _ A 1 | T C R _ K A S A N _ S W _ F L A G S
2020-12-22 12:01:38 -08:00
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
# ifdef C O N F I G _ A R M 6 4 _ M T E
2019-09-06 10:58:01 +01:00
/ *
* Update M A I R _ E L 1 , G C R _ E L 1 a n d T F S R * _ E L 1 i f M T E i s s u p p o r t e d
* ( ID_ A A 6 4 P F R 1 _ E L 1 [ 1 1 : 8 ] > 1 ) .
* /
mrs x10 , I D _ A A 6 4 P F R 1 _ E L 1
ubfx x10 , x10 , #I D _ A A 64 P F R 1 _ M T E _ S H I F T , #4
cmp x10 , #I D _ A A 64 P F R 1 _ M T E
b. l t 1 f
/* Normal Tagged memory type at the corresponding MAIR index */
mov x10 , #M A I R _ A T T R _ N O R M A L _ T A G G E D
2021-03-26 18:01:36 +00:00
bfi m a i r , x10 , #( 8 * M T _ N O R M A L _ T A G G E D ) , #8
2019-09-06 10:58:01 +01:00
arm64: kasan: mte: use a constant kernel GCR_EL1 value
When KASAN_HW_TAGS is selected, KASAN is enabled at boot time, and the
hardware supports MTE, we'll initialize `kernel_gcr_excl` with a value
dependent on KASAN_TAG_MAX. While the resulting value is a constant
which depends on KASAN_TAG_MAX, we have to perform some runtime work to
generate the value, and have to read the value from memory during the
exception entry path. It would be better if we could generate this as a
constant at compile-time, and use it as such directly.
Early in boot within __cpu_setup(), we initialize GCR_EL1 to a safe
value, and later override this with the value required by KASAN. If
CONFIG_KASAN_HW_TAGS is not selected, or if KASAN is disabeld at boot
time, the kernel will not use IRG instructions, and so the initial value
of GCR_EL1 is does not matter to the kernel. Thus, we can instead have
__cpu_setup() initialize GCR_EL1 to a value consistent with
KASAN_TAG_MAX, and avoid the need to re-initialize it during hotplug and
resume form suspend.
This patch makes arem64 use a compile-time constant KERNEL_GCR_EL1
value, which is compatible with KASAN_HW_TAGS when this is selected.
This removes the need to re-initialize GCR_EL1 dynamically, and acts as
an optimization to the entry assembly, which no longer needs to load
this value from memory. The redundant initialization hooks are removed.
In order to do this, KASAN_TAG_MAX needs to be visible outside of the
core KASAN code. To do this, I've moved the KASAN_TAG_* values into
<linux/kasan-tags.h>.
There should be no functional change as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Peter Collingbourne <pcc@google.com>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Tested-by: Andrey Konovalov <andreyknvl@gmail.com>
Link: https://lore.kernel.org/r/20210714143843.56537-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-07-14 15:38:42 +01:00
mov x10 , #K E R N E L _ G C R _ E L 1
2019-09-06 10:58:01 +01:00
msr_ s S Y S _ G C R _ E L 1 , x10
2021-05-07 11:59:05 -07:00
/ *
* If G C R _ E L 1 . R R N D =1 i s i m p l e m e n t e d t h e s a m e w a y a s R R N D =0 , t h e n
* RGSR_ E L 1 . S E E D m u s t b e n o n - z e r o f o r I R G t o p r o d u c e
* pseudorandom n u m b e r s . A s R G S R _ E L 1 i s U N K N O W N o u t o f r e s e t , w e
* must i n i t i a l i z e i t .
* /
mrs x10 , C N T V C T _ E L 0
ands x10 , x10 , #S Y S _ R G S R _ E L 1 _ S E E D _ M A S K
csinc x10 , x10 , x z r , n e
lsl x10 , x10 , #S Y S _ R G S R _ E L 1 _ S E E D _ S H I F T
msr_ s S Y S _ R G S R _ E L 1 , x10
2019-09-06 10:58:01 +01:00
/* clear any pending tag check faults in TFSR*_EL1 */
msr_ s S Y S _ T F S R _ E L 1 , x z r
msr_ s S Y S _ T F S R E 0 _ E L 1 , x z r
2020-12-22 12:01:38 -08:00
/* set the TCR_EL1 bits */
2021-06-02 16:52:29 -07:00
mov_ q x10 , T C R _ M T E _ F L A G S
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
orr t c r , t c r , x10
2019-09-06 10:58:01 +01:00
1 :
# endif
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
tcr_ c l e a r _ e r r a t a _ b i t s t c r , x9 , x5
2018-12-06 22:50:41 +00:00
2019-08-07 16:55:22 +01:00
# ifdef C O N F I G _ A R M 6 4 _ V A _ B I T S _ 5 2
2022-07-01 13:10:45 +02:00
sub x9 , x z r , x0
2018-12-06 22:50:41 +00:00
add x9 , x9 , #64
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
tcr_ s e t _ t 1 s z t c r , x9
2018-12-06 22:50:41 +00:00
# else
2022-06-24 17:06:33 +02:00
idmap_ g e t _ t 0 s z x9
2018-12-06 22:50:41 +00:00
# endif
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
tcr_ s e t _ t 0 s z t c r , 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-19 16:42:27 +00:00
2014-03-07 08:49:25 +00:00
/ *
2017-12-13 17:07:17 +00:00
* Set t h e I P S b i t s i n T C R _ E L 1 .
2014-03-07 08:49:25 +00:00
* /
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
tcr_ c o m p u t e _ p a _ s i z e t c r , #T C R _ I P S _ S H I F T , x 5 , x6
2015-07-10 17:24:28 +01:00
# ifdef C O N F I G _ A R M 6 4 _ H W _ A F D B M
/ *
2018-03-26 15:12:48 +01:00
* Enable h a r d w a r e u p d a t e o f t h e A c c e s s F l a g s b i t .
* Hardware d i r t y b i t m a n a g e m e n t i s e n a b l e d l a t e r ,
* via c a p a b i l i t i e s .
2015-07-10 17:24:28 +01:00
* /
mrs x9 , I D _ A A 6 4 M M F R 1 _ E L 1
and x9 , x9 , #0xf
2018-03-26 15:12:48 +01:00
cbz x9 , 1 f
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
orr t c r , t c r , #T C R _ H A / / h a r d w a r e A c c e s s f l a g u p d a t e
2018-03-26 15:12:48 +01:00
1 :
2015-07-10 17:24:28 +01:00
# endif / * C O N F I G _ A R M 6 4 _ H W _ A F D B M * /
2021-03-26 18:01:36 +00:00
msr m a i r _ e l 1 , m a i r
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
msr t c r _ e l 1 , t c r
2020-03-13 14:34:52 +05:30
/ *
* Prepare S C T L R
* /
2020-11-13 12:49:24 +00:00
mov_ q x0 , I N I T _ S C T L R _ E L 1 _ M M U _ O N
2012-03-05 11:49:28 +00:00
ret / / r e t u r n t o h e a d . S
2021-03-26 18:01:36 +00:00
.unreq mair
arm64: setup: name `tcr` register
In __cpu_setup we conditionally manipulate the TCR_EL1 value in x10
after previously using x10 as a scratch register for unrelated temporary
variables.
To make this a bit clearer, let's move the TCR_EL1 value into a named
register `tcr`. To simplify the register allocation, this is placed in
the highest available caller-saved scratch register, tcr.
Following the example of `mair`, we initialise the register with the
default value prior to any feature discovery, and write it to MAIR_EL1
after all feature discovery is complete, which allows us to simplify the
featuere discovery code.
The existing `mte_tcr` register is no longer needed, and is replaced by
the use of x10 as a temporary, matching the rest of the MTE feature
discovery assembly in __cpu_setup. As x20 is no longer used, the
function is now AAPCS compliant, as we've generally aimed for in our
assembly functions.
There should be no functional change as as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210326180137.43119-3-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2021-03-26 18:01:37 +00:00
.unreq tcr
2020-01-06 19:58:18 +00:00
SYM_ F U N C _ E N D ( _ _ c p u _ s e t u p )