[PATCH v2] riscv: Improve KASAN_VMALLOC support
Alex Ghiti
alex at ghiti.fr
Wed Mar 10 19:18:53 GMT 2021
Le 3/9/21 à 9:37 PM, Palmer Dabbelt a écrit :
> On Fri, 26 Feb 2021 10:01:54 PST (-0800), alex at ghiti.fr wrote:
>> When KASAN vmalloc region is populated, there is no userspace process and
>> the page table in use is swapper_pg_dir, so there is no need to read
>> SATP. Then we can use the same scheme used by kasan_populate_p*d
>> functions to go through the page table, which harmonizes the code.
>>
>> In addition, make use of set_pgd that goes through all unused page table
>> levels, contrary to p*d_populate functions, which makes this function
>> work
>> whatever the number of page table levels.
>>
>> And finally, make sure the writes to swapper_pg_dir are visible using
>> an sfence.vma.
>
> So I think this is actually a bug: without the fence we could get a
> kasan-related fault at any point (as the mappings might not be visible
> yet), and if we get one when inside do_page_fault() (or while holding a
> lock it wants) we'll end up deadlocking against ourselves. That'll
> probably never happen in practice, but it'd still be good to get the
> fence onto fixes. The rest are cleanups, they're for for-next (and
> should probably be part of your sv48 series, if you need to re-spin it
> -- I'll look at that next).
I only talked about sv48 support in the changelog as it explains why I
replaced p*d_populate functions for set_p*d, this is not directly linked
to the sv48 patchset, this is just a bonus that it works for both :)
>
> LMK if you want to split this up, or if you want me to do it. Either way,
I'll split it up: one patch for the cleanup and one patch for the fix.
>
> Reviewed-by: Palmer Dabbelt <palmerdabbelt at google.com>
Thanks,
Alex
>
> Thanks!
>
>> Signed-off-by: Alexandre Ghiti <alex at ghiti.fr>
>> ---
>>
>> Changes in v2:
>> - Quiet kernel test robot warnings about missing prototypes by declaring
>> the introduced functions as static.
>>
>> arch/riscv/mm/kasan_init.c | 61 +++++++++++++-------------------------
>> 1 file changed, 20 insertions(+), 41 deletions(-)
>>
>> diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c
>> index e3d91f334b57..aaa3bdc0ffc0 100644
>> --- a/arch/riscv/mm/kasan_init.c
>> +++ b/arch/riscv/mm/kasan_init.c
>> @@ -11,18 +11,6 @@
>> #include <asm/fixmap.h>
>> #include <asm/pgalloc.h>
>>
>> -static __init void *early_alloc(size_t size, int node)
>> -{
>> - void *ptr = memblock_alloc_try_nid(size, size,
>> - __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, node);
>> -
>> - if (!ptr)
>> - panic("%pS: Failed to allocate %zu bytes align=%zx nid=%d
>> from=%llx\n",
>> - __func__, size, size, node, (u64)__pa(MAX_DMA_ADDRESS));
>> -
>> - return ptr;
>> -}
>> -
>> extern pgd_t early_pg_dir[PTRS_PER_PGD];
>> asmlinkage void __init kasan_early_init(void)
>> {
>> @@ -155,38 +143,29 @@ static void __init kasan_populate(void *start,
>> void *end)
>> memset(start, KASAN_SHADOW_INIT, end - start);
>> }
>>
>> -void __init kasan_shallow_populate(void *start, void *end)
>> +static void __init kasan_shallow_populate_pgd(unsigned long vaddr,
>> unsigned long end)
>> {
>> - unsigned long vaddr = (unsigned long)start & PAGE_MASK;
>> - unsigned long vend = PAGE_ALIGN((unsigned long)end);
>> - unsigned long pfn;
>> - int index;
>> + unsigned long next;
>> void *p;
>> - pud_t *pud_dir, *pud_k;
>> - pgd_t *pgd_dir, *pgd_k;
>> - p4d_t *p4d_dir, *p4d_k;
>> -
>> - while (vaddr < vend) {
>> - index = pgd_index(vaddr);
>> - pfn = csr_read(CSR_SATP) & SATP_PPN;
>> - pgd_dir = (pgd_t *)pfn_to_virt(pfn) + index;
>> - pgd_k = init_mm.pgd + index;
>> - pgd_dir = pgd_offset_k(vaddr);
>> - set_pgd(pgd_dir, *pgd_k);
>> -
>> - p4d_dir = p4d_offset(pgd_dir, vaddr);
>> - p4d_k = p4d_offset(pgd_k, vaddr);
>> -
>> - vaddr = (vaddr + PUD_SIZE) & PUD_MASK;
>> - pud_dir = pud_offset(p4d_dir, vaddr);
>> - pud_k = pud_offset(p4d_k, vaddr);
>> -
>> - if (pud_present(*pud_dir)) {
>> - p = early_alloc(PAGE_SIZE, NUMA_NO_NODE);
>> - pud_populate(&init_mm, pud_dir, p);
>> + pgd_t *pgd_k = pgd_offset_k(vaddr);
>> +
>> + do {
>> + next = pgd_addr_end(vaddr, end);
>> + if (pgd_page_vaddr(*pgd_k) == (unsigned
>> long)lm_alias(kasan_early_shadow_pmd)) {
>> + p = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
>> + set_pgd(pgd_k, pfn_pgd(PFN_DOWN(__pa(p)), PAGE_TABLE));
>> }
>> - vaddr += PAGE_SIZE;
>> - }
>> + } while (pgd_k++, vaddr = next, vaddr != end);
>> +}
>> +
>> +static void __init kasan_shallow_populate(void *start, void *end)
>> +{
>> + unsigned long vaddr = (unsigned long)start & PAGE_MASK;
>> + unsigned long vend = PAGE_ALIGN((unsigned long)end);
>> +
>> + kasan_shallow_populate_pgd(vaddr, vend);
>> +
>> + local_flush_tlb_all();
>> }
>>
>> void __init kasan_init(void)
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
More information about the linux-riscv
mailing list