linux/arch/openrisc/mm/cache.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * OpenRISC cache.c
   4 *
   5 * Linux architectural port borrowing liberally from similar works of
   6 * others.  All original copyrights apply as per the original source
   7 * declaration.
   8 *
   9 * Modifications for the OpenRISC architecture:
  10 * Copyright (C) 2015 Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
  11 */
  12
  13#include <asm/spr.h>
  14#include <asm/spr_defs.h>
  15#include <asm/cache.h>
  16#include <asm/cacheflush.h>
  17#include <asm/tlbflush.h>
  18
  19static __always_inline void cache_loop(struct page *page, const unsigned int reg)
  20{
  21        unsigned long paddr = page_to_pfn(page) << PAGE_SHIFT;
  22        unsigned long line = paddr & ~(L1_CACHE_BYTES - 1);
  23
  24        while (line < paddr + PAGE_SIZE) {
  25                mtspr(reg, line);
  26                line += L1_CACHE_BYTES;
  27        }
  28}
  29
  30void local_dcache_page_flush(struct page *page)
  31{
  32        cache_loop(page, SPR_DCBFR);
  33}
  34EXPORT_SYMBOL(local_dcache_page_flush);
  35
  36void local_icache_page_inv(struct page *page)
  37{
  38        cache_loop(page, SPR_ICBIR);
  39}
  40EXPORT_SYMBOL(local_icache_page_inv);
  41
  42void update_cache(struct vm_area_struct *vma, unsigned long address,
  43        pte_t *pte)
  44{
  45        unsigned long pfn = pte_val(*pte) >> PAGE_SHIFT;
  46        struct page *page = pfn_to_page(pfn);
  47        int dirty = !test_and_set_bit(PG_dc_clean, &page->flags);
  48
  49        /*
  50         * Since icaches do not snoop for updated data on OpenRISC, we
  51         * must write back and invalidate any dirty pages manually. We
  52         * can skip data pages, since they will not end up in icaches.
  53         */
  54        if ((vma->vm_flags & VM_EXEC) && dirty)
  55                sync_icache_dcache(page);
  56}
  57
  58