History log of /freebsd-current/sys/arm64/arm64/swtch.S
Revision Date Author Comments
# c2e0d56f 04-Jun-2024 Andrew Turner <andrew@FreeBSD.org>

arm64: Support BTI checking in most of the kernel

LLD has the -zbti-report=error argument to check if the BTI note is
present when linking. To allow for this to be used when linking the
kernel and modules:
- Add the BTI note to the remaining assembly files
- Mark ptrauth.c as protected by BTI
- Disable -zbti-report for vmm hypervisor switching code as it's not
used there.

The linux64 module doesn't build with the flag as it includes vdso code
that doesn't include the note.

Reviewed by: imp, kib, emaste
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D45466


# 12257233 03-Jan-2024 Andrew Turner <andrew@FreeBSD.org>

arm64: Split out a savectx version of vfp_save_state

Rather than try to detect when vfp_save_state is called by savectx use
a separate function that sets up the pcb as needed.

Reviewed by: imp
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D43304


# 685dc743 16-Aug-2023 Warner Losh <imp@FreeBSD.org>

sys: Remove $FreeBSD$: one-line .c pattern

Remove /^[\s*]*__FBSDID\("\$FreeBSD\$"\);?\s*\n/


# ec1bc530 26-Mar-2023 Kyle Evans <kevans@FreeBSD.org>

arm64: cpu_switch: don't zero out pcb_onfault

Previously this would zero out x18 in the pcb, now it's attacking the
innocent pcb_onfault -- drop it entirely.

This technically fixes
e605b87a9e7 ("Save only callee-saved registers in pcb"), but it's
harmless until the below commit trims down pcb_x.

Reported by: mmel
Reviewed by: andrew, mmel
Fixes: 1c1f31a5e517 ("Remove unused registes from the arm pcb")
Differential Revision: https://reviews.freebsd.org/D39277


# 787bf3bc 22-Mar-2023 Andrew Turner <andrew@FreeBSD.org>

arm64: Use the new PCB macros in swtch.S

Rather than hard coding the location of these registers in the array
use the new macros to find the correct offset.

Sponsored by: Arm Ltd


# 03bf40c5 07-Nov-2022 Mark Johnston <markj@FreeBSD.org>

arm64: Disable per-thread stack-smashing protection in data_abort()

With PERTHREAD_SSP configured, the compiler's stack-smashing protection
uses a per-thread canary value instead of a global value. The value is
stored in td->td_md.md_canary; the sp_el0 register always contains a
pointer to that value, and certain functions selected by the compiler
will store the canary value on the stack as a part of the function
prologue (and will verify the copy as part of the epilogue). In
particular, the thread structure may be accessed.

