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

system.c (2763B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * system.c - a driver for reserving pnp system resources
      4 *
      5 * Some code is based on pnpbios_core.c
      6 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
      7 * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
      8 *	Bjorn Helgaas <bjorn.helgaas@hp.com>
      9 */
     10
     11#include <linux/pnp.h>
     12#include <linux/device.h>
     13#include <linux/init.h>
     14#include <linux/slab.h>
     15#include <linux/kernel.h>
     16#include <linux/ioport.h>
     17
     18static const struct pnp_device_id pnp_dev_table[] = {
     19	/* General ID for reserving resources */
     20	{"PNP0c02", 0},
     21	/* memory controller */
     22	{"PNP0c01", 0},
     23	{"", 0}
     24};
     25
     26static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
     27{
     28	char *regionid;
     29	const char *pnpid = dev_name(&dev->dev);
     30	resource_size_t start = r->start, end = r->end;
     31	struct resource *res;
     32
     33	regionid = kmalloc(16, GFP_KERNEL);
     34	if (!regionid)
     35		return;
     36
     37	snprintf(regionid, 16, "pnp %s", pnpid);
     38	if (port)
     39		res = request_region(start, end - start + 1, regionid);
     40	else
     41		res = request_mem_region(start, end - start + 1, regionid);
     42	if (res)
     43		res->flags &= ~IORESOURCE_BUSY;
     44	else
     45		kfree(regionid);
     46
     47	/*
     48	 * Failures at this point are usually harmless. pci quirks for
     49	 * example do reserve stuff they know about too, so we may well
     50	 * have double reservations.
     51	 */
     52	dev_info(&dev->dev, "%pR %s reserved\n", r,
     53		 res ? "has been" : "could not be");
     54}
     55
     56static void reserve_resources_of_dev(struct pnp_dev *dev)
     57{
     58	struct resource *res;
     59	int i;
     60
     61	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
     62		if (res->flags & IORESOURCE_DISABLED)
     63			continue;
     64		if (res->start == 0)
     65			continue;	/* disabled */
     66		if (res->start < 0x100)
     67			/*
     68			 * Below 0x100 is only standard PC hardware
     69			 * (pics, kbd, timer, dma, ...)
     70			 * We should not get resource conflicts there,
     71			 * and the kernel reserves these anyway
     72			 * (see arch/i386/kernel/setup.c).
     73			 * So, do nothing
     74			 */
     75			continue;
     76		if (res->end < res->start)
     77			continue;	/* invalid */
     78
     79		reserve_range(dev, res, 1);
     80	}
     81
     82	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
     83		if (res->flags & IORESOURCE_DISABLED)
     84			continue;
     85
     86		reserve_range(dev, res, 0);
     87	}
     88}
     89
     90static int system_pnp_probe(struct pnp_dev *dev,
     91			    const struct pnp_device_id *dev_id)
     92{
     93	reserve_resources_of_dev(dev);
     94	return 0;
     95}
     96
     97static struct pnp_driver system_pnp_driver = {
     98	.name     = "system",
     99	.id_table = pnp_dev_table,
    100	.flags    = PNP_DRIVER_RES_DO_NOT_CHANGE,
    101	.probe    = system_pnp_probe,
    102};
    103
    104static int __init pnp_system_init(void)
    105{
    106	return pnp_register_driver(&system_pnp_driver);
    107}
    108
    109/*
    110 * Reserve motherboard resources after PCI claim BARs,
    111 * but before PCI assign resources for uninitialized PCI devices
    112 */
    113fs_initcall(pnp_system_init);