Page MenuHomeFreeBSD

arm64: Add BTI support to pmap
ClosedPublic

Authored by andrew on Oct 23 2023, 2:38 PM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, May 9, 12:02 AM
Unknown Object (File)
Mon, May 6, 6:40 PM
Unknown Object (File)
Fri, May 3, 7:22 PM
Unknown Object (File)
Tue, Apr 30, 4:51 PM
Unknown Object (File)
Tue, Apr 30, 4:50 PM
Unknown Object (File)
Tue, Apr 30, 4:49 PM
Unknown Object (File)
Tue, Apr 30, 10:11 AM
Unknown Object (File)
Sun, Apr 28, 11:15 PM
Subscribers

Details

Summary

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
table.

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

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

sys/arm64/arm64/pmap.c
436

Please add a comment explaining what this flag does.

2369

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.

3680

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.

5549

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

7538

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

8055

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.

8068

Why "on_remove" instead of "remove"?

8072

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

8102

Why not perform these checks in pmap_bti_check_args()?

sys/arm64/arm64/pmap.c
2369

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

3680

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.

8068

That's how it's named on amd64

sys/arm64/arm64/pmap.c
2369

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.

3680

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
sys/arm64/arm64/pmap.c
2369

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

sys/arm64/arm64/pmap.c
2369

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.

3680

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.Feb 22 2024, 4:28 PM
This revision was automatically updated to reflect the committed changes.