This happens to occur in data_abort(), which leads to the same problem
addressed by commit 2c10be9e06d4 ("arm64: Handle translation faults for
thread structures"). This commit fixes that directly, by disabling SSP
in data_abort() and a couple of related functions by using a function
attribute. It also moves the update of sp_el0 out of C code in case
the compiler decides to start checking the canary in pmap_switch()
someday.

A different solution might be to move the canary value to the PCB, which
currently lives on the kernel stack and isn't subject to the same
problem as thread structures (if only because guard pages inhibit
superpage promotion). However, there isn't any particular reason the
PCB has to live on the stack today; on amd64 it is embedded in struct
thread, reintroducing the same problem. Keeping the reference canary
value at the top of the stack is also rather dubious since it could be
clobbered by a sufficiently large stack overflow.

A third solution could be to go back to the approach of commit
5aa5420ff2e8, and modify UMA to use the direct map for thread structures
even if KASAN is enabled. But, transient promotions and demotions in
the direct map are possible too.

Reviewed by: alc, kib, andrew
MFC after: 1 month
Sponsored by: Juniper Networks, Inc.
Sponsored by: Klara, Inc.
Differential Revision: https://reviews.freebsd.org/D37255


# e605b87a 25-May-2022 Dapeng Gao <peter@dpgao.cc>

Save only callee-saved registers in pcb

On AArch64, registers x9-x18 are not callee-saved, yet they are
preserved at many placed in swtch.S. This patch removes code that
preserves these registers.


# 664640ba 26-Jan-2022 Andrew Turner <andrew@FreeBSD.org>

Sort the names of the arm64 debug registers

While here clean up the names for the naming convention of the other
registers in this file.

Reviewed by: kib, mhorne (earlier version)
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D34060


# 85b7c566 08-Jul-2021 Andrew Turner <andrew@FreeBSD.org>

Add arm64 pointer authentication support

Pointer authentication allows userspace to add instructions to insert
a Pointer Authentication Code (PAC) into a register based on an address
and modifier and check if the PAC is correct. If the check fails it will
either return an invalid address or fault to the kernel.

As many of these instructions are a NOP when disabled and in earlier
revisions of the architecture this can be used, for example, to sign
the return address before pushing it to the stack making Return-oriented
programming (ROP) attack more difficult on hardware that supports them.

The kernel manages five 128 bit signing keys: 2 instruction keys, 2 data
keys, and a generic key. The instructions then use one of these when
signing the registers. Instructions that use the first four store the
PAC in the register being signed, however the instructions that use the
generic key store the PAC in a separate register.

Currently all userspace threads share all the keys within a process
with a new set of userspace keys being generated when executing a new
process. This means a forked child will share its keys with its parent
until it calls an appropriate exec system call.

In the kernel we allow the use of one of the instruction keys, the ia
key. This will be used to sign return addresses in function calls.
Unlike userspace each kernel thread has its own randomly generated.

Thread0 has a static key as does the early code on secondary CPUs.
This should be safe as there is minimal user interaction with these
threads, however we could generate random keys when the Armv8.5
Random number generation instructions are present.

Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31261


# 267d55fa 08-Aug-2021 Andrew Turner <andrew@FreeBSD.org>

Remove an unused arm64 panic string

This was added early in the development of the arm64 port when
cpu_switch was just a stub. It should have been removed when cpu_switch
was implemented, however this didn't seem to be the case, and the '%p'
was added.

As this hasn't been needed in 7 years we can remove it.

Sponsored by: The FreeBSD Foundation


# 337eb2ab 03-Aug-2021 Andrew Turner <andrew@FreeBSD.org>

Add macros for the arm64 daifset/daifclr flags

Sponsored by: The FreeBSD Foundation


# 1791a628 09-Aug-2021 Andrew Turner <andrew@FreeBSD.org>

Clean up the arm64 fork_trampoline

When exiting to userspace the code is similar to the restore_registers
macro in exception.S. Rework it to remove most of the non-style
differences.

Sponsored by: The FreeBSD Foundation


# 5f66d5a3 20-Dec-2020 mhorne <mhorne@FreeBSD.org>

arm64: remove pcb_pc

The program counter field in the PCB is written in exactly one place,
makectx(), upon entry to the debugger. For threads other than curthread,
its value will be empty, or bogus. Rather than writing to this field in
more places, it can be removed in favor of using the value in the link
register.

To make this clearer, pcb->pcb_x[30] is renamed to pcb->pcb_lr, similar
to what already exists in struct trapframe. Also, prefer lr to x30 in
assembly, as it better conveys intention.

This improves PC_REGS() for kdb_thread != curthread. It is required for
a functional gdb(4) stub, fixing the output of `info threads`, in
particular.

The space occupied by pcb_pc is retained, for compatibility with kgdb.

Reviewed by: markj, jhb
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D27720


# 494278bb 19-Dec-2019 Andrew Turner <andrew@FreeBSD.org>

Stop speculation past an eret instruction

On arm64 the eret instruction is used to return from an exception handler.
Some implementations may speculate past this instruction into the next
function. As the user may control many registers in these functions add
a synchronisation barrier sequence after the eret instruction to stop these
CPUs from speculating out of the exception handler.

PR: 242676
Submitted by: Anthony Steinhauser <asteinhauser@google.com> (previous version)
MFC after: 1 week


# e403f986 01-Nov-2018 Andrew Turner <andrew@FreeBSD.org>

Use the correct offsets for the trap frame in fork_trampoline.

Sponsored by: DARPA, AFRL


# 8d59ab65 08-Jun-2018 Konstantin Belousov <kib@FreeBSD.org>

Restore release semantic for the old thread unlock on arm64.

With the introduction of pmap_switch(), the DSB instruction on the
address map switch is not necessary executed, which is fixed by
changing the unlock store to release. Also remove comment which
documented pre-pmap_switch() code.

Reviewed by: andrew
Sponsored by: The FreeBSD Foundation
MFC after: 1 week


# fc2a8776 20-Mar-2018 Ed Maste <emaste@FreeBSD.org>

Rename assym.s to assym.inc

assym is only to be included by other .s files, and should never
actually be assembled by itself.

Reviewed by: imp, bdrewery (earlier)
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D14180


# 45a91d45 08-Jan-2018 Andrew Turner <andrew@FreeBSD.org>

Move some of the common thread switching code into C. This will help with
future optimisations, e.g. using Address Space IDs (asid).

MFC after: 1 week
Sponsored by: DARPA, AFRL


# e8e65e28 22-Aug-2017 Andrew Turner <andrew@FreeBSD.org>

Fix a comment on uncommitted work.


# 6683b30c 22-Aug-2017 Andrew Turner <andrew@FreeBSD.org>

Move the l0 pagetable address to struct mdproc. It is a property of the
whole process so should live there.

Sponsored by: DARPA, AFRL


# cbf2160e 21-Aug-2017 Andrew Turner <andrew@FreeBSD.org>

Improve the performance of the arm64 thread switching code.

The full system memory barrier around a TLB invalidation is stricter than
required. It needs to wait on accesses to main memory, with just the weaker
store variant before the invalidate. As such use the dsb istst, tlbi, dlb
ish sequence already used in pmap.

The tlbi instruction in this sequence is also unnecessarily using a
broadcast invalidate when it just needs to invalidate the local CPUs TLB.
Switch to a non-broadcast variant of this instruction.

Sponsored by: DARPA, AFRL


# 9a19869a 09-Jun-2017 Andrew Turner <andrew@FreeBSD.org>

Store the read-only thread pointer when scheduling a new thread. This is
not currently set, however we may wish to set it later.


# 783b3676 15-Feb-2017 Andrew Turner <andrew@FreeBSD.org>

Load the new sp_el0 with interrupts disabled in fork_trampoline. If an
interrupt arrives in fork_trampoline after sp_el0 was written we may then
switch to a new thread, enter userland so change this stack pointer, then
return to this code with the wrong value. This fixes this case by moving
the load of sp_el0 until after interrupts have been disabled.

Reported by: Mark Millard (markmi@dsl-only.net)
Sponsored by: ABT Systems Ltd
Differential Revision: https://reviews.freebsd.org/D9593


# f2f21faf 31-Mar-2016 Andrew Turner <andrew@FreeBSD.org>

Add support for 4 level pagetables. The userland address space has been
increased to 256TiB. The kernel address space can also be increased to be
the same size, but this will be performed in a later change.

To help work with an extra level of page tables two new functions have
been added, one to file the lowest level table entry, and one to find the
block/page level. Both of these find the entry for a given pmap and virtual
address.

This has been tested with a combination of buildworld, stress2 tests, and
by using sort to consume a large amount of memory by sorting /dev/zero. No
new issues are known to be present from this change.

Reviewed by: kib
Obtained from: ABT Systems Ltd
Relnotes: yes
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D5720


# 770fd1c9 11-Feb-2016 Andrew Turner <andrew@FreeBSD.org>

Only update curthread and curpcb after we have finished using the old
values.

If switching from a thread that used floating-point registers to a thread
that is still running, but holding the blocked_lock lock we would switch
the curthread to the new (running) thread, then call critical_enter. This
will non-atomically increment td_critnest, and later call critical_exit to
non-atomically decrement this value.

This can happen at the same time as the new thread is still running on the
old core, also calling these functions. In this case there will be a race
between these non-atomic operations. This can be an issue as we could loose
one of these operations leading to the value to not return to zero.

If, later on, we then hit a data abort we check if the td_critnest is zero.
If this check fails we will panic the kernel.

This has been observed when running pcmstat on a Cavium ThunderX. The pcm
thread will use the blocked_lock lock and there is a high chance userspace
will use the floating-point registers. When, later on, pmcstat triggers a
data abort we will hit this panic.

The fix is to update these values after storing the floating-point state.
This means we use the correct curthread while storing the state so it will
not be an issue that the changes to td_critnest are non-atomic.

Sponsored by: ABT Systems Ltd


# d664515e 10-Feb-2016 Andrew Turner <andrew@FreeBSD.org>

Revert an arm64 change that sneaked in with r295464.


# 907fe116 10-Feb-2016 Andrew Turner <andrew@FreeBSD.org>

Update of the Allwinner drivers to:
* Use the Linux compat string
* Use EARLY_DRIVER_MODULE to attach at the right time
* Add a generic A10 kernel config file
* A20 now use generic_timer
* Add two new dts files for Olimex boards
* Update our custom DTS file for A10 and A20 to use the same compatible
property names as the vendor ones.

Submitted by: Emmanuel Vadot <manu@bidouilliste.com>
Differential Revision: https://reviews.freebsd.org/D4792


# 87e19994 02-Feb-2016 Andrew Turner <andrew@FreeBSD.org>

Implement single stepping on arm64. We need to set the single step bits in
the processor and debug state registers. A flag has been added to the pcb
to tell us when to enable single stepping for a given thread.

Reviewed by: kib
Sponsored by: ABT Systems Ltd
Differential Revision: https://reviews.freebsd.org/D4730


# 8eb447cc 27-Jan-2016 Wojciech Macek <wma@FreeBSD.org>

Fix mutex releasing in ARM64 cpu_switch

The code should be comparing pointers, not any data
gathered from a blocked_lock.

Spotted by: cognet
Approved by: zbb, cognet (mentor)
Differential revision: https://reviews.freebsd.org/D5100


# 0a21ab2c 07-Sep-2015 Andrew Turner <andrew@FreeBSD.org>

Use load-acquire semantics while waiting for td_lock to be released. The
store should have release semantics and will have due to the dsb above it
so add a comment to explain this. [1]

While here update the code to not reload the current thread, it's already
in a register, we just need to not trash it.

Suggested by: kib [1]
Sponsored by: ABT Systems Ltd


# f692e325 03-Aug-2015 Andrew Turner <andrew@FreeBSD.org>

Pass the pcb to store the vfp state in to vfp_save_state. This fixes a bug
in savectx where it will be used to store the current state however will
pass in a pcb when vfp_save_state expected a thread pointer.

Obtained from: ABT Systems Ltd
Sponsored by: The FreeBSD Foundation


# 721555e7 16-Jul-2015 Zbigniew Bodek <zbb@FreeBSD.org>

Fix KSTACK_PAGES issue when the default value was changed in KERNCONF

If KSTACK_PAGES was changed to anything alse than the default,
the value from param.h was taken instead in some places and
the value from KENRCONF in some others. This resulted in
inconsistency which caused corruption in SMP envorinment.

Ensure all places where KSTACK_PAGES are used the opt_kstack_pages.h
is included.

The file opt_kstack_pages.h could not be included in param.h
because was breaking the toolchain compilation.

Reviewed by: kib
Obtained from: Semihalf
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D3094


# b2b55077 09-Jul-2015 Andrew Turner <andrew@FreeBSD.org>

Add support for SMP. This uses the FDT data to find the CPUs to start on,
and psci to start them. I expect ACPI support to be added later.

This has been tested on qemu with 2 cpus as that is the current value of
MAXCPUS. This is expected to be increased in the future as FreeBSD has
been tested on 48 cores on the Cavium ThunderX hardware.

Partially based on a patch from Robin Randhawa from ARM.

Approved by: ABT Systems Ltd
Relnotes: yes
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D3024


# 80ad08a3 08-Jul-2015 Andrew Turner <andrew@FreeBSD.org>

Add an implementation of savectx that doesn't just call panic.

Obtained from: ABT Systems Ltd
Sponsored by: The FreeBSD Foundation


# e5acd89c 13-Apr-2015 Andrew Turner <andrew@FreeBSD.org>

Bring in the start of the arm64 kernel.

This is only the minimum set of files needed to boot in qemu. As such it is
missing a few things.

The bus_dma code is currently only stub functions with a full implementation
from the development tree to follow.

The gic driver has been copied as the interrupt framework is different. It
is expected the two drivers will be merged by the arm intrng project,
however this will need to be imported into the tree and support for arm64
would need to be added.

This includes code developed by myself, SemiHalf, Ed Maste, and Robin
Randhawa from ARM. This has been funded by the FreeBSD Foundation, with
early development by myself in my spare time with assistance from Robin.

Differential Revision: https://reviews.freebsd.org/D2199
Reviewed by: emaste, imp
Relnotes: yes
Sponsored by: The FreeBSD Foundation