2012-03-05 11:49:26 +00:00
|
|
|
/*
|
2016-04-27 16:47:00 +00:00
|
|
|
* Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S
|
2012-03-05 11:49:26 +00:00
|
|
|
*
|
|
|
|
* Copyright (C) 1996-2000 Russell King
|
|
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#error "Only include this from assembly code"
|
|
|
|
#endif
|
|
|
|
|
2015-02-20 13:53:13 +00:00
|
|
|
#ifndef __ASM_ASSEMBLER_H
|
|
|
|
#define __ASM_ASSEMBLER_H
|
|
|
|
|
2016-04-27 16:47:00 +00:00
|
|
|
#include <asm/asm-offsets.h>
|
2016-06-28 17:07:29 +00:00
|
|
|
#include <asm/cpufeature.h>
|
2017-10-25 09:04:32 +00:00
|
|
|
#include <asm/debug-monitors.h>
|
2017-02-08 20:08:37 +00:00
|
|
|
#include <asm/mmu_context.h>
|
2016-04-27 16:47:10 +00:00
|
|
|
#include <asm/page.h>
|
2016-04-27 16:47:00 +00:00
|
|
|
#include <asm/pgtable-hwdef.h>
|
2012-03-05 11:49:26 +00:00
|
|
|
#include <asm/ptrace.h>
|
arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
- Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
avoid disabling step in the MDSCR when we don't need to.
MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
userspace.
- Ensure debug exceptions are re-enabled on *all* exception entry
paths, even the debug exception handling path (where we re-enable
exceptions after invoking the handler). Since we can now rely on
MDSCR_EL1.SS being cleared by the entry code, exception handlers can
usually enable debug immediately before enabling interrupts.
- Remove all debug exception unmasking from ret_to_user and
el1_preempt, since we will never get here with debug exceptions
masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2014-04-29 18:04:06 +00:00
|
|
|
#include <asm/thread_info.h>
|
2012-03-05 11:49:26 +00:00
|
|
|
|
2017-11-02 12:12:34 +00:00
|
|
|
.macro save_and_disable_daif, flags
|
|
|
|
mrs \flags, daif
|
|
|
|
msr daifset, #0xf
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro disable_daif
|
|
|
|
msr daifset, #0xf
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro enable_daif
|
|
|
|
msr daifclr, #0xf
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro restore_daif, flags:req
|
|
|
|
msr daif, \flags
|
|
|
|
.endm
|
|
|
|
|
2017-11-02 12:12:39 +00:00
|
|
|
/* Only on aarch64 pstate, PSR_D_BIT is different for aarch32 */
|
|
|
|
.macro inherit_daif, pstate:req, tmp:req
|
|
|
|
and \tmp, \pstate, #(PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
|
|
|
|
msr daif, \tmp
|
|
|
|
.endm
|
|
|
|
|
2017-11-02 12:12:41 +00:00
|
|
|
/* IRQ is the lowest priority flag, unconditionally unmask the rest. */
|
|
|
|
.macro enable_da_f
|
|
|
|
msr daifclr, #(8 | 4 | 1)
|
|
|
|
.endm
|
|
|
|
|
2012-03-05 11:49:26 +00:00
|
|
|
/*
|
|
|
|
* Enable and disable interrupts.
|
|
|
|
*/
|
|
|
|
.macro disable_irq
|
|
|
|
msr daifset, #2
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro enable_irq
|
|
|
|
msr daifclr, #2
|
|
|
|
.endm
|
|
|
|
|
2016-07-01 15:53:00 +00:00
|
|
|
.macro save_and_disable_irq, flags
|
|
|
|
mrs \flags, daif
|
|
|
|
msr daifset, #2
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro restore_irq, flags
|
|
|
|
msr daif, \flags
|
|
|
|
.endm
|
|
|
|
|
2012-03-05 11:49:26 +00:00
|
|
|
.macro enable_dbg
|
|
|
|
msr daifclr, #8
|
|
|
|
.endm
|
|
|
|
|
arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
- Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
avoid disabling step in the MDSCR when we don't need to.
MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
userspace.
- Ensure debug exceptions are re-enabled on *all* exception entry
paths, even the debug exception handling path (where we re-enable
exceptions after invoking the handler). Since we can now rely on
MDSCR_EL1.SS being cleared by the entry code, exception handlers can
usually enable debug immediately before enabling interrupts.
- Remove all debug exception unmasking from ret_to_user and
el1_preempt, since we will never get here with debug exceptions
masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2014-04-29 18:04:06 +00:00
|
|
|
.macro disable_step_tsk, flgs, tmp
|
|
|
|
tbz \flgs, #TIF_SINGLESTEP, 9990f
|
2012-03-05 11:49:26 +00:00
|
|
|
mrs \tmp, mdscr_el1
|
2017-10-25 09:04:32 +00:00
|
|
|
bic \tmp, \tmp, #DBG_MDSCR_SS
|
2012-03-05 11:49:26 +00:00
|
|
|
msr mdscr_el1, \tmp
|
arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
- Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
avoid disabling step in the MDSCR when we don't need to.
MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
userspace.
- Ensure debug exceptions are re-enabled on *all* exception entry
paths, even the debug exception handling path (where we re-enable
exceptions after invoking the handler). Since we can now rely on
MDSCR_EL1.SS being cleared by the entry code, exception handlers can
usually enable debug immediately before enabling interrupts.
- Remove all debug exception unmasking from ret_to_user and
el1_preempt, since we will never get here with debug exceptions
masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2014-04-29 18:04:06 +00:00
|
|
|
isb // Synchronise with enable_dbg
|
|
|
|
9990:
|
2012-03-05 11:49:26 +00:00
|
|
|
.endm
|
|
|
|
|
2017-11-02 12:12:38 +00:00
|
|
|
/* call with daif masked */
|
arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
- Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
avoid disabling step in the MDSCR when we don't need to.
MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
userspace.
- Ensure debug exceptions are re-enabled on *all* exception entry
paths, even the debug exception handling path (where we re-enable
exceptions after invoking the handler). Since we can now rely on
MDSCR_EL1.SS being cleared by the entry code, exception handlers can
usually enable debug immediately before enabling interrupts.
- Remove all debug exception unmasking from ret_to_user and
el1_preempt, since we will never get here with debug exceptions
masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2014-04-29 18:04:06 +00:00
|
|
|
.macro enable_step_tsk, flgs, tmp
|
|
|
|
tbz \flgs, #TIF_SINGLESTEP, 9990f
|
2012-03-05 11:49:26 +00:00
|
|
|
mrs \tmp, mdscr_el1
|
2017-10-25 09:04:32 +00:00
|
|
|
orr \tmp, \tmp, #DBG_MDSCR_SS
|
2012-03-05 11:49:26 +00:00
|
|
|
msr mdscr_el1, \tmp
|
arm64: debug: avoid accessing mdscr_el1 on fault paths where possible
Since mdscr_el1 is part of the debug register group, it is highly likely
to be trapped by a hypervisor to prevent virtual machines from debugging
(buggering?) each other. Unfortunately, this absolutely destroys our
performance, since we access the register on many of our low-level
fault handling paths to keep track of the various debug state machines.
This patch removes our dependency on mdscr_el1 in the case that debugging
is not being used. More specifically we:
- Use TIF_SINGLESTEP to indicate that a task is stepping at EL0 and
avoid disabling step in the MDSCR when we don't need to.
MDSCR_EL1.SS handling is moved to kernel_entry, when trapping from
userspace.
- Ensure debug exceptions are re-enabled on *all* exception entry
paths, even the debug exception handling path (where we re-enable
exceptions after invoking the handler). Since we can now rely on
MDSCR_EL1.SS being cleared by the entry code, exception handlers can
usually enable debug immediately before enabling interrupts.
- Remove all debug exception unmasking from ret_to_user and
el1_preempt, since we will never get here with debug exceptions
masked.
This results in a slight change to kernel debug behaviour, where we now
step into interrupt handlers and data aborts from EL1 when debugging the
kernel, which is actually a useful thing to do. A side-effect of this is
that it *does* potentially prevent stepping off {break,watch}points when
there is a high-frequency interrupt source (e.g. a timer), so a debugger
would need to use either breakpoints or manually disable interrupts to
get around this issue.
With this patch applied, guest performance is restored under KVM when
debug register accesses are trapped (and we get a measurable performance
increase on the host on Cortex-A57 too).
Cc: Ian Campbell <ian.campbell@citrix.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2014-04-29 18:04:06 +00:00
|
|
|
9990:
|
2012-03-05 11:49:26 +00:00
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SMP data memory barrier
|
|
|
|
*/
|
|
|
|
.macro smp_dmb, opt
|
|
|
|
dmb \opt
|
|
|
|
.endm
|
|
|
|
|
2016-09-06 15:40:23 +00:00
|
|
|
/*
|
|
|
|
* NOP sequence
|
|
|
|
*/
|
|
|
|
.macro nops, num
|
|
|
|
.rept \num
|
|
|
|
nop
|
|
|
|
.endr
|
|
|
|
.endm
|
|
|
|
|
2016-01-01 14:02:12 +00:00
|
|
|
/*
|
|
|
|
* Emit an entry into the exception table
|
|
|
|
*/
|
|
|
|
.macro _asm_extable, from, to
|
|
|
|
.pushsection __ex_table, "a"
|
|
|
|
.align 3
|
|
|
|
.long (\from - .), (\to - .)
|
|
|
|
.popsection
|
|
|
|
.endm
|
|
|
|
|
2012-03-05 11:49:26 +00:00
|
|
|
#define USER(l, x...) \
|
|
|
|
9999: x; \
|
2016-01-01 14:02:12 +00:00
|
|
|
_asm_extable 9999b, l
|
2012-03-05 11:49:26 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Register aliases.
|
|
|
|
*/
|
|
|
|
lr .req x30 // link register
|
2012-10-19 16:37:35 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Vector entry
|
|
|
|
*/
|
|
|
|
.macro ventry label
|
|
|
|
.align 7
|
|
|
|
b \label
|
|
|
|
.endm
|
2013-10-11 13:52:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Select code when configured for BE.
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_CPU_BIG_ENDIAN
|
|
|
|
#define CPU_BE(code...) code
|
|
|
|
#else
|
|
|
|
#define CPU_BE(code...)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Select code when configured for LE.
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_CPU_BIG_ENDIAN
|
|
|
|
#define CPU_LE(code...)
|
|
|
|
#else
|
|
|
|
#define CPU_LE(code...) code
|
|
|
|
#endif
|
|
|
|
|
2013-10-11 13:52:13 +00:00
|
|
|
/*
|
|
|
|
* Define a macro that constructs a 64-bit value by concatenating two
|
|
|
|
* 32-bit registers. Note that on big endian systems the order of the
|
|
|
|
* registers is swapped.
|
|
|
|
*/
|
|
|
|
#ifndef CONFIG_CPU_BIG_ENDIAN
|
|
|
|
.macro regs_to_64, rd, lbits, hbits
|
|
|
|
#else
|
|
|
|
.macro regs_to_64, rd, hbits, lbits
|
|
|
|
#endif
|
|
|
|
orr \rd, \lbits, \hbits, lsl #32
|
|
|
|
.endm
|
2015-02-20 13:53:13 +00:00
|
|
|
|
2015-03-04 18:45:38 +00:00
|
|
|
/*
|
|
|
|
* Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
|
2017-01-11 14:54:53 +00:00
|
|
|
* <symbol> is within the range +/- 4 GB of the PC when running
|
|
|
|
* in core kernel context. In module context, a movz/movk sequence
|
|
|
|
* is used, since modules may be loaded far away from the kernel
|
|
|
|
* when KASLR is in effect.
|
2015-03-04 18:45:38 +00:00
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* @dst: destination register (64 bit wide)
|
|
|
|
* @sym: name of the symbol
|
|
|
|
*/
|
2017-01-11 14:54:53 +00:00
|
|
|
.macro adr_l, dst, sym
|
|
|
|
#ifndef MODULE
|
2015-03-04 18:45:38 +00:00
|
|
|
adrp \dst, \sym
|
|
|
|
add \dst, \dst, :lo12:\sym
|
2017-01-11 14:54:53 +00:00
|
|
|
#else
|
|
|
|
movz \dst, #:abs_g3:\sym
|
|
|
|
movk \dst, #:abs_g2_nc:\sym
|
|
|
|
movk \dst, #:abs_g1_nc:\sym
|
|
|
|
movk \dst, #:abs_g0_nc:\sym
|
|
|
|
#endif
|
2015-03-04 18:45:38 +00:00
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @dst: destination register (32 or 64 bit wide)
|
|
|
|
* @sym: name of the symbol
|
|
|
|
* @tmp: optional 64-bit scratch register to be used if <dst> is a
|
|
|
|
* 32-bit wide register, in which case it cannot be used to hold
|
|
|
|
* the address
|
|
|
|
*/
|
|
|
|
.macro ldr_l, dst, sym, tmp=
|
2017-01-11 14:54:53 +00:00
|
|
|
#ifndef MODULE
|
2015-03-04 18:45:38 +00:00
|
|
|
.ifb \tmp
|
|
|
|
adrp \dst, \sym
|
|
|
|
ldr \dst, [\dst, :lo12:\sym]
|
|
|
|
.else
|
|
|
|
adrp \tmp, \sym
|
|
|
|
ldr \dst, [\tmp, :lo12:\sym]
|
|
|
|
.endif
|
2017-01-11 14:54:53 +00:00
|
|
|
#else
|
|
|
|
.ifb \tmp
|
|
|
|
adr_l \dst, \sym
|
|
|
|
ldr \dst, [\dst]
|
|
|
|
.else
|
|
|
|
adr_l \tmp, \sym
|
|
|
|
ldr \dst, [\tmp]
|
|
|
|
.endif
|
|
|
|
#endif
|
2015-03-04 18:45:38 +00:00
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @src: source register (32 or 64 bit wide)
|
|
|
|
* @sym: name of the symbol
|
|
|
|
* @tmp: mandatory 64-bit scratch register to calculate the address
|
|
|
|
* while <src> needs to be preserved.
|
|
|
|
*/
|
|
|
|
.macro str_l, src, sym, tmp
|
2017-01-11 14:54:53 +00:00
|
|
|
#ifndef MODULE
|
2015-03-04 18:45:38 +00:00
|
|
|
adrp \tmp, \sym
|
|
|
|
str \src, [\tmp, :lo12:\sym]
|
2017-01-11 14:54:53 +00:00
|
|
|
#else
|
|
|
|
adr_l \tmp, \sym
|
|
|
|
str \src, [\tmp]
|
|
|
|
#endif
|
2015-03-04 18:45:38 +00:00
|
|
|
.endm
|
|
|
|
|
2015-12-10 10:22:39 +00:00
|
|
|
/*
|
2017-07-15 16:23:13 +00:00
|
|
|
* @dst: Result of per_cpu(sym, smp_processor_id()), can be SP for
|
|
|
|
* non-module code
|
2015-12-10 10:22:39 +00:00
|
|
|
* @sym: The name of the per-cpu variable
|
|
|
|
* @tmp: scratch register
|
|
|
|
*/
|
2016-11-03 20:23:12 +00:00
|
|
|
.macro adr_this_cpu, dst, sym, tmp
|
2017-07-15 16:23:13 +00:00
|
|
|
#ifndef MODULE
|
|
|
|
adrp \tmp, \sym
|
|
|
|
add \dst, \tmp, #:lo12:\sym
|
|
|
|
#else
|
2016-11-03 20:23:12 +00:00
|
|
|
adr_l \dst, \sym
|
2017-07-15 16:23:13 +00:00
|
|
|
#endif
|
2015-12-10 10:22:39 +00:00
|
|
|
mrs \tmp, tpidr_el1
|
2016-11-03 20:23:12 +00:00
|
|
|
add \dst, \dst, \tmp
|
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id()))
|
|
|
|
* @sym: The name of the per-cpu variable
|
|
|
|
* @tmp: scratch register
|
|
|
|
*/
|
|
|
|
.macro ldr_this_cpu dst, sym, tmp
|
|
|
|
adr_l \dst, \sym
|
|
|
|
mrs \tmp, tpidr_el1
|
|
|
|
ldr \dst, [\dst, \tmp]
|
2015-12-10 10:22:39 +00:00
|
|
|
.endm
|
|
|
|
|
2016-04-27 16:47:00 +00:00
|
|
|
/*
|
|
|
|
* vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
|
|
|
|
*/
|
|
|
|
.macro vma_vm_mm, rd, rn
|
|
|
|
ldr \rd, [\rn, #VMA_VM_MM]
|
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* mmid - get context id from mm pointer (mm->context.id)
|
|
|
|
*/
|
|
|
|
.macro mmid, rd, rn
|
|
|
|
ldr \rd, [\rn, #MM_CONTEXT_ID]
|
|
|
|
.endm
|
2016-09-09 13:07:16 +00:00
|
|
|
/*
|
|
|
|
* read_ctr - read CTR_EL0. If the system has mismatched
|
|
|
|
* cache line sizes, provide the system wide safe value
|
|
|
|
* from arm64_ftr_reg_ctrel0.sys_val
|
|
|
|
*/
|
|
|
|
.macro read_ctr, reg
|
|
|
|
alternative_if_not ARM64_MISMATCHED_CACHE_LINE_SIZE
|
|
|
|
mrs \reg, ctr_el0 // read CTR
|
|
|
|
nop
|
|
|
|
alternative_else
|
|
|
|
ldr_l \reg, arm64_ftr_reg_ctrel0 + ARM64_FTR_SYSVAL
|
|
|
|
alternative_endif
|
|
|
|
.endm
|
|
|
|
|
2016-04-27 16:47:00 +00:00
|
|
|
|
|
|
|
/*
|
2016-09-09 13:07:14 +00:00
|
|
|
* raw_dcache_line_size - get the minimum D-cache line size on this CPU
|
|
|
|
* from the CTR register.
|
2016-04-27 16:47:00 +00:00
|
|
|
*/
|
2016-09-09 13:07:14 +00:00
|
|
|
.macro raw_dcache_line_size, reg, tmp
|
2016-04-27 16:47:00 +00:00
|
|
|
mrs \tmp, ctr_el0 // read CTR
|
|
|
|
ubfm \tmp, \tmp, #16, #19 // cache line size encoding
|
|
|
|
mov \reg, #4 // bytes per word
|
|
|
|
lsl \reg, \reg, \tmp // actual cache line size
|
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
2016-09-09 13:07:14 +00:00
|
|
|
* dcache_line_size - get the safe D-cache line size across all CPUs
|
2016-04-27 16:47:00 +00:00
|
|
|
*/
|
2016-09-09 13:07:14 +00:00
|
|
|
.macro dcache_line_size, reg, tmp
|
2016-09-09 13:07:16 +00:00
|
|
|
read_ctr \tmp
|
|
|
|
ubfm \tmp, \tmp, #16, #19 // cache line size encoding
|
|
|
|
mov \reg, #4 // bytes per word
|
|
|
|
lsl \reg, \reg, \tmp // actual cache line size
|
2016-09-09 13:07:14 +00:00
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* raw_icache_line_size - get the minimum I-cache line size on this CPU
|
|
|
|
* from the CTR register.
|
|
|
|
*/
|
|
|
|
.macro raw_icache_line_size, reg, tmp
|
2016-04-27 16:47:00 +00:00
|
|
|
mrs \tmp, ctr_el0 // read CTR
|
|
|
|
and \tmp, \tmp, #0xf // cache line size encoding
|
|
|
|
mov \reg, #4 // bytes per word
|
|
|
|
lsl \reg, \reg, \tmp // actual cache line size
|
|
|
|
.endm
|
|
|
|
|
2016-09-09 13:07:14 +00:00
|
|
|
/*
|
|
|
|
* icache_line_size - get the safe I-cache line size across all CPUs
|
|
|
|
*/
|
|
|
|
.macro icache_line_size, reg, tmp
|
2016-09-09 13:07:16 +00:00
|
|
|
read_ctr \tmp
|
|
|
|
and \tmp, \tmp, #0xf // cache line size encoding
|
|
|
|
mov \reg, #4 // bytes per word
|
|
|
|
lsl \reg, \reg, \tmp // actual cache line size
|
2016-09-09 13:07:14 +00:00
|
|
|
.endm
|
|
|
|
|
2016-04-27 16:47:00 +00:00
|
|
|
/*
|
|
|
|
* tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map
|
|
|
|
*/
|
|
|
|
.macro tcr_set_idmap_t0sz, valreg, tmpreg
|
|
|
|
#ifndef CONFIG_ARM64_VA_BITS_48
|
|
|
|
ldr_l \tmpreg, idmap_t0sz
|
|
|
|
bfi \valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
|
|
|
|
#endif
|
|
|
|
.endm
|
|
|
|
|
2017-12-13 17:07:17 +00:00
|
|
|
/*
|
|
|
|
* tcr_compute_pa_size - set TCR.(I)PS to the highest supported
|
|
|
|
* ID_AA64MMFR0_EL1.PARange value
|
|
|
|
*
|
|
|
|
* tcr: register with the TCR_ELx value to be updated
|
|
|
|
* pos: PARange bitfield position
|
|
|
|
* tmp{0,1}: temporary registers
|
|
|
|
*/
|
|
|
|
.macro tcr_compute_pa_size, tcr, pos, tmp0, tmp1
|
|
|
|
mrs \tmp0, ID_AA64MMFR0_EL1
|
|
|
|
// Narrow PARange to fit the PS field in TCR_ELx
|
|
|
|
ubfx \tmp0, \tmp0, #ID_AA64MMFR0_PARANGE_SHIFT, #3
|
|
|
|
mov \tmp1, #ID_AA64MMFR0_PARANGE_MAX
|
|
|
|
cmp \tmp0, \tmp1
|
|
|
|
csel \tmp0, \tmp1, \tmp0, hi
|
|
|
|
bfi \tcr, \tmp0, \pos, #3
|
|
|
|
.endm
|
|
|
|
|
2016-04-27 16:47:00 +00:00
|
|
|
/*
|
|
|
|
* Macro to perform a data cache maintenance for the interval
|
|
|
|
* [kaddr, kaddr + size)
|
|
|
|
*
|
|
|
|
* op: operation passed to dc instruction
|
|
|
|
* domain: domain used in dsb instruciton
|
|
|
|
* kaddr: starting virtual address of the region
|
|
|
|
* size: size of the region
|
|
|
|
* Corrupts: kaddr, size, tmp1, tmp2
|
|
|
|
*/
|
|
|
|
.macro dcache_by_line_op op, domain, kaddr, size, tmp1, tmp2
|
|
|
|
dcache_line_size \tmp1, \tmp2
|
|
|
|
add \size, \kaddr, \size
|
|
|
|
sub \tmp2, \tmp1, #1
|
|
|
|
bic \kaddr, \kaddr, \tmp2
|
2016-06-28 17:07:29 +00:00
|
|
|
9998:
|
|
|
|
.if (\op == cvau || \op == cvac)
|
|
|
|
alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
|
|
|
|
dc \op, \kaddr
|
|
|
|
alternative_else
|
|
|
|
dc civac, \kaddr
|
2017-07-25 10:55:42 +00:00
|
|
|
alternative_endif
|
|
|
|
.elseif (\op == cvap)
|
|
|
|
alternative_if ARM64_HAS_DCPOP
|
|
|
|
sys 3, c7, c12, 1, \kaddr // dc cvap
|
|
|
|
alternative_else
|
|
|
|
dc cvac, \kaddr
|
2016-06-28 17:07:29 +00:00
|
|
|
alternative_endif
|
|
|
|
.else
|
|
|
|
dc \op, \kaddr
|
|
|
|
.endif
|
2016-04-27 16:47:00 +00:00
|
|
|
add \kaddr, \kaddr, \tmp1
|
|
|
|
cmp \kaddr, \size
|
|
|
|
b.lo 9998b
|
|
|
|
dsb \domain
|
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present
|
|
|
|
*/
|
|
|
|
.macro reset_pmuserenr_el0, tmpreg
|
|
|
|
mrs \tmpreg, id_aa64dfr0_el1 // Check ID_AA64DFR0_EL1 PMUVer
|
|
|
|
sbfx \tmpreg, \tmpreg, #8, #4
|
|
|
|
cmp \tmpreg, #1 // Skip if no PMU present
|
|
|
|
b.lt 9000f
|
|
|
|
msr pmuserenr_el0, xzr // Disable PMU access from EL0
|
|
|
|
9000:
|
|
|
|
.endm
|
|
|
|
|
2016-04-27 16:47:10 +00:00
|
|
|
/*
|
|
|
|
* copy_page - copy src to dest using temp registers t1-t8
|
|
|
|
*/
|
|
|
|
.macro copy_page dest:req src:req t1:req t2:req t3:req t4:req t5:req t6:req t7:req t8:req
|
|
|
|
9998: ldp \t1, \t2, [\src]
|
|
|
|
ldp \t3, \t4, [\src, #16]
|
|
|
|
ldp \t5, \t6, [\src, #32]
|
|
|
|
ldp \t7, \t8, [\src, #48]
|
|
|
|
add \src, \src, #64
|
|
|
|
stnp \t1, \t2, [\dest]
|
|
|
|
stnp \t3, \t4, [\dest, #16]
|
|
|
|
stnp \t5, \t6, [\dest, #32]
|
|
|
|
stnp \t7, \t8, [\dest, #48]
|
|
|
|
add \dest, \dest, #64
|
|
|
|
tst \src, #(PAGE_SIZE - 1)
|
|
|
|
b.ne 9998b
|
|
|
|
.endm
|
|
|
|
|
2015-10-08 19:02:03 +00:00
|
|
|
/*
|
|
|
|
* Annotate a function as position independent, i.e., safe to be called before
|
|
|
|
* the kernel virtual mapping is activated.
|
|
|
|
*/
|
|
|
|
#define ENDPIPROC(x) \
|
|
|
|
.globl __pi_##x; \
|
|
|
|
.type __pi_##x, %function; \
|
|
|
|
.set __pi_##x, x; \
|
|
|
|
.size __pi_##x, . - x; \
|
|
|
|
ENDPROC(x)
|
|
|
|
|
2017-07-26 15:05:20 +00:00
|
|
|
/*
|
|
|
|
* Annotate a function as being unsuitable for kprobes.
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_KPROBES
|
|
|
|
#define NOKPROBE(x) \
|
|
|
|
.pushsection "_kprobe_blacklist", "aw"; \
|
|
|
|
.quad x; \
|
|
|
|
.popsection;
|
|
|
|
#else
|
|
|
|
#define NOKPROBE(x)
|
|
|
|
#endif
|
2015-12-26 12:48:02 +00:00
|
|
|
/*
|
|
|
|
* Emit a 64-bit absolute little endian symbol reference in a way that
|
|
|
|
* ensures that it will be resolved at build time, even when building a
|
|
|
|
* PIE binary. This requires cooperation from the linker script, which
|
|
|
|
* must emit the lo32/hi32 halves individually.
|
|
|
|
*/
|
|
|
|
.macro le64sym, sym
|
|
|
|
.long \sym\()_lo32
|
|
|
|
.long \sym\()_hi32
|
|
|
|
.endm
|
|
|
|
|
2016-04-18 15:09:44 +00:00
|
|
|
/*
|
|
|
|
* mov_q - move an immediate constant into a 64-bit register using
|
|
|
|
* between 2 and 4 movz/movk instructions (depending on the
|
|
|
|
* magnitude and sign of the operand)
|
|
|
|
*/
|
|
|
|
.macro mov_q, reg, val
|
|
|
|
.if (((\val) >> 31) == 0 || ((\val) >> 31) == 0x1ffffffff)
|
|
|
|
movz \reg, :abs_g1_s:\val
|
|
|
|
.else
|
|
|
|
.if (((\val) >> 47) == 0 || ((\val) >> 47) == 0x1ffff)
|
|
|
|
movz \reg, :abs_g2_s:\val
|
|
|
|
.else
|
|
|
|
movz \reg, :abs_g3:\val
|
|
|
|
movk \reg, :abs_g2_nc:\val
|
|
|
|
.endif
|
|
|
|
movk \reg, :abs_g1_nc:\val
|
|
|
|
.endif
|
|
|
|
movk \reg, :abs_g0_nc:\val
|
|
|
|
.endm
|
|
|
|
|
2016-07-01 15:53:00 +00:00
|
|
|
/*
|
|
|
|
* Return the current thread_info.
|
|
|
|
*/
|
|
|
|
.macro get_thread_info, rd
|
|
|
|
mrs \rd, sp_el0
|
|
|
|
.endm
|
|
|
|
|
2017-02-08 20:08:37 +00:00
|
|
|
/*
|
|
|
|
* Errata workaround prior to TTBR0_EL1 update
|
|
|
|
*
|
|
|
|
* val: TTBR value with new BADDR, preserved
|
|
|
|
* tmp0: temporary register, clobbered
|
|
|
|
* tmp1: other temporary register, clobbered
|
|
|
|
*/
|
|
|
|
.macro pre_ttbr0_update_workaround, val, tmp0, tmp1
|
|
|
|
#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
|
|
|
|
alternative_if ARM64_WORKAROUND_QCOM_FALKOR_E1003
|
|
|
|
mrs \tmp0, ttbr0_el1
|
|
|
|
mov \tmp1, #FALKOR_RESERVED_ASID
|
|
|
|
bfi \tmp0, \tmp1, #48, #16 // reserved ASID + old BADDR
|
|
|
|
msr ttbr0_el1, \tmp0
|
|
|
|
isb
|
|
|
|
bfi \tmp0, \val, #0, #48 // reserved ASID + new BADDR
|
|
|
|
msr ttbr0_el1, \tmp0
|
|
|
|
isb
|
|
|
|
alternative_else_nop_endif
|
|
|
|
#endif
|
|
|
|
.endm
|
|
|
|
|
2016-07-01 14:48:55 +00:00
|
|
|
/*
|
|
|
|
* Errata workaround post TTBR0_EL1 update.
|
|
|
|
*/
|
|
|
|
.macro post_ttbr0_update_workaround
|
|
|
|
#ifdef CONFIG_CAVIUM_ERRATUM_27456
|
|
|
|
alternative_if ARM64_WORKAROUND_CAVIUM_27456
|
|
|
|
ic iallu
|
|
|
|
dsb nsh
|
|
|
|
isb
|
|
|
|
alternative_else_nop_endif
|
|
|
|
#endif
|
|
|
|
.endm
|
|
|
|
|
2015-02-20 13:53:13 +00:00
|
|
|
#endif /* __ASM_ASSEMBLER_H */
|