Page MenuHomeFreeBSD

arm64: Add BTI support to pmap

Authored by andrew on Oct 23 2023, 2:38 PM.
Referenced Files
Unknown Object (File)
Thu, Feb 22, 10:01 PM
Unknown Object (File)
Jan 18 2024, 1:21 PM
Unknown Object (File)
Jan 5 2024, 10:33 PM
Unknown Object (File)
Dec 23 2023, 3:00 AM
Unknown Object (File)
Dec 14 2023, 7:08 PM
Unknown Object (File)
Dec 2 2023, 8:14 AM
Unknown Object (File)
Nov 22 2023, 5:12 PM
Unknown Object (File)
Nov 15 2023, 9:02 AM



Add a rangeset to the arm64 pmap to describe which address space needs
the Branch Target Identification (BTI) Guard Page flag set in the page

On hardware that supports BTI the Guard Page flag tells the hardware
to raise an exception if the target of a BR* and BLR* instruction is
not an appropriate landing pad instruction.

To support this in userspace we need to know which address space
should be guarded. For this add a rangeset to the arm64 pmap when the
hardware supports BTI. The kernel can then use pmap_bti_set and
pmap_bti_clear mark and unmark which address space is guarded.

Sponsored by: Arm Ltd
Sponsored by: The FreeBSD Foundation

Diff Detail

rG FreeBSD src repository
Lint Not Applicable
Tests Not Applicable

Event Timeline


Please add a comment explaining what this flag does.


I think it would be better to embed pm_bti into the pmap, like we do with the rangeset for PKRU. Or perhaps just use malloc(). A dedicated zone for one allocation per pmap is overkill IMO.


Hmm, do we want to call pmap_bti_on_remove() even when pm_stats.resident_count == 0? If so, I think PKRU has the same problem.


The case where pm_stage is not equal seems like it should be an error.


We should really just reuse the zone created in rs_rangeset_init(). That could be a followup change though.


I think we want to add a rangeset_lookup_ge(), i.e., find the next range at or above the specified place, instead of looking up each page. That should be easy to implement, the underlying pctrie implementation provides it.


Why "on_remove" instead of "remove"?


Isn't it sufficient to just check pm_bti != NULL?


Why not perform these checks in pmap_bti_check_args()?


I did it this way to break the KBI so it could be MFCd to 14, I could change to malloc.


It should be called if the address space could be reused. If there is a guarantee that the address space will not be reused when pm_stats.resident_count == 0 then we can add a check.


That's how it's named on amd64


Why is it a problem to add fields to the end of struct pmap? vm_pmap is the last field of struct vmspace, so growing it shouldn't break any important KBI.


I don't believe there is any particular guarantee that resident_count == 0 implies that the address space won't be reused. A process may be completely swapped out. In practice, I suspect the VDSO page would keep the resident count positive, but that's not a guarantee.

  • Add a comment above pmap_bti_support
  • Remove pmap_bti_ranges_root_zone and switch to malloc for pm_bti
  • Remove pmap_bti_clear and pmap_bti_deassign, they are unused
  • Move the pmap_bti_check_uargs checks to pmap_bti_set
  • Remove unneeded PM_STAGE1 checks

I still don't see why the rangeset can't be embedded.


I can see a use for a rangeset for 2 or 3 other features. As these are unimplemented on most current CPUs I'd prefer to not add too much bloat to struct pmap if it's not used on most currently shipping devices.


In that case we need to call pmap_bti_on_remove even when resident_count == 0. We need to remove the bti flag as the address space may be reused by code that doesn't understand BTI.

This revision was not accepted when it landed; it landed in state Needs Review.Thu, Feb 22, 4:28 PM
This revision was automatically updated to reflect the committed changes.