+Alex On Tue, Mar 16, 2021 at 9:20 AM Jiuyang Liu <l...@jiuyang.me> wrote: > > This patch inserts SFENCE.VMA after modifying PTE based on RISC-V > specification. > > arch/riscv/include/asm/pgtable.h: > 1. implement pte_user, pte_global and pte_leaf to check correspond > attribute of a pte_t.
Adding pte_user(), pte_global(), and pte_leaf() is fine. > > 2. insert SFENCE.VMA in set_pte_at based on RISC-V Volume 2, Privileged > Spec v. 20190608 page 66 and 67: > If software modifies a non-leaf PTE, it should execute SFENCE.VMA with > rs1=x0. If any PTE along the traversal path had its G bit set, rs2 must > be x0; otherwise, rs2 should be set to the ASID for which the > translation is being modified. > If software modifies a leaf PTE, it should execute SFENCE.VMA with rs1 > set to a virtual address within the page. If any PTE along the traversal > path had its G bit set, rs2 must be x0; otherwise, rs2 should be set to > the ASID for which the translation is being modified. > > arch/riscv/include/asm/tlbflush.h: > 1. implement get_current_asid to get current program asid. > 2. implement local_flush_tlb_asid to flush tlb with asid. As per my understanding, we don't need to explicitly invalidate local TLB in set_pte() or set_pet_at() because generic Linux page table management (<linux>/mm/*) will call the appropriate flush_tlb_xyz() function after page table updates. Also, just local TLB flush is generally not sufficient because a lot of page tables will be used accross on multiple HARTs. > > Signed-off-by: Jiuyang Liu <l...@jiuyang.me> > --- > arch/riscv/include/asm/pgtable.h | 27 +++++++++++++++++++++++++++ > arch/riscv/include/asm/tlbflush.h | 12 ++++++++++++ > 2 files changed, 39 insertions(+) > > diff --git a/arch/riscv/include/asm/pgtable.h > b/arch/riscv/include/asm/pgtable.h > index ebf817c1bdf4..5a47c60372c1 100644 > --- a/arch/riscv/include/asm/pgtable.h > +++ b/arch/riscv/include/asm/pgtable.h > @@ -222,6 +222,16 @@ static inline int pte_write(pte_t pte) > return pte_val(pte) & _PAGE_WRITE; > } > > +static inline int pte_user(pte_t pte) > +{ > + return pte_val(pte) & _PAGE_USER; > +} > + > +static inline int pte_global(pte_t pte) > +{ > + return pte_val(pte) & _PAGE_GLOBAL; > +} > + > static inline int pte_exec(pte_t pte) > { > return pte_val(pte) & _PAGE_EXEC; > @@ -248,6 +258,11 @@ static inline int pte_special(pte_t pte) > return pte_val(pte) & _PAGE_SPECIAL; > } > > +static inline int pte_leaf(pte_t pte) > +{ > + return pte_val(pte) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC); > +} > + > /* static inline pte_t pte_rdprotect(pte_t pte) */ > > static inline pte_t pte_wrprotect(pte_t pte) > @@ -358,6 +373,18 @@ static inline void set_pte_at(struct mm_struct *mm, > flush_icache_pte(pteval); > > set_pte(ptep, pteval); > + > + if (pte_present(pteval)) { > + if (pte_leaf(pteval)) { > + local_flush_tlb_page(addr); > + } else { > + if (pte_global(pteval)) > + local_flush_tlb_all(); > + else > + local_flush_tlb_asid(); > + > + } > + } > } > > static inline void pte_clear(struct mm_struct *mm, > diff --git a/arch/riscv/include/asm/tlbflush.h > b/arch/riscv/include/asm/tlbflush.h > index 394cfbccdcd9..1f9b62b3670b 100644 > --- a/arch/riscv/include/asm/tlbflush.h > +++ b/arch/riscv/include/asm/tlbflush.h > @@ -21,6 +21,18 @@ static inline void local_flush_tlb_page(unsigned long addr) > { > __asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory"); > } > + > +static inline unsigned long get_current_asid(void) > +{ > + return (csr_read(CSR_SATP) >> SATP_ASID_SHIFT) & SATP_ASID_MASK; > +} > + > +static inline void local_flush_tlb_asid(void) > +{ > + unsigned long asid = get_current_asid(); > + __asm__ __volatile__ ("sfence.vma x0, %0" : : "r" (asid) : "memory"); > +} > + > #else /* CONFIG_MMU */ > #define local_flush_tlb_all() do { } while (0) > #define local_flush_tlb_page(addr) do { } while (0) > -- > 2.30.2 > > > _______________________________________________ > linux-riscv mailing list > linux-ri...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv Regards, Anup