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

setup.c (10726B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2006-2007 PA Semi, Inc
      4 *
      5 * Authors: Kip Walker, PA Semi
      6 *	    Olof Johansson, PA Semi
      7 *
      8 * Maintained by: Olof Johansson <olof@lixom.net>
      9 *
     10 * Based on arch/powerpc/platforms/maple/setup.c
     11 */
     12
     13#include <linux/errno.h>
     14#include <linux/kernel.h>
     15#include <linux/delay.h>
     16#include <linux/console.h>
     17#include <linux/export.h>
     18#include <linux/pci.h>
     19#include <linux/of_platform.h>
     20#include <linux/gfp.h>
     21#include <linux/irqdomain.h>
     22
     23#include <asm/iommu.h>
     24#include <asm/machdep.h>
     25#include <asm/i8259.h>
     26#include <asm/mpic.h>
     27#include <asm/smp.h>
     28#include <asm/time.h>
     29#include <asm/mmu.h>
     30#include <asm/debug.h>
     31
     32#include <pcmcia/ss.h>
     33#include <pcmcia/cistpl.h>
     34#include <pcmcia/ds.h>
     35
     36#include "pasemi.h"
     37
     38/* SDC reset register, must be pre-mapped at reset time */
     39static void __iomem *reset_reg;
     40
     41/* Various error status registers, must be pre-mapped at MCE time */
     42
     43#define MAX_MCE_REGS	32
     44struct mce_regs {
     45	char *name;
     46	void __iomem *addr;
     47};
     48
     49static struct mce_regs mce_regs[MAX_MCE_REGS];
     50static int num_mce_regs;
     51static int nmi_virq = 0;
     52
     53
     54static void __noreturn pas_restart(char *cmd)
     55{
     56	/* Need to put others cpu in hold loop so they're not sleeping */
     57	smp_send_stop();
     58	udelay(10000);
     59	printk("Restarting...\n");
     60	while (1)
     61		out_le32(reset_reg, 0x6000000);
     62}
     63
     64#ifdef CONFIG_PPC_PASEMI_NEMO
     65void pas_shutdown(void)
     66{
     67	/* Set the PLD bit that makes the SB600 think the power button is being pressed */
     68	void __iomem *pld_map = ioremap(0xf5000000,4096);
     69	while (1)
     70		out_8(pld_map+7,0x01);
     71}
     72
     73/* RTC platform device structure as is not in device tree */
     74static struct resource rtc_resource[] = {{
     75	.name = "rtc",
     76	.start = 0x70,
     77	.end = 0x71,
     78	.flags = IORESOURCE_IO,
     79}, {
     80	.name = "rtc",
     81	.start = 8,
     82	.end = 8,
     83	.flags = IORESOURCE_IRQ,
     84}};
     85
     86static inline void nemo_init_rtc(void)
     87{
     88	platform_device_register_simple("rtc_cmos", -1, rtc_resource, 2);
     89}
     90
     91#else
     92
     93static inline void nemo_init_rtc(void)
     94{
     95}
     96#endif
     97
     98#ifdef CONFIG_SMP
     99static arch_spinlock_t timebase_lock;
    100static unsigned long timebase;
    101
    102static void pas_give_timebase(void)
    103{
    104	unsigned long flags;
    105
    106	local_irq_save(flags);
    107	hard_irq_disable();
    108	arch_spin_lock(&timebase_lock);
    109	mtspr(SPRN_TBCTL, TBCTL_FREEZE);
    110	isync();
    111	timebase = get_tb();
    112	arch_spin_unlock(&timebase_lock);
    113
    114	while (timebase)
    115		barrier();
    116	mtspr(SPRN_TBCTL, TBCTL_RESTART);
    117	local_irq_restore(flags);
    118}
    119
    120static void pas_take_timebase(void)
    121{
    122	while (!timebase)
    123		smp_rmb();
    124
    125	arch_spin_lock(&timebase_lock);
    126	set_tb(timebase >> 32, timebase & 0xffffffff);
    127	timebase = 0;
    128	arch_spin_unlock(&timebase_lock);
    129}
    130
    131static struct smp_ops_t pas_smp_ops = {
    132	.probe		= smp_mpic_probe,
    133	.message_pass	= smp_mpic_message_pass,
    134	.kick_cpu	= smp_generic_kick_cpu,
    135	.setup_cpu	= smp_mpic_setup_cpu,
    136	.give_timebase	= pas_give_timebase,
    137	.take_timebase	= pas_take_timebase,
    138};
    139#endif /* CONFIG_SMP */
    140
    141static void __init pas_setup_arch(void)
    142{
    143#ifdef CONFIG_SMP
    144	/* Setup SMP callback */
    145	smp_ops = &pas_smp_ops;
    146#endif
    147
    148	/* Remap SDC register for doing reset */
    149	/* XXXOJN This should maybe come out of the device tree */
    150	reset_reg = ioremap(0xfc101100, 4);
    151}
    152
    153static int __init pas_setup_mce_regs(void)
    154{
    155	struct pci_dev *dev;
    156	int reg;
    157
    158	/* Remap various SoC status registers for use by the MCE handler */
    159
    160	reg = 0;
    161
    162	dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa00a, NULL);
    163	while (dev && reg < MAX_MCE_REGS) {
    164		mce_regs[reg].name = kasprintf(GFP_KERNEL,
    165						"mc%d_mcdebug_errsta", reg);
    166		mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x730);
    167		dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa00a, dev);
    168		reg++;
    169	}
    170
    171	dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
    172	if (dev && reg+4 < MAX_MCE_REGS) {
    173		mce_regs[reg].name = "iobdbg_IntStatus1";
    174		mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x438);
    175		reg++;
    176		mce_regs[reg].name = "iobdbg_IOCTbusIntDbgReg";
    177		mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x454);
    178		reg++;
    179		mce_regs[reg].name = "iobiom_IntStatus";
    180		mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0xc10);
    181		reg++;
    182		mce_regs[reg].name = "iobiom_IntDbgReg";
    183		mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0xc1c);
    184		reg++;
    185	}
    186
    187	dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa009, NULL);
    188	if (dev && reg+2 < MAX_MCE_REGS) {
    189		mce_regs[reg].name = "l2csts_IntStatus";
    190		mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x200);
    191		reg++;
    192		mce_regs[reg].name = "l2csts_Cnt";
    193		mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x214);
    194		reg++;
    195	}
    196
    197	num_mce_regs = reg;
    198
    199	return 0;
    200}
    201machine_device_initcall(pasemi, pas_setup_mce_regs);
    202
    203#ifdef CONFIG_PPC_PASEMI_NEMO
    204static void sb600_8259_cascade(struct irq_desc *desc)
    205{
    206	struct irq_chip *chip = irq_desc_get_chip(desc);
    207	unsigned int cascade_irq = i8259_irq();
    208
    209	if (cascade_irq)
    210		generic_handle_irq(cascade_irq);
    211
    212	chip->irq_eoi(&desc->irq_data);
    213}
    214
    215static void __init nemo_init_IRQ(struct mpic *mpic)
    216{
    217	struct device_node *np;
    218	int gpio_virq;
    219	/* Connect the SB600's legacy i8259 controller */
    220	np = of_find_node_by_path("/pxp@0,e0000000");
    221	i8259_init(np, 0);
    222	of_node_put(np);
    223
    224	gpio_virq = irq_create_mapping(NULL, 3);
    225	irq_set_irq_type(gpio_virq, IRQ_TYPE_LEVEL_HIGH);
    226	irq_set_chained_handler(gpio_virq, sb600_8259_cascade);
    227	mpic_unmask_irq(irq_get_irq_data(gpio_virq));
    228
    229	irq_set_default_host(mpic->irqhost);
    230}
    231
    232#else
    233
    234static inline void nemo_init_IRQ(struct mpic *mpic)
    235{
    236}
    237#endif
    238
    239static __init void pas_init_IRQ(void)
    240{
    241	struct device_node *np;
    242	struct device_node *root, *mpic_node;
    243	unsigned long openpic_addr;
    244	const unsigned int *opprop;
    245	int naddr, opplen;
    246	int mpic_flags;
    247	const unsigned int *nmiprop;
    248	struct mpic *mpic;
    249
    250	mpic_node = NULL;
    251
    252	for_each_node_by_type(np, "interrupt-controller")
    253		if (of_device_is_compatible(np, "open-pic")) {
    254			mpic_node = np;
    255			break;
    256		}
    257	if (!mpic_node)
    258		for_each_node_by_type(np, "open-pic") {
    259			mpic_node = np;
    260			break;
    261		}
    262	if (!mpic_node) {
    263		pr_err("Failed to locate the MPIC interrupt controller\n");
    264		return;
    265	}
    266
    267	/* Find address list in /platform-open-pic */
    268	root = of_find_node_by_path("/");
    269	naddr = of_n_addr_cells(root);
    270	opprop = of_get_property(root, "platform-open-pic", &opplen);
    271	if (!opprop) {
    272		pr_err("No platform-open-pic property.\n");
    273		of_node_put(root);
    274		return;
    275	}
    276	openpic_addr = of_read_number(opprop, naddr);
    277	pr_debug("OpenPIC addr: %lx\n", openpic_addr);
    278
    279	mpic_flags = MPIC_LARGE_VECTORS | MPIC_NO_BIAS | MPIC_NO_RESET;
    280
    281	nmiprop = of_get_property(mpic_node, "nmi-source", NULL);
    282	if (nmiprop)
    283		mpic_flags |= MPIC_ENABLE_MCK;
    284
    285	mpic = mpic_alloc(mpic_node, openpic_addr,
    286			  mpic_flags, 0, 0, "PASEMI-OPIC");
    287	BUG_ON(!mpic);
    288
    289	mpic_assign_isu(mpic, 0, mpic->paddr + 0x10000);
    290	mpic_init(mpic);
    291	/* The NMI/MCK source needs to be prio 15 */
    292	if (nmiprop) {
    293		nmi_virq = irq_create_mapping(NULL, *nmiprop);
    294		mpic_irq_set_priority(nmi_virq, 15);
    295		irq_set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
    296		mpic_unmask_irq(irq_get_irq_data(nmi_virq));
    297	}
    298
    299	nemo_init_IRQ(mpic);
    300
    301	of_node_put(mpic_node);
    302	of_node_put(root);
    303}
    304
    305static void __init pas_progress(char *s, unsigned short hex)
    306{
    307	printk("[%04x] : %s\n", hex, s ? s : "");
    308}
    309
    310
    311static int pas_machine_check_handler(struct pt_regs *regs)
    312{
    313	int cpu = smp_processor_id();
    314	unsigned long srr0, srr1, dsisr;
    315	int dump_slb = 0;
    316	int i;
    317
    318	srr0 = regs->nip;
    319	srr1 = regs->msr;
    320
    321	if (nmi_virq && mpic_get_mcirq() == nmi_virq) {
    322		pr_err("NMI delivered\n");
    323		debugger(regs);
    324		mpic_end_irq(irq_get_irq_data(nmi_virq));
    325		goto out;
    326	}
    327
    328	dsisr = mfspr(SPRN_DSISR);
    329	pr_err("Machine Check on CPU %d\n", cpu);
    330	pr_err("SRR0  0x%016lx SRR1 0x%016lx\n", srr0, srr1);
    331	pr_err("DSISR 0x%016lx DAR  0x%016lx\n", dsisr, regs->dar);
    332	pr_err("BER   0x%016lx MER  0x%016lx\n", mfspr(SPRN_PA6T_BER),
    333		mfspr(SPRN_PA6T_MER));
    334	pr_err("IER   0x%016lx DER  0x%016lx\n", mfspr(SPRN_PA6T_IER),
    335		mfspr(SPRN_PA6T_DER));
    336	pr_err("Cause:\n");
    337
    338	if (srr1 & 0x200000)
    339		pr_err("Signalled by SDC\n");
    340
    341	if (srr1 & 0x100000) {
    342		pr_err("Load/Store detected error:\n");
    343		if (dsisr & 0x8000)
    344			pr_err("D-cache ECC double-bit error or bus error\n");
    345		if (dsisr & 0x4000)
    346			pr_err("LSU snoop response error\n");
    347		if (dsisr & 0x2000) {
    348			pr_err("MMU SLB multi-hit or invalid B field\n");
    349			dump_slb = 1;
    350		}
    351		if (dsisr & 0x1000)
    352			pr_err("Recoverable Duptags\n");
    353		if (dsisr & 0x800)
    354			pr_err("Recoverable D-cache parity error count overflow\n");
    355		if (dsisr & 0x400)
    356			pr_err("TLB parity error count overflow\n");
    357	}
    358
    359	if (srr1 & 0x80000)
    360		pr_err("Bus Error\n");
    361
    362	if (srr1 & 0x40000) {
    363		pr_err("I-side SLB multiple hit\n");
    364		dump_slb = 1;
    365	}
    366
    367	if (srr1 & 0x20000)
    368		pr_err("I-cache parity error hit\n");
    369
    370	if (num_mce_regs == 0)
    371		pr_err("No MCE registers mapped yet, can't dump\n");
    372	else
    373		pr_err("SoC debug registers:\n");
    374
    375	for (i = 0; i < num_mce_regs; i++)
    376		pr_err("%s: 0x%08x\n", mce_regs[i].name,
    377			in_le32(mce_regs[i].addr));
    378
    379	if (dump_slb) {
    380		unsigned long e, v;
    381		int i;
    382
    383		pr_err("slb contents:\n");
    384		for (i = 0; i < mmu_slb_size; i++) {
    385			asm volatile("slbmfee  %0,%1" : "=r" (e) : "r" (i));
    386			asm volatile("slbmfev  %0,%1" : "=r" (v) : "r" (i));
    387			pr_err("%02d %016lx %016lx\n", i, e, v);
    388		}
    389	}
    390
    391out:
    392	/* SRR1[62] is from MSR[62] if recoverable, so pass that back */
    393	return !!(srr1 & 0x2);
    394}
    395
    396static const struct of_device_id pasemi_bus_ids[] = {
    397	/* Unfortunately needed for legacy firmwares */
    398	{ .type = "localbus", },
    399	{ .type = "sdc", },
    400	/* These are the proper entries, which newer firmware uses */
    401	{ .compatible = "pasemi,localbus", },
    402	{ .compatible = "pasemi,sdc", },
    403	{},
    404};
    405
    406static int __init pasemi_publish_devices(void)
    407{
    408	/* Publish OF platform devices for SDC and other non-PCI devices */
    409	of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
    410
    411	nemo_init_rtc();
    412
    413	return 0;
    414}
    415machine_device_initcall(pasemi, pasemi_publish_devices);
    416
    417
    418/*
    419 * Called very early, MMU is off, device-tree isn't unflattened
    420 */
    421static int __init pas_probe(void)
    422{
    423	if (!of_machine_is_compatible("PA6T-1682M") &&
    424	    !of_machine_is_compatible("pasemi,pwrficient"))
    425		return 0;
    426
    427#ifdef CONFIG_PPC_PASEMI_NEMO
    428	/*
    429	 * Check for the Nemo motherboard here, if we are running on one
    430	 * change the machine definition to fit
    431	 */
    432	if (of_machine_is_compatible("pasemi,nemo")) {
    433		pm_power_off		= pas_shutdown;
    434		ppc_md.name		= "A-EON Amigaone X1000";
    435	}
    436#endif
    437
    438	iommu_init_early_pasemi();
    439
    440	return 1;
    441}
    442
    443define_machine(pasemi) {
    444	.name			= "PA Semi PWRficient",
    445	.probe			= pas_probe,
    446	.setup_arch		= pas_setup_arch,
    447	.discover_phbs		= pas_pci_init,
    448	.init_IRQ		= pas_init_IRQ,
    449	.get_irq		= mpic_get_irq,
    450	.restart		= pas_restart,
    451	.get_boot_time		= pas_get_boot_time,
    452	.calibrate_decr		= generic_calibrate_decr,
    453	.progress		= pas_progress,
    454	.machine_check_exception = pas_machine_check_handler,
    455};