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

direct.c (6568B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * direct.c - Low-level direct PCI config space access
      4 */
      5
      6#include <linux/pci.h>
      7#include <linux/init.h>
      8#include <linux/dmi.h>
      9#include <asm/pci_x86.h>
     10
     11/*
     12 * Functions for accessing PCI base (first 256 bytes) and extended
     13 * (4096 bytes per PCI function) configuration space with type 1
     14 * accesses.
     15 */
     16
     17#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
     18	(0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
     19	| (devfn << 8) | (reg & 0xFC))
     20
     21static int pci_conf1_read(unsigned int seg, unsigned int bus,
     22			  unsigned int devfn, int reg, int len, u32 *value)
     23{
     24	unsigned long flags;
     25
     26	if (seg || (bus > 255) || (devfn > 255) || (reg > 4095)) {
     27		*value = -1;
     28		return -EINVAL;
     29	}
     30
     31	raw_spin_lock_irqsave(&pci_config_lock, flags);
     32
     33	outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
     34
     35	switch (len) {
     36	case 1:
     37		*value = inb(0xCFC + (reg & 3));
     38		break;
     39	case 2:
     40		*value = inw(0xCFC + (reg & 2));
     41		break;
     42	case 4:
     43		*value = inl(0xCFC);
     44		break;
     45	}
     46
     47	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
     48
     49	return 0;
     50}
     51
     52static int pci_conf1_write(unsigned int seg, unsigned int bus,
     53			   unsigned int devfn, int reg, int len, u32 value)
     54{
     55	unsigned long flags;
     56
     57	if (seg || (bus > 255) || (devfn > 255) || (reg > 4095))
     58		return -EINVAL;
     59
     60	raw_spin_lock_irqsave(&pci_config_lock, flags);
     61
     62	outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
     63
     64	switch (len) {
     65	case 1:
     66		outb((u8)value, 0xCFC + (reg & 3));
     67		break;
     68	case 2:
     69		outw((u16)value, 0xCFC + (reg & 2));
     70		break;
     71	case 4:
     72		outl((u32)value, 0xCFC);
     73		break;
     74	}
     75
     76	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
     77
     78	return 0;
     79}
     80
     81#undef PCI_CONF1_ADDRESS
     82
     83const struct pci_raw_ops pci_direct_conf1 = {
     84	.read =		pci_conf1_read,
     85	.write =	pci_conf1_write,
     86};
     87
     88
     89/*
     90 * Functions for accessing PCI configuration space with type 2 accesses
     91 */
     92
     93#define PCI_CONF2_ADDRESS(dev, reg)	(u16)(0xC000 | (dev << 8) | reg)
     94
     95static int pci_conf2_read(unsigned int seg, unsigned int bus,
     96			  unsigned int devfn, int reg, int len, u32 *value)
     97{
     98	unsigned long flags;
     99	int dev, fn;
    100
    101	WARN_ON(seg);
    102	if ((bus > 255) || (devfn > 255) || (reg > 255)) {
    103		*value = -1;
    104		return -EINVAL;
    105	}
    106
    107	dev = PCI_SLOT(devfn);
    108	fn = PCI_FUNC(devfn);
    109
    110	if (dev & 0x10) 
    111		return PCIBIOS_DEVICE_NOT_FOUND;
    112
    113	raw_spin_lock_irqsave(&pci_config_lock, flags);
    114
    115	outb((u8)(0xF0 | (fn << 1)), 0xCF8);
    116	outb((u8)bus, 0xCFA);
    117
    118	switch (len) {
    119	case 1:
    120		*value = inb(PCI_CONF2_ADDRESS(dev, reg));
    121		break;
    122	case 2:
    123		*value = inw(PCI_CONF2_ADDRESS(dev, reg));
    124		break;
    125	case 4:
    126		*value = inl(PCI_CONF2_ADDRESS(dev, reg));
    127		break;
    128	}
    129
    130	outb(0, 0xCF8);
    131
    132	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
    133
    134	return 0;
    135}
    136
    137static int pci_conf2_write(unsigned int seg, unsigned int bus,
    138			   unsigned int devfn, int reg, int len, u32 value)
    139{
    140	unsigned long flags;
    141	int dev, fn;
    142
    143	WARN_ON(seg);
    144	if ((bus > 255) || (devfn > 255) || (reg > 255)) 
    145		return -EINVAL;
    146
    147	dev = PCI_SLOT(devfn);
    148	fn = PCI_FUNC(devfn);
    149
    150	if (dev & 0x10) 
    151		return PCIBIOS_DEVICE_NOT_FOUND;
    152
    153	raw_spin_lock_irqsave(&pci_config_lock, flags);
    154
    155	outb((u8)(0xF0 | (fn << 1)), 0xCF8);
    156	outb((u8)bus, 0xCFA);
    157
    158	switch (len) {
    159	case 1:
    160		outb((u8)value, PCI_CONF2_ADDRESS(dev, reg));
    161		break;
    162	case 2:
    163		outw((u16)value, PCI_CONF2_ADDRESS(dev, reg));
    164		break;
    165	case 4:
    166		outl((u32)value, PCI_CONF2_ADDRESS(dev, reg));
    167		break;
    168	}
    169
    170	outb(0, 0xCF8);    
    171
    172	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
    173
    174	return 0;
    175}
    176
    177#undef PCI_CONF2_ADDRESS
    178
    179static const struct pci_raw_ops pci_direct_conf2 = {
    180	.read =		pci_conf2_read,
    181	.write =	pci_conf2_write,
    182};
    183
    184
    185/*
    186 * Before we decide to use direct hardware access mechanisms, we try to do some
    187 * trivial checks to ensure it at least _seems_ to be working -- we just test
    188 * whether bus 00 contains a host bridge (this is similar to checking
    189 * techniques used in XFree86, but ours should be more reliable since we
    190 * attempt to make use of direct access hints provided by the PCI BIOS).
    191 *
    192 * This should be close to trivial, but it isn't, because there are buggy
    193 * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
    194 */
    195static int __init pci_sanity_check(const struct pci_raw_ops *o)
    196{
    197	u32 x = 0;
    198	int devfn;
    199
    200	if (pci_probe & PCI_NO_CHECKS)
    201		return 1;
    202	/* Assume Type 1 works for newer systems.
    203	   This handles machines that don't have anything on PCI Bus 0. */
    204	if (dmi_get_bios_year() >= 2001)
    205		return 1;
    206
    207	for (devfn = 0; devfn < 0x100; devfn++) {
    208		if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
    209			continue;
    210		if (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)
    211			return 1;
    212
    213		if (o->read(0, 0, devfn, PCI_VENDOR_ID, 2, &x))
    214			continue;
    215		if (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)
    216			return 1;
    217	}
    218
    219	DBG(KERN_WARNING "PCI: Sanity check failed\n");
    220	return 0;
    221}
    222
    223static int __init pci_check_type1(void)
    224{
    225	unsigned long flags;
    226	unsigned int tmp;
    227	int works = 0;
    228
    229	local_irq_save(flags);
    230
    231	outb(0x01, 0xCFB);
    232	tmp = inl(0xCF8);
    233	outl(0x80000000, 0xCF8);
    234	if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) {
    235		works = 1;
    236	}
    237	outl(tmp, 0xCF8);
    238	local_irq_restore(flags);
    239
    240	return works;
    241}
    242
    243static int __init pci_check_type2(void)
    244{
    245	unsigned long flags;
    246	int works = 0;
    247
    248	local_irq_save(flags);
    249
    250	outb(0x00, 0xCFB);
    251	outb(0x00, 0xCF8);
    252	outb(0x00, 0xCFA);
    253	if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 &&
    254	    pci_sanity_check(&pci_direct_conf2)) {
    255		works = 1;
    256	}
    257
    258	local_irq_restore(flags);
    259
    260	return works;
    261}
    262
    263void __init pci_direct_init(int type)
    264{
    265	if (type == 0)
    266		return;
    267	printk(KERN_INFO "PCI: Using configuration type %d for base access\n",
    268		 type);
    269	if (type == 1) {
    270		raw_pci_ops = &pci_direct_conf1;
    271		if (raw_pci_ext_ops)
    272			return;
    273		if (!(pci_probe & PCI_HAS_IO_ECS))
    274			return;
    275		printk(KERN_INFO "PCI: Using configuration type 1 "
    276		       "for extended access\n");
    277		raw_pci_ext_ops = &pci_direct_conf1;
    278		return;
    279	}
    280	raw_pci_ops = &pci_direct_conf2;
    281}
    282
    283int __init pci_direct_probe(void)
    284{
    285	if ((pci_probe & PCI_PROBE_CONF1) == 0)
    286		goto type2;
    287	if (!request_region(0xCF8, 8, "PCI conf1"))
    288		goto type2;
    289
    290	if (pci_check_type1()) {
    291		raw_pci_ops = &pci_direct_conf1;
    292		port_cf9_safe = true;
    293		return 1;
    294	}
    295	release_region(0xCF8, 8);
    296
    297 type2:
    298	if ((pci_probe & PCI_PROBE_CONF2) == 0)
    299		return 0;
    300	if (!request_region(0xCF8, 4, "PCI conf2"))
    301		return 0;
    302	if (!request_region(0xC000, 0x1000, "PCI conf2"))
    303		goto fail2;
    304
    305	if (pci_check_type2()) {
    306		raw_pci_ops = &pci_direct_conf2;
    307		port_cf9_safe = true;
    308		return 2;
    309	}
    310
    311	release_region(0xC000, 0x1000);
    312 fail2:
    313	release_region(0xCF8, 4);
    314	return 0;
    315}