[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <507f88a2-63c0-f615-2684-a200dd44c34a@ghiti.fr>
Date: Tue, 7 Apr 2020 01:09:02 -0400
From: Alex Ghiti <alex@...ti.fr>
To: Zong Li <zong.li@...ive.com>, palmer@...belt.com,
paul.walmsley@...ive.com, linux-riscv@...ts.infradead.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH RFC 2/8] riscv/kaslr: introduce functions to clear page
table
On 3/24/20 3:30 AM, Zong Li wrote:
> In KASLR, we need to re-create page table after getting a random
> destination. Introduce clear function to clear old content. Also, the
> page table entries allow writing value when it's empty, so we have to
> clear the early page table.
>
> This patch is a preparation to support KASLR.
>
> Signed-off-by: Zong Li <zong.li@...ive.com>
> ---
> arch/riscv/mm/init.c | 54 ++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 54 insertions(+)
>
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index ace5d74fd939..51e263c04fa2 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -315,6 +315,7 @@ static void __init create_pmd_mapping(pmd_t *pmdp,
> #define get_pgd_next_virt(__pa) get_pmd_virt(__pa)
> #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \
> create_pmd_mapping(__nextp, __va, __pa, __sz, __prot)
> +#define clear_pgd_next_mapping(__nextp) clear_pmd(__nextp)
> #define fixmap_pgd_next fixmap_pmd
> #else
> #define pgd_next_t pte_t
> @@ -322,6 +323,7 @@ static void __init create_pmd_mapping(pmd_t *pmdp,
> #define get_pgd_next_virt(__pa) get_pte_virt(__pa)
> #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \
> create_pte_mapping(__nextp, __va, __pa, __sz, __prot)
> +#define clear_pgd_next_mapping(__nextp) clear_pte(__nextp)
> #define fixmap_pgd_next fixmap_pte
> #endif
>
> @@ -361,6 +363,58 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
> return PMD_SIZE;
> }
>
> +#ifdef CONFIG_RANDOMIZE_BASE
> +static void __init clear_pte(pte_t *ptep)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < PTRS_PER_PTE; i++)
> + if (!pte_none(ptep[i]))
> + ptep[i] = __pte(0);
> +}
> +
> +static void __init clear_pmd(pmd_t *pmdp)
> +{
> + unsigned int i;
> + pte_t *ptep;
> + phys_addr_t pte_phys;
> + uintptr_t kaslr_offset = get_kaslr_offset();
> +
> + for (i = 0; i < PTRS_PER_PMD; i++)
> + if (!pmd_none(pmdp[i])) {
> + if (pmd_leaf(pmdp[i])) {
> + pmd_clear(&pmdp[i]);
> + } else {
> + pte_phys = PFN_PHYS(_pmd_pfn(pmdp[i]));
> + ptep = get_pte_virt(pte_phys + kaslr_offset);
> + clear_pte(ptep);
> + pmd_clear(&pmdp[i]);
> + }
> + }
> +}
> +
> +static void __init clear_pgd(pgd_t *pgdp)
> +{
> + unsigned int i;
> + pgd_next_t *nextp;
> + phys_addr_t next_phys;
> + uintptr_t kaslr_offset = get_kaslr_offset();
> +
> + for (i = 0; i < PTRS_PER_PGD; i++)
> + if (pgd_val(pgdp[i]) != 0) {
> + if (pgd_leaf(pgd_val(pgdp[i]))) {
> + set_pgd(&pgdp[i], __pgd(0));
> + } else {
> + next_phys = PFN_PHYS(_pgd_pfn(pgdp[i]));
> + nextp = get_pgd_next_virt(next_phys +
> + kaslr_offset);
> + clear_pgd_next_mapping(nextp);
> + set_pgd(&pgdp[i], __pgd(0));
> + }
> + }
> +}
> +#endif
> +
> /*
> * setup_vm() is called from head.S with MMU-off.
> *
>
If this is only for clearing early page tables, a memset is way easier
as there is only one page per level to clear.
Alex
Powered by blists - more mailing lists