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_32.c (9174B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  linux/arch/sparc/kernel/setup.c
      4 *
      5 *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
      6 *  Copyright (C) 2000  Anton Blanchard (anton@samba.org)
      7 */
      8
      9#include <linux/errno.h>
     10#include <linux/sched.h>
     11#include <linux/kernel.h>
     12#include <linux/mm.h>
     13#include <linux/stddef.h>
     14#include <linux/unistd.h>
     15#include <linux/ptrace.h>
     16#include <linux/slab.h>
     17#include <linux/initrd.h>
     18#include <asm/smp.h>
     19#include <linux/user.h>
     20#include <linux/screen_info.h>
     21#include <linux/delay.h>
     22#include <linux/fs.h>
     23#include <linux/seq_file.h>
     24#include <linux/syscalls.h>
     25#include <linux/kdev_t.h>
     26#include <linux/major.h>
     27#include <linux/string.h>
     28#include <linux/init.h>
     29#include <linux/interrupt.h>
     30#include <linux/console.h>
     31#include <linux/spinlock.h>
     32#include <linux/root_dev.h>
     33#include <linux/cpu.h>
     34#include <linux/kdebug.h>
     35#include <linux/export.h>
     36#include <linux/start_kernel.h>
     37#include <uapi/linux/mount.h>
     38
     39#include <asm/io.h>
     40#include <asm/processor.h>
     41#include <asm/oplib.h>
     42#include <asm/page.h>
     43#include <asm/traps.h>
     44#include <asm/vaddrs.h>
     45#include <asm/mbus.h>
     46#include <asm/idprom.h>
     47#include <asm/cpudata.h>
     48#include <asm/setup.h>
     49#include <asm/cacheflush.h>
     50#include <asm/sections.h>
     51
     52#include "kernel.h"
     53
     54struct screen_info screen_info = {
     55	0, 0,			/* orig-x, orig-y */
     56	0,			/* unused */
     57	0,			/* orig-video-page */
     58	0,			/* orig-video-mode */
     59	128,			/* orig-video-cols */
     60	0,0,0,			/* ega_ax, ega_bx, ega_cx */
     61	54,			/* orig-video-lines */
     62	0,                      /* orig-video-isVGA */
     63	16                      /* orig-video-points */
     64};
     65
     66/* Typing sync at the prom prompt calls the function pointed to by
     67 * romvec->pv_synchook which I set to the following function.
     68 * This should sync all filesystems and return, for now it just
     69 * prints out pretty messages and returns.
     70 */
     71
     72/* Pretty sick eh? */
     73static void prom_sync_me(void)
     74{
     75	unsigned long prom_tbr, flags;
     76
     77	/* XXX Badly broken. FIX! - Anton */
     78	local_irq_save(flags);
     79	__asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr));
     80	__asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
     81			     "nop\n\t"
     82			     "nop\n\t"
     83			     "nop\n\t" : : "r" (&trapbase));
     84
     85	prom_printf("PROM SYNC COMMAND...\n");
     86	show_free_areas(0, NULL);
     87	if (!is_idle_task(current)) {
     88		local_irq_enable();
     89		ksys_sync();
     90		local_irq_disable();
     91	}
     92	prom_printf("Returning to prom\n");
     93
     94	__asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
     95			     "nop\n\t"
     96			     "nop\n\t"
     97			     "nop\n\t" : : "r" (prom_tbr));
     98	local_irq_restore(flags);
     99}
    100
    101static unsigned int boot_flags __initdata = 0;
    102#define BOOTME_DEBUG  0x1
    103
    104/* Exported for mm/init.c:paging_init. */
    105unsigned long cmdline_memory_size __initdata = 0;
    106
    107/* which CPU booted us (0xff = not set) */
    108unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */
    109
    110static void
    111prom_console_write(struct console *con, const char *s, unsigned int n)
    112{
    113	prom_write(s, n);
    114}
    115
    116static struct console prom_early_console = {
    117	.name =		"earlyprom",
    118	.write =	prom_console_write,
    119	.flags =	CON_PRINTBUFFER | CON_BOOT,
    120	.index =	-1,
    121};
    122
    123/* 
    124 * Process kernel command line switches that are specific to the
    125 * SPARC or that require special low-level processing.
    126 */
    127static void __init process_switch(char c)
    128{
    129	switch (c) {
    130	case 'd':
    131		boot_flags |= BOOTME_DEBUG;
    132		break;
    133	case 's':
    134		break;
    135	case 'h':
    136		prom_printf("boot_flags_init: Halt!\n");
    137		prom_halt();
    138		break;
    139	case 'p':
    140		prom_early_console.flags &= ~CON_BOOT;
    141		break;
    142	default:
    143		printk("Unknown boot switch (-%c)\n", c);
    144		break;
    145	}
    146}
    147
    148static void __init boot_flags_init(char *commands)
    149{
    150	while (*commands) {
    151		/* Move to the start of the next "argument". */
    152		while (*commands == ' ')
    153			commands++;
    154
    155		/* Process any command switches, otherwise skip it. */
    156		if (*commands == '\0')
    157			break;
    158		if (*commands == '-') {
    159			commands++;
    160			while (*commands && *commands != ' ')
    161				process_switch(*commands++);
    162			continue;
    163		}
    164		if (!strncmp(commands, "mem=", 4)) {
    165			/*
    166			 * "mem=XXX[kKmM] overrides the PROM-reported
    167			 * memory size.
    168			 */
    169			cmdline_memory_size = simple_strtoul(commands + 4,
    170						     &commands, 0);
    171			if (*commands == 'K' || *commands == 'k') {
    172				cmdline_memory_size <<= 10;
    173				commands++;
    174			} else if (*commands=='M' || *commands=='m') {
    175				cmdline_memory_size <<= 20;
    176				commands++;
    177			}
    178		}
    179		while (*commands && *commands != ' ')
    180			commands++;
    181	}
    182}
    183
    184extern unsigned short root_flags;
    185extern unsigned short root_dev;
    186extern unsigned short ram_flags;
    187#define RAMDISK_IMAGE_START_MASK	0x07FF
    188#define RAMDISK_PROMPT_FLAG		0x8000
    189#define RAMDISK_LOAD_FLAG		0x4000
    190
    191extern int root_mountflags;
    192
    193char reboot_command[COMMAND_LINE_SIZE];
    194
    195struct cpuid_patch_entry {
    196	unsigned int	addr;
    197	unsigned int	sun4d[3];
    198	unsigned int	leon[3];
    199};
    200extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
    201
    202static void __init per_cpu_patch(void)
    203{
    204	struct cpuid_patch_entry *p;
    205
    206	if (sparc_cpu_model == sun4m) {
    207		/* Nothing to do, this is what the unpatched code
    208		 * targets.
    209		 */
    210		return;
    211	}
    212
    213	p = &__cpuid_patch;
    214	while (p < &__cpuid_patch_end) {
    215		unsigned long addr = p->addr;
    216		unsigned int *insns;
    217
    218		switch (sparc_cpu_model) {
    219		case sun4d:
    220			insns = &p->sun4d[0];
    221			break;
    222
    223		case sparc_leon:
    224			insns = &p->leon[0];
    225			break;
    226		default:
    227			prom_printf("Unknown cpu type, halting.\n");
    228			prom_halt();
    229		}
    230		*(unsigned int *) (addr + 0) = insns[0];
    231		flushi(addr + 0);
    232		*(unsigned int *) (addr + 4) = insns[1];
    233		flushi(addr + 4);
    234		*(unsigned int *) (addr + 8) = insns[2];
    235		flushi(addr + 8);
    236
    237		p++;
    238	}
    239}
    240
    241struct leon_1insn_patch_entry {
    242	unsigned int addr;
    243	unsigned int insn;
    244};
    245
    246enum sparc_cpu sparc_cpu_model;
    247EXPORT_SYMBOL(sparc_cpu_model);
    248
    249static __init void leon_patch(void)
    250{
    251	struct leon_1insn_patch_entry *start = (void *)__leon_1insn_patch;
    252	struct leon_1insn_patch_entry *end = (void *)__leon_1insn_patch_end;
    253
    254	/* Default instruction is leon - no patching */
    255	if (sparc_cpu_model == sparc_leon)
    256		return;
    257
    258	while (start < end) {
    259		unsigned long addr = start->addr;
    260
    261		*(unsigned int *)(addr) = start->insn;
    262		flushi(addr);
    263
    264		start++;
    265	}
    266}
    267
    268struct tt_entry *sparc_ttable;
    269
    270/* Called from head_32.S - before we have setup anything
    271 * in the kernel. Be very careful with what you do here.
    272 */
    273void __init sparc32_start_kernel(struct linux_romvec *rp)
    274{
    275	prom_init(rp);
    276
    277	/* Set sparc_cpu_model */
    278	sparc_cpu_model = sun_unknown;
    279	if (!strcmp(&cputypval[0], "sun4m"))
    280		sparc_cpu_model = sun4m;
    281	if (!strcmp(&cputypval[0], "sun4s"))
    282		sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
    283	if (!strcmp(&cputypval[0], "sun4d"))
    284		sparc_cpu_model = sun4d;
    285	if (!strcmp(&cputypval[0], "sun4e"))
    286		sparc_cpu_model = sun4e;
    287	if (!strcmp(&cputypval[0], "sun4u"))
    288		sparc_cpu_model = sun4u;
    289	if (!strncmp(&cputypval[0], "leon" , 4))
    290		sparc_cpu_model = sparc_leon;
    291
    292	leon_patch();
    293	start_kernel();
    294}
    295
    296void __init setup_arch(char **cmdline_p)
    297{
    298	int i;
    299	unsigned long highest_paddr;
    300
    301	sparc_ttable = &trapbase;
    302
    303	/* Initialize PROM console and command line. */
    304	*cmdline_p = prom_getbootargs();
    305	strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
    306	parse_early_param();
    307
    308	boot_flags_init(*cmdline_p);
    309
    310	register_console(&prom_early_console);
    311
    312	switch(sparc_cpu_model) {
    313	case sun4m:
    314		pr_info("ARCH: SUN4M\n");
    315		break;
    316	case sun4d:
    317		pr_info("ARCH: SUN4D\n");
    318		break;
    319	case sun4e:
    320		pr_info("ARCH: SUN4E\n");
    321		break;
    322	case sun4u:
    323		pr_info("ARCH: SUN4U\n");
    324		break;
    325	case sparc_leon:
    326		pr_info("ARCH: LEON\n");
    327		break;
    328	default:
    329		pr_info("ARCH: UNKNOWN!\n");
    330		break;
    331	}
    332
    333	idprom_init();
    334	load_mmu();
    335
    336	phys_base = 0xffffffffUL;
    337	highest_paddr = 0UL;
    338	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
    339		unsigned long top;
    340
    341		if (sp_banks[i].base_addr < phys_base)
    342			phys_base = sp_banks[i].base_addr;
    343		top = sp_banks[i].base_addr +
    344			sp_banks[i].num_bytes;
    345		if (highest_paddr < top)
    346			highest_paddr = top;
    347	}
    348	pfn_base = phys_base >> PAGE_SHIFT;
    349
    350	if (!root_flags)
    351		root_mountflags &= ~MS_RDONLY;
    352	ROOT_DEV = old_decode_dev(root_dev);
    353#ifdef CONFIG_BLK_DEV_RAM
    354	rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
    355#endif
    356
    357	prom_setsync(prom_sync_me);
    358
    359	if((boot_flags & BOOTME_DEBUG) && (linux_dbvec != NULL) &&
    360	   ((*(short *)linux_dbvec) != -1)) {
    361		printk("Booted under KADB. Syncing trap table.\n");
    362		(*(linux_dbvec->teach_debugger))();
    363	}
    364
    365	/* Run-time patch instructions to match the cpu model */
    366	per_cpu_patch();
    367
    368	paging_init();
    369
    370	smp_setup_cpu_possible_map();
    371}
    372
    373extern int stop_a_enabled;
    374
    375void sun_do_break(void)
    376{
    377	if (!stop_a_enabled)
    378		return;
    379
    380	printk("\n");
    381	flush_user_windows();
    382
    383	prom_cmdline();
    384}
    385EXPORT_SYMBOL(sun_do_break);
    386
    387int stop_a_enabled = 1;
    388
    389static int __init topology_init(void)
    390{
    391	int i, ncpus, err;
    392
    393	/* Count the number of physically present processors in
    394	 * the machine, even on uniprocessor, so that /proc/cpuinfo
    395	 * output is consistent with 2.4.x
    396	 */
    397	ncpus = 0;
    398	while (!cpu_find_by_instance(ncpus, NULL, NULL))
    399		ncpus++;
    400	ncpus_probed = ncpus;
    401
    402	err = 0;
    403	for_each_online_cpu(i) {
    404		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
    405		if (!p)
    406			err = -ENOMEM;
    407		else
    408			register_cpu(p, i);
    409	}
    410
    411	return err;
    412}
    413
    414subsys_initcall(topology_init);