cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tlb.h (2332B)


      1/* SPDX-License-Identifier: GPL-2.0-only */
      2/*
      3 * Based on arch/arm/include/asm/tlb.h
      4 *
      5 * Copyright (C) 2002 Russell King
      6 * Copyright (C) 2012 ARM Ltd.
      7 */
      8#ifndef __ASM_TLB_H
      9#define __ASM_TLB_H
     10
     11#include <linux/pagemap.h>
     12#include <linux/swap.h>
     13
     14static inline void __tlb_remove_table(void *_table)
     15{
     16	free_page_and_swap_cache((struct page *)_table);
     17}
     18
     19#define tlb_flush tlb_flush
     20static void tlb_flush(struct mmu_gather *tlb);
     21
     22#include <asm-generic/tlb.h>
     23
     24/*
     25 * get the tlbi levels in arm64.  Default value is 0 if more than one
     26 * of cleared_* is set or neither is set.
     27 * Arm64 doesn't support p4ds now.
     28 */
     29static inline int tlb_get_level(struct mmu_gather *tlb)
     30{
     31	/* The TTL field is only valid for the leaf entry. */
     32	if (tlb->freed_tables)
     33		return 0;
     34
     35	if (tlb->cleared_ptes && !(tlb->cleared_pmds ||
     36				   tlb->cleared_puds ||
     37				   tlb->cleared_p4ds))
     38		return 3;
     39
     40	if (tlb->cleared_pmds && !(tlb->cleared_ptes ||
     41				   tlb->cleared_puds ||
     42				   tlb->cleared_p4ds))
     43		return 2;
     44
     45	if (tlb->cleared_puds && !(tlb->cleared_ptes ||
     46				   tlb->cleared_pmds ||
     47				   tlb->cleared_p4ds))
     48		return 1;
     49
     50	return 0;
     51}
     52
     53static inline void tlb_flush(struct mmu_gather *tlb)
     54{
     55	struct vm_area_struct vma = TLB_FLUSH_VMA(tlb->mm, 0);
     56	bool last_level = !tlb->freed_tables;
     57	unsigned long stride = tlb_get_unmap_size(tlb);
     58	int tlb_level = tlb_get_level(tlb);
     59
     60	/*
     61	 * If we're tearing down the address space then we only care about
     62	 * invalidating the walk-cache, since the ASID allocator won't
     63	 * reallocate our ASID without invalidating the entire TLB.
     64	 */
     65	if (tlb->fullmm) {
     66		if (!last_level)
     67			flush_tlb_mm(tlb->mm);
     68		return;
     69	}
     70
     71	__flush_tlb_range(&vma, tlb->start, tlb->end, stride,
     72			  last_level, tlb_level);
     73}
     74
     75static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
     76				  unsigned long addr)
     77{
     78	pgtable_pte_page_dtor(pte);
     79	tlb_remove_table(tlb, pte);
     80}
     81
     82#if CONFIG_PGTABLE_LEVELS > 2
     83static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
     84				  unsigned long addr)
     85{
     86	struct page *page = virt_to_page(pmdp);
     87
     88	pgtable_pmd_page_dtor(page);
     89	tlb_remove_table(tlb, page);
     90}
     91#endif
     92
     93#if CONFIG_PGTABLE_LEVELS > 3
     94static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
     95				  unsigned long addr)
     96{
     97	tlb_remove_table(tlb, virt_to_page(pudp));
     98}
     99#endif
    100
    101#endif