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

sc-r5k.c (2169B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
      4 * derived from r4xx0.c by David S. Miller (davem@davemloft.net).
      5 */
      6#include <linux/init.h>
      7#include <linux/kernel.h>
      8#include <linux/sched.h>
      9#include <linux/mm.h>
     10
     11#include <asm/mipsregs.h>
     12#include <asm/bcache.h>
     13#include <asm/cacheops.h>
     14#include <asm/page.h>
     15#include <asm/mmu_context.h>
     16#include <asm/r4kcache.h>
     17
     18/* Secondary cache size in bytes, if present.  */
     19static unsigned long scache_size;
     20
     21#define SC_LINE 32
     22#define SC_PAGE (128*SC_LINE)
     23
     24static inline void blast_r5000_scache(void)
     25{
     26	unsigned long start = INDEX_BASE;
     27	unsigned long end = start + scache_size;
     28
     29	while(start < end) {
     30		cache_op(R5K_Page_Invalidate_S, start);
     31		start += SC_PAGE;
     32	}
     33}
     34
     35static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
     36{
     37	unsigned long end, a;
     38
     39	/* Catch bad driver code */
     40	BUG_ON(size == 0);
     41
     42	if (size >= scache_size) {
     43		blast_r5000_scache();
     44		return;
     45	}
     46
     47	/* On the R5000 secondary cache we cannot
     48	 * invalidate less than a page at a time.
     49	 * The secondary cache is physically indexed, write-through.
     50	 */
     51	a = addr & ~(SC_PAGE - 1);
     52	end = (addr + size - 1) & ~(SC_PAGE - 1);
     53	while (a <= end) {
     54		cache_op(R5K_Page_Invalidate_S, a);
     55		a += SC_PAGE;
     56	}
     57}
     58
     59static void r5k_sc_enable(void)
     60{
     61	unsigned long flags;
     62
     63	local_irq_save(flags);
     64	set_c0_config(R5K_CONF_SE);
     65	blast_r5000_scache();
     66	local_irq_restore(flags);
     67}
     68
     69static void r5k_sc_disable(void)
     70{
     71	unsigned long flags;
     72
     73	local_irq_save(flags);
     74	blast_r5000_scache();
     75	clear_c0_config(R5K_CONF_SE);
     76	local_irq_restore(flags);
     77}
     78
     79static inline int __init r5k_sc_probe(void)
     80{
     81	unsigned long config = read_c0_config();
     82
     83	if (config & CONF_SC)
     84		return 0;
     85
     86	scache_size = (512 * 1024) << ((config & R5K_CONF_SS) >> 20);
     87
     88	printk("R5000 SCACHE size %ldkB, linesize 32 bytes.\n",
     89			scache_size >> 10);
     90
     91	return 1;
     92}
     93
     94static struct bcache_ops r5k_sc_ops = {
     95	.bc_enable = r5k_sc_enable,
     96	.bc_disable = r5k_sc_disable,
     97	.bc_wback_inv = r5k_dma_cache_inv_sc,
     98	.bc_inv = r5k_dma_cache_inv_sc
     99};
    100
    101void r5k_sc_init(void)
    102{
    103	if (r5k_sc_probe()) {
    104		r5k_sc_enable();
    105		bcops = &r5k_sc_ops;
    106	}
    107}