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

mips-mt.c (6049B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * General MIPS MT support routines, usable in AP/SP and SMVP.
      4 * Copyright (C) 2005 Mips Technologies, Inc
      5 */
      6
      7#include <linux/device.h>
      8#include <linux/kernel.h>
      9#include <linux/sched.h>
     10#include <linux/export.h>
     11#include <linux/interrupt.h>
     12#include <linux/security.h>
     13
     14#include <asm/cpu.h>
     15#include <asm/processor.h>
     16#include <linux/atomic.h>
     17#include <asm/hardirq.h>
     18#include <asm/mmu_context.h>
     19#include <asm/mipsmtregs.h>
     20#include <asm/r4kcache.h>
     21#include <asm/cacheflush.h>
     22
     23int vpelimit;
     24
     25static int __init maxvpes(char *str)
     26{
     27	get_option(&str, &vpelimit);
     28
     29	return 1;
     30}
     31
     32__setup("maxvpes=", maxvpes);
     33
     34int tclimit;
     35
     36static int __init maxtcs(char *str)
     37{
     38	get_option(&str, &tclimit);
     39
     40	return 1;
     41}
     42
     43__setup("maxtcs=", maxtcs);
     44
     45/*
     46 * Dump new MIPS MT state for the core. Does not leave TCs halted.
     47 * Takes an argument which taken to be a pre-call MVPControl value.
     48 */
     49
     50void mips_mt_regdump(unsigned long mvpctl)
     51{
     52	unsigned long flags;
     53	unsigned long vpflags;
     54	unsigned long mvpconf0;
     55	int nvpe;
     56	int ntc;
     57	int i;
     58	int tc;
     59	unsigned long haltval;
     60	unsigned long tcstatval;
     61
     62	local_irq_save(flags);
     63	vpflags = dvpe();
     64	printk("=== MIPS MT State Dump ===\n");
     65	printk("-- Global State --\n");
     66	printk("   MVPControl Passed: %08lx\n", mvpctl);
     67	printk("   MVPControl Read: %08lx\n", vpflags);
     68	printk("   MVPConf0 : %08lx\n", (mvpconf0 = read_c0_mvpconf0()));
     69	nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
     70	ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
     71	printk("-- per-VPE State --\n");
     72	for (i = 0; i < nvpe; i++) {
     73		for (tc = 0; tc < ntc; tc++) {
     74			settc(tc);
     75			if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
     76				printk("  VPE %d\n", i);
     77				printk("   VPEControl : %08lx\n",
     78				       read_vpe_c0_vpecontrol());
     79				printk("   VPEConf0 : %08lx\n",
     80				       read_vpe_c0_vpeconf0());
     81				printk("   VPE%d.Status : %08lx\n",
     82				       i, read_vpe_c0_status());
     83				printk("   VPE%d.EPC : %08lx %pS\n",
     84				       i, read_vpe_c0_epc(),
     85				       (void *) read_vpe_c0_epc());
     86				printk("   VPE%d.Cause : %08lx\n",
     87				       i, read_vpe_c0_cause());
     88				printk("   VPE%d.Config7 : %08lx\n",
     89				       i, read_vpe_c0_config7());
     90				break; /* Next VPE */
     91			}
     92		}
     93	}
     94	printk("-- per-TC State --\n");
     95	for (tc = 0; tc < ntc; tc++) {
     96		settc(tc);
     97		if (read_tc_c0_tcbind() == read_c0_tcbind()) {
     98			/* Are we dumping ourself?  */
     99			haltval = 0; /* Then we're not halted, and mustn't be */
    100			tcstatval = flags; /* And pre-dump TCStatus is flags */
    101			printk("  TC %d (current TC with VPE EPC above)\n", tc);
    102		} else {
    103			haltval = read_tc_c0_tchalt();
    104			write_tc_c0_tchalt(1);
    105			tcstatval = read_tc_c0_tcstatus();
    106			printk("  TC %d\n", tc);
    107		}
    108		printk("   TCStatus : %08lx\n", tcstatval);
    109		printk("   TCBind : %08lx\n", read_tc_c0_tcbind());
    110		printk("   TCRestart : %08lx %pS\n",
    111		       read_tc_c0_tcrestart(), (void *) read_tc_c0_tcrestart());
    112		printk("   TCHalt : %08lx\n", haltval);
    113		printk("   TCContext : %08lx\n", read_tc_c0_tccontext());
    114		if (!haltval)
    115			write_tc_c0_tchalt(0);
    116	}
    117	printk("===========================\n");
    118	evpe(vpflags);
    119	local_irq_restore(flags);
    120}
    121
    122static int mt_opt_rpsctl = -1;
    123static int mt_opt_nblsu = -1;
    124static int mt_opt_forceconfig7;
    125static int mt_opt_config7 = -1;
    126
    127static int __init rpsctl_set(char *str)
    128{
    129	get_option(&str, &mt_opt_rpsctl);
    130	return 1;
    131}
    132__setup("rpsctl=", rpsctl_set);
    133
    134static int __init nblsu_set(char *str)
    135{
    136	get_option(&str, &mt_opt_nblsu);
    137	return 1;
    138}
    139__setup("nblsu=", nblsu_set);
    140
    141static int __init config7_set(char *str)
    142{
    143	get_option(&str, &mt_opt_config7);
    144	mt_opt_forceconfig7 = 1;
    145	return 1;
    146}
    147__setup("config7=", config7_set);
    148
    149static unsigned int itc_base;
    150
    151static int __init set_itc_base(char *str)
    152{
    153	get_option(&str, &itc_base);
    154	return 1;
    155}
    156
    157__setup("itcbase=", set_itc_base);
    158
    159void mips_mt_set_cpuoptions(void)
    160{
    161	unsigned int oconfig7 = read_c0_config7();
    162	unsigned int nconfig7 = oconfig7;
    163
    164	if (mt_opt_rpsctl >= 0) {
    165		printk("34K return prediction stack override set to %d.\n",
    166			mt_opt_rpsctl);
    167		if (mt_opt_rpsctl)
    168			nconfig7 |= (1 << 2);
    169		else
    170			nconfig7 &= ~(1 << 2);
    171	}
    172	if (mt_opt_nblsu >= 0) {
    173		printk("34K ALU/LSU sync override set to %d.\n", mt_opt_nblsu);
    174		if (mt_opt_nblsu)
    175			nconfig7 |= (1 << 5);
    176		else
    177			nconfig7 &= ~(1 << 5);
    178	}
    179	if (mt_opt_forceconfig7) {
    180		printk("CP0.Config7 forced to 0x%08x.\n", mt_opt_config7);
    181		nconfig7 = mt_opt_config7;
    182	}
    183	if (oconfig7 != nconfig7) {
    184		__asm__ __volatile("sync");
    185		write_c0_config7(nconfig7);
    186		ehb();
    187		printk("Config7: 0x%08x\n", read_c0_config7());
    188	}
    189
    190	if (itc_base != 0) {
    191		/*
    192		 * Configure ITC mapping.  This code is very
    193		 * specific to the 34K core family, which uses
    194		 * a special mode bit ("ITC") in the ErrCtl
    195		 * register to enable access to ITC control
    196		 * registers via cache "tag" operations.
    197		 */
    198		unsigned long ectlval;
    199		unsigned long itcblkgrn;
    200
    201		/* ErrCtl register is known as "ecc" to Linux */
    202		ectlval = read_c0_ecc();
    203		write_c0_ecc(ectlval | (0x1 << 26));
    204		ehb();
    205#define INDEX_0 (0x80000000)
    206#define INDEX_8 (0x80000008)
    207		/* Read "cache tag" for Dcache pseudo-index 8 */
    208		cache_op(Index_Load_Tag_D, INDEX_8);
    209		ehb();
    210		itcblkgrn = read_c0_dtaglo();
    211		itcblkgrn &= 0xfffe0000;
    212		/* Set for 128 byte pitch of ITC cells */
    213		itcblkgrn |= 0x00000c00;
    214		/* Stage in Tag register */
    215		write_c0_dtaglo(itcblkgrn);
    216		ehb();
    217		/* Write out to ITU with CACHE op */
    218		cache_op(Index_Store_Tag_D, INDEX_8);
    219		/* Now set base address, and turn ITC on with 0x1 bit */
    220		write_c0_dtaglo((itc_base & 0xfffffc00) | 0x1 );
    221		ehb();
    222		/* Write out to ITU with CACHE op */
    223		cache_op(Index_Store_Tag_D, INDEX_0);
    224		write_c0_ecc(ectlval);
    225		ehb();
    226		printk("Mapped %ld ITC cells starting at 0x%08x\n",
    227			((itcblkgrn & 0x7fe00000) >> 20), itc_base);
    228	}
    229}
    230
    231struct class *mt_class;
    232
    233static int __init mt_init(void)
    234{
    235	struct class *mtc;
    236
    237	mtc = class_create(THIS_MODULE, "mt");
    238	if (IS_ERR(mtc))
    239		return PTR_ERR(mtc);
    240
    241	mt_class = mtc;
    242
    243	return 0;
    244}
    245
    246subsys_initcall(mt_init);