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

pci-legacy.c (7377B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *
      4 * Copyright (C) 2003, 04, 11 Ralf Baechle (ralf@linux-mips.org)
      5 * Copyright (C) 2011 Wind River Systems,
      6 *   written by Ralf Baechle (ralf@linux-mips.org)
      7 */
      8#include <linux/bug.h>
      9#include <linux/kernel.h>
     10#include <linux/mm.h>
     11#include <linux/memblock.h>
     12#include <linux/export.h>
     13#include <linux/init.h>
     14#include <linux/types.h>
     15#include <linux/pci.h>
     16#include <linux/of_address.h>
     17
     18#include <asm/cpu-info.h>
     19
     20/*
     21 * If PCI_PROBE_ONLY in pci_flags is set, we don't change any PCI resource
     22 * assignments.
     23 */
     24
     25/*
     26 * The PCI controller list.
     27 */
     28static LIST_HEAD(controllers);
     29
     30static int pci_initialized;
     31
     32/*
     33 * We need to avoid collisions with `mirrored' VGA ports
     34 * and other strange ISA hardware, so we always want the
     35 * addresses to be allocated in the 0x000-0x0ff region
     36 * modulo 0x400.
     37 *
     38 * Why? Because some silly external IO cards only decode
     39 * the low 10 bits of the IO address. The 0x00-0xff region
     40 * is reserved for motherboard devices that decode all 16
     41 * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
     42 * but we want to try to avoid allocating at 0x2900-0x2bff
     43 * which might have be mirrored at 0x0100-0x03ff..
     44 */
     45resource_size_t
     46pcibios_align_resource(void *data, const struct resource *res,
     47		       resource_size_t size, resource_size_t align)
     48{
     49	struct pci_dev *dev = data;
     50	struct pci_controller *hose = dev->sysdata;
     51	resource_size_t start = res->start;
     52
     53	if (res->flags & IORESOURCE_IO) {
     54		/* Make sure we start at our min on all hoses */
     55		if (start < PCIBIOS_MIN_IO + hose->io_resource->start)
     56			start = PCIBIOS_MIN_IO + hose->io_resource->start;
     57
     58		/*
     59		 * Put everything into 0x00-0xff region modulo 0x400
     60		 */
     61		if (start & 0x300)
     62			start = (start + 0x3ff) & ~0x3ff;
     63	} else if (res->flags & IORESOURCE_MEM) {
     64		/* Make sure we start at our min on all hoses */
     65		if (start < PCIBIOS_MIN_MEM + hose->mem_resource->start)
     66			start = PCIBIOS_MIN_MEM + hose->mem_resource->start;
     67	}
     68
     69	return start;
     70}
     71
     72static void pcibios_scanbus(struct pci_controller *hose)
     73{
     74	static int next_busno;
     75	static int need_domain_info;
     76	LIST_HEAD(resources);
     77	struct pci_bus *bus;
     78	struct pci_host_bridge *bridge;
     79	int ret;
     80
     81	bridge = pci_alloc_host_bridge(0);
     82	if (!bridge)
     83		return;
     84
     85	if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY))
     86		next_busno = (*hose->get_busno)();
     87
     88	pci_add_resource_offset(&resources,
     89				hose->mem_resource, hose->mem_offset);
     90	pci_add_resource_offset(&resources,
     91				hose->io_resource, hose->io_offset);
     92	list_splice_init(&resources, &bridge->windows);
     93	bridge->dev.parent = NULL;
     94	bridge->sysdata = hose;
     95	bridge->busnr = next_busno;
     96	bridge->ops = hose->pci_ops;
     97	bridge->swizzle_irq = pci_common_swizzle;
     98	bridge->map_irq = pcibios_map_irq;
     99	ret = pci_scan_root_bus_bridge(bridge);
    100	if (ret) {
    101		pci_free_host_bridge(bridge);
    102		return;
    103	}
    104
    105	hose->bus = bus = bridge->bus;
    106
    107	need_domain_info = need_domain_info || pci_domain_nr(bus);
    108	set_pci_need_domain_info(hose, need_domain_info);
    109
    110	next_busno = bus->busn_res.end + 1;
    111	/* Don't allow 8-bit bus number overflow inside the hose -
    112	   reserve some space for bridges. */
    113	if (next_busno > 224) {
    114		next_busno = 0;
    115		need_domain_info = 1;
    116	}
    117
    118	/*
    119	 * We insert PCI resources into the iomem_resource and
    120	 * ioport_resource trees in either pci_bus_claim_resources()
    121	 * or pci_bus_assign_resources().
    122	 */
    123	if (pci_has_flag(PCI_PROBE_ONLY)) {
    124		pci_bus_claim_resources(bus);
    125	} else {
    126		struct pci_bus *child;
    127
    128		pci_bus_size_bridges(bus);
    129		pci_bus_assign_resources(bus);
    130		list_for_each_entry(child, &bus->children, node)
    131			pcie_bus_configure_settings(child);
    132	}
    133	pci_bus_add_devices(bus);
    134}
    135
    136#ifdef CONFIG_OF
    137void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node)
    138{
    139	struct of_pci_range range;
    140	struct of_pci_range_parser parser;
    141
    142	hose->of_node = node;
    143
    144	if (of_pci_range_parser_init(&parser, node))
    145		return;
    146
    147	for_each_of_pci_range(&parser, &range) {
    148		struct resource *res = NULL;
    149
    150		switch (range.flags & IORESOURCE_TYPE_BITS) {
    151		case IORESOURCE_IO:
    152			hose->io_map_base =
    153				(unsigned long)ioremap(range.cpu_addr,
    154						       range.size);
    155			res = hose->io_resource;
    156			break;
    157		case IORESOURCE_MEM:
    158			res = hose->mem_resource;
    159			break;
    160		}
    161		if (res != NULL) {
    162			res->name = node->full_name;
    163			res->flags = range.flags;
    164			res->start = range.cpu_addr;
    165			res->end = range.cpu_addr + range.size - 1;
    166			res->parent = res->child = res->sibling = NULL;
    167		}
    168	}
    169}
    170
    171struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
    172{
    173	struct pci_controller *hose = bus->sysdata;
    174
    175	return of_node_get(hose->of_node);
    176}
    177#endif
    178
    179static DEFINE_MUTEX(pci_scan_mutex);
    180
    181void register_pci_controller(struct pci_controller *hose)
    182{
    183	struct resource *parent;
    184
    185	parent = hose->mem_resource->parent;
    186	if (!parent)
    187		parent = &iomem_resource;
    188
    189	if (request_resource(parent, hose->mem_resource) < 0)
    190		goto out;
    191
    192	parent = hose->io_resource->parent;
    193	if (!parent)
    194		parent = &ioport_resource;
    195
    196	if (request_resource(parent, hose->io_resource) < 0) {
    197		release_resource(hose->mem_resource);
    198		goto out;
    199	}
    200
    201	INIT_LIST_HEAD(&hose->list);
    202	list_add_tail(&hose->list, &controllers);
    203
    204	/*
    205	 * Do not panic here but later - this might happen before console init.
    206	 */
    207	if (!hose->io_map_base) {
    208		printk(KERN_WARNING
    209		       "registering PCI controller with io_map_base unset\n");
    210	}
    211
    212	/*
    213	 * Scan the bus if it is register after the PCI subsystem
    214	 * initialization.
    215	 */
    216	if (pci_initialized) {
    217		mutex_lock(&pci_scan_mutex);
    218		pcibios_scanbus(hose);
    219		mutex_unlock(&pci_scan_mutex);
    220	}
    221
    222	return;
    223
    224out:
    225	printk(KERN_WARNING
    226	       "Skipping PCI bus scan due to resource conflict\n");
    227}
    228
    229static int __init pcibios_init(void)
    230{
    231	struct pci_controller *hose;
    232
    233	/* Scan all of the recorded PCI controllers.  */
    234	list_for_each_entry(hose, &controllers, list)
    235		pcibios_scanbus(hose);
    236
    237	pci_initialized = 1;
    238
    239	return 0;
    240}
    241
    242subsys_initcall(pcibios_init);
    243
    244static int pcibios_enable_resources(struct pci_dev *dev, int mask)
    245{
    246	u16 cmd, old_cmd;
    247	int idx;
    248	struct resource *r;
    249
    250	pci_read_config_word(dev, PCI_COMMAND, &cmd);
    251	old_cmd = cmd;
    252	for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
    253		/* Only set up the requested stuff */
    254		if (!(mask & (1<<idx)))
    255			continue;
    256
    257		r = &dev->resource[idx];
    258		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
    259			continue;
    260		if ((idx == PCI_ROM_RESOURCE) &&
    261				(!(r->flags & IORESOURCE_ROM_ENABLE)))
    262			continue;
    263		if (!r->start && r->end) {
    264			pci_err(dev,
    265				"can't enable device: resource collisions\n");
    266			return -EINVAL;
    267		}
    268		if (r->flags & IORESOURCE_IO)
    269			cmd |= PCI_COMMAND_IO;
    270		if (r->flags & IORESOURCE_MEM)
    271			cmd |= PCI_COMMAND_MEMORY;
    272	}
    273	if (cmd != old_cmd) {
    274		pci_info(dev, "enabling device (%04x -> %04x)\n", old_cmd, cmd);
    275		pci_write_config_word(dev, PCI_COMMAND, cmd);
    276	}
    277	return 0;
    278}
    279
    280int pcibios_enable_device(struct pci_dev *dev, int mask)
    281{
    282	int err = pcibios_enable_resources(dev, mask);
    283
    284	if (err < 0)
    285		return err;
    286
    287	return pcibios_plat_dev_init(dev);
    288}
    289
    290void pcibios_fixup_bus(struct pci_bus *bus)
    291{
    292	struct pci_dev *dev = bus->self;
    293
    294	if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
    295	    (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
    296		pci_read_bridge_bases(bus);
    297	}
    298}
    299
    300char * (*pcibios_plat_setup)(char *str) __initdata;
    301
    302char *__init pcibios_setup(char *str)
    303{
    304	if (pcibios_plat_setup)
    305		return pcibios_plat_setup(str);
    306	return str;
    307}