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

init.c (5044B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2009 Lemote Inc.
      4 * Author: Wu Zhangjin, wuzhangjin@gmail.com
      5 */
      6
      7#include <linux/irqchip.h>
      8#include <linux/logic_pio.h>
      9#include <linux/memblock.h>
     10#include <linux/of.h>
     11#include <linux/of_address.h>
     12#include <asm/bootinfo.h>
     13#include <asm/traps.h>
     14#include <asm/smp-ops.h>
     15#include <asm/cacheflush.h>
     16#include <asm/fw/fw.h>
     17
     18#include <loongson.h>
     19#include <boot_param.h>
     20
     21#define NODE_ID_OFFSET_ADDR	((void __iomem *)TO_UNCAC(0x1001041c))
     22
     23u32 node_id_offset;
     24
     25static void __init mips_nmi_setup(void)
     26{
     27	void *base;
     28
     29	base = (void *)(CAC_BASE + 0x380);
     30	memcpy(base, except_vec_nmi, 0x80);
     31	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
     32}
     33
     34void ls7a_early_config(void)
     35{
     36	node_id_offset = ((readl(NODE_ID_OFFSET_ADDR) >> 8) & 0x1f) + 36;
     37}
     38
     39void rs780e_early_config(void)
     40{
     41	node_id_offset = 37;
     42}
     43
     44void virtual_early_config(void)
     45{
     46	node_id_offset = 44;
     47}
     48
     49void __init szmem(unsigned int node)
     50{
     51	u32 i, mem_type;
     52	static unsigned long num_physpages;
     53	u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
     54
     55	/* Otherwise come from DTB */
     56	if (loongson_sysconf.fw_interface != LOONGSON_LEFI)
     57		return;
     58
     59	/* Parse memory information and activate */
     60	for (i = 0; i < loongson_memmap->nr_map; i++) {
     61		node_id = loongson_memmap->map[i].node_id;
     62		if (node_id != node)
     63			continue;
     64
     65		mem_type = loongson_memmap->map[i].mem_type;
     66		mem_size = loongson_memmap->map[i].mem_size;
     67		mem_start = loongson_memmap->map[i].mem_start;
     68
     69		switch (mem_type) {
     70		case SYSTEM_RAM_LOW:
     71		case SYSTEM_RAM_HIGH:
     72			start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
     73			node_psize = (mem_size << 20) >> PAGE_SHIFT;
     74			end_pfn  = start_pfn + node_psize;
     75			num_physpages += node_psize;
     76			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
     77				(u32)node_id, mem_type, mem_start, mem_size);
     78			pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
     79				start_pfn, end_pfn, num_physpages);
     80			memblock_add_node(PFN_PHYS(start_pfn),
     81					  PFN_PHYS(node_psize), node,
     82					  MEMBLOCK_NONE);
     83			break;
     84		case SYSTEM_RAM_RESERVED:
     85			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
     86				(u32)node_id, mem_type, mem_start, mem_size);
     87			memblock_reserve(((node_id << 44) + mem_start), mem_size << 20);
     88			break;
     89		}
     90	}
     91}
     92
     93#ifndef CONFIG_NUMA
     94static void __init prom_init_memory(void)
     95{
     96	szmem(0);
     97}
     98#endif
     99
    100void __init prom_init(void)
    101{
    102	fw_init_cmdline();
    103
    104	if (fw_arg2 == 0 || (fdt_magic(fw_arg2) == FDT_MAGIC)) {
    105		loongson_sysconf.fw_interface = LOONGSON_DTB;
    106		prom_dtb_init_env();
    107	} else {
    108		loongson_sysconf.fw_interface = LOONGSON_LEFI;
    109		prom_lefi_init_env();
    110	}
    111
    112	/* init base address of io space */
    113	set_io_port_base(PCI_IOBASE);
    114
    115	if (loongson_sysconf.early_config)
    116		loongson_sysconf.early_config();
    117
    118#ifdef CONFIG_NUMA
    119	prom_init_numa_memory();
    120#else
    121	prom_init_memory();
    122#endif
    123
    124	/* Hardcode to CPU UART 0 */
    125	if ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64R)
    126		setup_8250_early_printk_port(TO_UNCAC(LOONGSON_REG_BASE), 0, 1024);
    127	else
    128		setup_8250_early_printk_port(TO_UNCAC(LOONGSON_REG_BASE + 0x1e0), 0, 1024);
    129
    130	register_smp_ops(&loongson3_smp_ops);
    131	board_nmi_handler_setup = mips_nmi_setup;
    132}
    133
    134static int __init add_legacy_isa_io(struct fwnode_handle *fwnode, resource_size_t hw_start,
    135				    resource_size_t size)
    136{
    137	int ret = 0;
    138	struct logic_pio_hwaddr *range;
    139	unsigned long vaddr;
    140
    141	range = kzalloc(sizeof(*range), GFP_ATOMIC);
    142	if (!range)
    143		return -ENOMEM;
    144
    145	range->fwnode = fwnode;
    146	range->size = size = round_up(size, PAGE_SIZE);
    147	range->hw_start = hw_start;
    148	range->flags = LOGIC_PIO_CPU_MMIO;
    149
    150	ret = logic_pio_register_range(range);
    151	if (ret) {
    152		kfree(range);
    153		return ret;
    154	}
    155
    156	/* Legacy ISA must placed at the start of PCI_IOBASE */
    157	if (range->io_start != 0) {
    158		logic_pio_unregister_range(range);
    159		kfree(range);
    160		return -EINVAL;
    161	}
    162
    163	vaddr = PCI_IOBASE + range->io_start;
    164
    165	ioremap_page_range(vaddr, vaddr + size, hw_start, pgprot_device(PAGE_KERNEL));
    166
    167	return 0;
    168}
    169
    170static __init void reserve_pio_range(void)
    171{
    172	struct device_node *np;
    173
    174	for_each_node_by_name(np, "isa") {
    175		struct of_range range;
    176		struct of_range_parser parser;
    177
    178		pr_info("ISA Bridge: %pOF\n", np);
    179
    180		if (of_range_parser_init(&parser, np)) {
    181			pr_info("Failed to parse resources.\n");
    182			of_node_put(np);
    183			break;
    184		}
    185
    186		for_each_of_range(&parser, &range) {
    187			switch (range.flags & IORESOURCE_TYPE_BITS) {
    188			case IORESOURCE_IO:
    189				pr_info(" IO 0x%016llx..0x%016llx  ->  0x%016llx\n",
    190					range.cpu_addr,
    191					range.cpu_addr + range.size - 1,
    192					range.bus_addr);
    193				if (add_legacy_isa_io(&np->fwnode, range.cpu_addr, range.size))
    194					pr_warn("Failed to reserve legacy IO in Logic PIO\n");
    195				break;
    196			case IORESOURCE_MEM:
    197				pr_info(" MEM 0x%016llx..0x%016llx  ->  0x%016llx\n",
    198					range.cpu_addr,
    199					range.cpu_addr + range.size - 1,
    200					range.bus_addr);
    201				break;
    202			}
    203		}
    204	}
    205}
    206
    207void __init arch_init_irq(void)
    208{
    209	reserve_pio_range();
    210	irqchip_init();
    211}