Bug 285677 - vgic: Off-by-one error in its_init_cpu_lpi()
Summary: vgic: Off-by-one error in its_init_cpu_lpi()
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: arm (show other bugs)
Version: Unspecified
Hardware: arm64 Any
: --- Affects Only Me
Assignee: freebsd-arm (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2025-03-26 17:26 UTC by Julien Grall
Modified: 2025-03-28 17:59 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Julien Grall 2025-03-26 17:26:07 UTC
The function its_init_cpu_lpi() will configure the LPIs for a given CPU. One part is to configure the GICR_PROPBASER which contains, among other fields, the size of the property table. This is computed as followed:

```
        size = (flsl(LPI_CONFTAB_SIZE | GIC_FIRST_LPI) - 1);

        xbaser = vtophys(sc->sc_conf_base) |
            (GICR_PROPBASER_SHARE_IS << GICR_PROPBASER_SHARE_SHIFT) |
            (GICR_PROPBASER_CACHE_NIWAWB << GICR_PROPBASER_CACHE_SHIFT) |
            size;
```

Per the GIC specification (12.11.31 in ARM IHI 069G), the ID bits is:

```
The number of bits of LPI INTID supported, minus one, by the LPI Configuration table starting at Physical_Address.
```

As the function flsl returns the last bit set starting from 1 (e.g. if the value 1 is passed, then the return is 1), I think the size should be computed using
flsl(...) - 2.

The size is also used by the pending table which can't be touched by the OS once the LPIs has been enabled:

```
During normal operation, the LPI Pending table is maintained solely by the Redistributor.
Behavior is UNPREDICTABLE if software writes to the LPI Pending tables while GICR_CTLR.EnableLPIs == 1.
When GICR_CTLR.EnableLPIs is cleared to 0, behavior is UNPREDICTABLE if the LPI Pending table is written
before GICR_CTLR.RWP reads 0.
```

As we don't know the content past the region, this could lead to strange behavior. Although, I am not aware of any issue right now.

This will also become a problem in confidential compute, because FreeBSD may end up to declassify more memory than we should.

I am not posting a formal patch because I don't have a setup to build FreeBSD yet.
Comment 1 Colin Percival freebsd_committer freebsd_triage 2025-03-27 20:32:38 UTC
I opened a review: https://reviews.freebsd.org/D49542
Comment 2 commit-hook freebsd_committer freebsd_triage 2025-03-28 17:59:27 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=a1759dca96748648a6da5f9ebd14e46836eed45e

commit a1759dca96748648a6da5f9ebd14e46836eed45e
Author:     Colin Percival <cperciva@FreeBSD.org>
AuthorDate: 2025-03-27 20:23:32 +0000
Commit:     Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2025-03-28 17:58:19 +0000

    arm64: Fix off-by-one in its_init_cpu_lpi

    The low bits of GICR_PROPBASER are defined as
      The number of bits of LPI INTID supported, minus one, by the LPI
      Configuration table starting at Physical_Address.
    but flsl(1 << n) returns n + 1; use ilog2_long instead.

    PR:     285677
    Reported by:    Julien Grall
    Reviewed by:    andrew
    Sponsored by:   Amazon
    Differential Revision:  https://reviews.freebsd.org/D49542

 sys/arm64/arm64/gicv3_its.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)