[PATCH 2/2] arm64: mm: always map fixmap at page granularity

Mark Rutland mark.rutland at arm.com
Thu Mar 23 08:24:14 PDT 2023


On Tue, Mar 21, 2023 at 02:34:15PM +0000, Ryan Roberts wrote:
> On 21/03/2023 14:18, Mark Rutland wrote:
> > On Wed, Mar 15, 2023 at 10:23:31AM +0000, Ryan Roberts wrote:
> >> On 14/03/2023 14:21, Mark Rutland wrote:

> >>> diff --git a/arch/arm64/mm/fixmap.c b/arch/arm64/mm/fixmap.c
> >>> index 54e50552bfe3..d7a6a485f361 100644
> >>> --- a/arch/arm64/mm/fixmap.c
> >>> +++ b/arch/arm64/mm/fixmap.c
> >>> @@ -16,34 +16,77 @@
> >>>  #include <asm/pgalloc.h>
> >>>  #include <asm/tlbflush.h>
> >>>  
> >>> -static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
> >>> +#define NR_BM_PTE_TABLES \
> >>> +	SPAN_NR_ENTRIES(FIXADDR_START, FIXADDR_TOP, PMD_SHIFT)
> >>> +#define NR_BM_PMD_TABLES \
> >>> +	SPAN_NR_ENTRIES(FIXADDR_START, FIXADDR_TOP, PUD_SHIFT)
> >>
> >> One of the bear traps I stepped in last week when I was wrestling with this is
> >> that FIXADDR_START isn't actually the address of the first slot! It is
> >> __end_of_permanent_fixed_addresses. But you then have all the FIX_BTMAP slots,
> >> FIX_PTE/PMD/PUD/PGD before FIXADDR_START. So I think some refactoring is in
> >> order to properly cover all the slots.
> > 
> > Ugh, yes. This is a total mess.
> > 
> >> Honestly, the fact that the fixed_addresses enum is backwards is mind-bending
> >> too. 
> > 
> > That has been a long standing bugbear of mine, too.
> > 
> >> Any chance we can just define FIXADDR_START and FIXADDR_TOP to cover the
> >> whole lot, then calculate the slot address as (FIXADDR_START + (<ENUM> <<
> >> PAGE_SHIFT))?
> > 
> > Unfortunately, some code is (implicitly) relying on FIXADDR_START..FIXADDR_TOP
> > *not* including the FIX_BTMAP slots (e.g. virt_to_fix() and fix_to_virt() use
> > that to implicitly catch dodgy usage). Other code really wants FIXADDR_START to
> > be the base of the whole fixmap region (e.g. ptdump).
> 
> So perhaps one approach would be to have 2 sets of macros:
> 
> #define ARCH_FIXADDR_START
> #define ARCH_FIXADDR_TOP
> #define FIXADDR_START
> #define FIXADDR_TOP
> 
> static_assert(ARCH_FIXADDR_START <= FIXADDR_START);
> static_assert(ARCH_FIXADDR_TOP >= FIXADDR_TOP);
> 
> ARCH_FIXADDR_* covers the entire region exactly. And FIXADDR_* describes the
> sub-region that the generic code cares about. Then all the fixmap internals can
> be done against ARCH_FIXADDR_* and the generic code can do its checks against
> FIXADDR_* ?

FWIW, x86 has:

| #define FIXADDR_SIZE            (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
| #define FIXADDR_START           (FIXADDR_TOP - FIXADDR_SIZE)
| #define FIXADDR_TOT_SIZE        (__end_of_fixed_addresses << PAGE_SHIFT)
| #define FIXADDR_TOT_START       (FIXADDR_TOP - FIXADDR_TOT_SIZE)

... so I suspect we should do the same, in the hope that can (eventually) be
unified.

Thanks,
Mark.



More information about the linux-arm-kernel mailing list