[PATCH v3 07/13] riscv: Implement sv48 support
Nick Kossifidis
mick at ics.forth.gr
Mon Apr 25 22:57:19 PDT 2022
Hello Alex,
On 12/6/21 12:46, Alexandre Ghiti wrote:
>
> +#ifdef CONFIG_64BIT
> +static void __init disable_pgtable_l4(void)
> +{
> + pgtable_l4_enabled = false;
> + kernel_map.page_offset = PAGE_OFFSET_L3;
> + satp_mode = SATP_MODE_39;
> +}
> +
> +/*
> + * There is a simple way to determine if 4-level is supported by the
> + * underlying hardware: establish 1:1 mapping in 4-level page table mode
> + * then read SATP to see if the configuration was taken into account
> + * meaning sv48 is supported.
> + */
> +static __init void set_satp_mode(void)
> +{
> + u64 identity_satp, hw_satp;
> + uintptr_t set_satp_mode_pmd;
> +
> + set_satp_mode_pmd = ((unsigned long)set_satp_mode) & PMD_MASK;
> + create_pgd_mapping(early_pg_dir,
> + set_satp_mode_pmd, (uintptr_t)early_pud,
> + PGDIR_SIZE, PAGE_TABLE);
> + create_pud_mapping(early_pud,
> + set_satp_mode_pmd, (uintptr_t)early_pmd,
> + PUD_SIZE, PAGE_TABLE);
> + /* Handle the case where set_satp_mode straddles 2 PMDs */
> + create_pmd_mapping(early_pmd,
> + set_satp_mode_pmd, set_satp_mode_pmd,
> + PMD_SIZE, PAGE_KERNEL_EXEC);
> + create_pmd_mapping(early_pmd,
> + set_satp_mode_pmd + PMD_SIZE,
> + set_satp_mode_pmd + PMD_SIZE,
> + PMD_SIZE, PAGE_KERNEL_EXEC);
> +
> + identity_satp = PFN_DOWN((uintptr_t)&early_pg_dir) | satp_mode;
> +
> + local_flush_tlb_all();
> + csr_write(CSR_SATP, identity_satp);
> + hw_satp = csr_swap(CSR_SATP, 0ULL);
> + local_flush_tlb_all();
> +
> + if (hw_satp != identity_satp)
> + disable_pgtable_l4();
> +
> + memset(early_pg_dir, 0, PAGE_SIZE);
> + memset(early_pud, 0, PAGE_SIZE);
> + memset(early_pmd, 0, PAGE_SIZE);
> +}
> +#endif
> +
When doing the 1:1 mapping you don't take into account the limitation
that all bits above 47 need to have the same value as bit 47. If the
kernel exists at a high physical address with bit 47 set the
corresponding virtual address will be invalid, resulting an instruction
fetch fault as the privilege spec mandates. We verified this bug on our
prototype. I suggest we re-write this in assembly and do a proper satp
switch like we do on head.S, so that we don't need the 1:1 mapping and
we also have a way to recover in case this fails.
Regards,
Nick
More information about the linux-riscv
mailing list