On 27/04/2026 17:34, Ard Biesheuvel wrote:
> [...]
>
> -void noinstr set_swapper_pgd(pgd_t *pgdp, pgd_t pgd)
> +void noinstr set_rodata_pte(pte_t *ptep, pte_t pte)
> {
> - pgd_t *fixmap_pgdp;
> + pte_t *fixmap_ptep;
>
> /*
> - * Don't bother with the fixmap if swapper_pg_dir is still mapped
> - * writable in the kernel mapping.
> + * Don't bother with the fixmap if rodata is still mapped
> + * writable in the kernel and linear mappings.
> */
> if (rodata_is_rw) {
> - WRITE_ONCE(*pgdp, pgd);
> + WRITE_ONCE(*ptep, pte);
> dsb(ishst);
> isb();
> return;
> }
>
> - spin_lock(&swapper_pgdir_lock);
> - fixmap_pgdp = pgd_set_fixmap(__pa_symbol(pgdp));
> - WRITE_ONCE(*fixmap_pgdp, pgd);
> + spin_lock(&rodata_pgdir_lock);
> + fixmap_ptep = pte_set_fixmap(__pa_nodebug(ptep));
I don't know much about the fixmap but it strikes me as odd that we
would now use pte_set_fixmap() at all levels. I suppose the question is
whether swapper_pg_dir could be written concurrently with fixmap page
tables at PMD level or above? I'm also wondering if those fixmap page
tables are ever written to.
- Kevin
> + WRITE_ONCE(*fixmap_ptep, pte);
> /*
> * We need dsb(ishst) here to ensure the page-table-walker sees
> * our new entry before set_p?d() returns. The fixmap's
> * flush_tlb_kernel_range() via clear_fixmap() does this for us.
> */
> - pgd_clear_fixmap();
> - spin_unlock(&swapper_pgdir_lock);
> + pte_clear_fixmap();
> + spin_unlock(&rodata_pgdir_lock);
> }
>
> [...]