lkml.org 
[lkml]   [2020]   [Apr]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
SubjectRe: [PATCH RFC 2/8] riscv/kaslr: introduce functions to clear page table
Date
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@sifive.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

\
 
 \ /
  Last update: 2020-04-07 07:09    [W:0.109 / U:0.828 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site