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-ip22.c (4334B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * sc-ip22.c: Indy cache management functions.
      4 *
      5 * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
      6 * derived from r4xx0.c by David S. Miller (davem@davemloft.net).
      7 */
      8#include <linux/init.h>
      9#include <linux/kernel.h>
     10#include <linux/sched.h>
     11#include <linux/mm.h>
     12
     13#include <asm/bcache.h>
     14#include <asm/page.h>
     15#include <asm/bootinfo.h>
     16#include <asm/sgi/ip22.h>
     17#include <asm/sgi/mc.h>
     18
     19/* Secondary cache size in bytes, if present.  */
     20static unsigned long scache_size;
     21
     22#undef DEBUG_CACHE
     23
     24#define SC_SIZE 0x00080000
     25#define SC_LINE 32
     26#define CI_MASK (SC_SIZE - SC_LINE)
     27#define SC_INDEX(n) ((n) & CI_MASK)
     28
     29static inline void indy_sc_wipe(unsigned long first, unsigned long last)
     30{
     31	unsigned long tmp;
     32
     33	__asm__ __volatile__(
     34	"	.set	push			# indy_sc_wipe		\n"
     35	"	.set	noreorder					\n"
     36	"	.set	mips3						\n"
     37	"	.set	noat						\n"
     38	"	mfc0	%2, $12						\n"
     39	"	li	$1, 0x80		# Go 64 bit		\n"
     40	"	mtc0	$1, $12						\n"
     41	"								\n"
     42	"	#							\n"
     43	"	# Open code a dli $1, 0x9000000080000000		\n"
     44	"	#							\n"
     45	"	# Required because binutils 2.25 will happily accept	\n"
     46	"	# 64 bit instructions in .set mips3 mode but puke on	\n"
     47	"	# 64 bit constants when generating 32 bit ELF		\n"
     48	"	#							\n"
     49	"	lui	$1,0x9000					\n"
     50	"	dsll	$1,$1,0x10					\n"
     51	"	ori	$1,$1,0x8000					\n"
     52	"	dsll	$1,$1,0x10					\n"
     53	"								\n"
     54	"	or	%0, $1			# first line to flush	\n"
     55	"	or	%1, $1			# last line to flush	\n"
     56	"	.set	at						\n"
     57	"								\n"
     58	"1:	sw	$0, 0(%0)					\n"
     59	"	bne	%0, %1, 1b					\n"
     60	"	 daddu	%0, 32						\n"
     61	"								\n"
     62	"	mtc0	%2, $12			# Back to 32 bit	\n"
     63	"	nop				# pipeline hazard	\n"
     64	"	nop							\n"
     65	"	nop							\n"
     66	"	nop							\n"
     67	"	.set	pop						\n"
     68	: "=r" (first), "=r" (last), "=&r" (tmp)
     69	: "0" (first), "1" (last));
     70}
     71
     72static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size)
     73{
     74	unsigned long first_line, last_line;
     75	unsigned long flags;
     76
     77#ifdef DEBUG_CACHE
     78	printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
     79#endif
     80
     81	/* Catch bad driver code */
     82	BUG_ON(size == 0);
     83
     84	/* Which lines to flush?  */
     85	first_line = SC_INDEX(addr);
     86	last_line = SC_INDEX(addr + size - 1);
     87
     88	local_irq_save(flags);
     89	if (first_line <= last_line) {
     90		indy_sc_wipe(first_line, last_line);
     91		goto out;
     92	}
     93
     94	indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
     95	indy_sc_wipe(0, last_line);
     96out:
     97	local_irq_restore(flags);
     98}
     99
    100static void indy_sc_enable(void)
    101{
    102	unsigned long addr, tmp1, tmp2;
    103
    104	/* This is really cool... */
    105#ifdef DEBUG_CACHE
    106	printk("Enabling R4600 SCACHE\n");
    107#endif
    108	__asm__ __volatile__(
    109	".set\tpush\n\t"
    110	".set\tnoreorder\n\t"
    111	".set\tmips3\n\t"
    112	"mfc0\t%2, $12\n\t"
    113	"nop; nop; nop; nop;\n\t"
    114	"li\t%1, 0x80\n\t"
    115	"mtc0\t%1, $12\n\t"
    116	"nop; nop; nop; nop;\n\t"
    117	"li\t%0, 0x1\n\t"
    118	"dsll\t%0, 31\n\t"
    119	"lui\t%1, 0x9000\n\t"
    120	"dsll32\t%1, 0\n\t"
    121	"or\t%0, %1, %0\n\t"
    122	"sb\t$0, 0(%0)\n\t"
    123	"mtc0\t$0, $12\n\t"
    124	"nop; nop; nop; nop;\n\t"
    125	"mtc0\t%2, $12\n\t"
    126	"nop; nop; nop; nop;\n\t"
    127	".set\tpop"
    128	: "=r" (tmp1), "=r" (tmp2), "=r" (addr));
    129}
    130
    131static void indy_sc_disable(void)
    132{
    133	unsigned long tmp1, tmp2, tmp3;
    134
    135#ifdef DEBUG_CACHE
    136	printk("Disabling R4600 SCACHE\n");
    137#endif
    138	__asm__ __volatile__(
    139	".set\tpush\n\t"
    140	".set\tnoreorder\n\t"
    141	".set\tmips3\n\t"
    142	"li\t%0, 0x1\n\t"
    143	"dsll\t%0, 31\n\t"
    144	"lui\t%1, 0x9000\n\t"
    145	"dsll32\t%1, 0\n\t"
    146	"or\t%0, %1, %0\n\t"
    147	"mfc0\t%2, $12\n\t"
    148	"nop; nop; nop; nop\n\t"
    149	"li\t%1, 0x80\n\t"
    150	"mtc0\t%1, $12\n\t"
    151	"nop; nop; nop; nop\n\t"
    152	"sh\t$0, 0(%0)\n\t"
    153	"mtc0\t$0, $12\n\t"
    154	"nop; nop; nop; nop\n\t"
    155	"mtc0\t%2, $12\n\t"
    156	"nop; nop; nop; nop\n\t"
    157	".set\tpop"
    158	: "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
    159}
    160
    161static inline int __init indy_sc_probe(void)
    162{
    163	unsigned int size = ip22_eeprom_read(&sgimc->eeprom, 17);
    164	if (size == 0)
    165		return 0;
    166
    167	size <<= PAGE_SHIFT;
    168	printk(KERN_INFO "R4600/R5000 SCACHE size %dK, linesize 32 bytes.\n",
    169	       size >> 10);
    170	scache_size = size;
    171
    172	return 1;
    173}
    174
    175/* XXX Check with wje if the Indy caches can differentiate between
    176   writeback + invalidate and just invalidate.	*/
    177static struct bcache_ops indy_sc_ops = {
    178	.bc_enable = indy_sc_enable,
    179	.bc_disable = indy_sc_disable,
    180	.bc_wback_inv = indy_sc_wback_invalidate,
    181	.bc_inv = indy_sc_wback_invalidate
    182};
    183
    184void indy_sc_init(void)
    185{
    186	if (indy_sc_probe()) {
    187		indy_sc_enable();
    188		bcops = &indy_sc_ops;
    189	}
    190}