[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <ff85cdc4-b1e3-06a3-19fc-a7e1acf99d40@ics.forth.gr>
Date: Tue, 26 Apr 2022 08:57:19 +0300
From: Nick Kossifidis <mick@....forth.gr>
To: Alexandre Ghiti <alexandre.ghiti@...onical.com>,
Jonathan Corbet <corbet@....net>,
Paul Walmsley <paul.walmsley@...ive.com>,
Palmer Dabbelt <palmer@...belt.com>,
Albert Ou <aou@...s.berkeley.edu>,
Zong Li <zong.li@...ive.com>, Anup Patel <anup@...infault.org>,
Atish Patra <Atish.Patra@...osinc.com>,
Christoph Hellwig <hch@....de>,
Andrey Ryabinin <ryabinin.a.a@...il.com>,
Alexander Potapenko <glider@...gle.com>,
Andrey Konovalov <andreyknvl@...il.com>,
Dmitry Vyukov <dvyukov@...gle.com>,
Ard Biesheuvel <ardb@...nel.org>,
Arnd Bergmann <arnd@...db.de>,
Kees Cook <keescook@...omium.org>,
Guo Ren <guoren@...ux.alibaba.com>,
Heinrich Schuchardt <heinrich.schuchardt@...onical.com>,
Mayuresh Chitale <mchitale@...tanamicro.com>,
panqinglin2020@...as.ac.cn, linux-doc@...r.kernel.org,
linux-riscv@...ts.infradead.org, linux-kernel@...r.kernel.org,
kasan-dev@...glegroups.com, linux-efi@...r.kernel.org,
linux-arch@...r.kernel.org
Subject: Re: [PATCH v3 07/13] riscv: Implement sv48 support
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
Powered by blists - more mailing lists