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

conf_space.c (11602B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * PCI Backend - Functions for creating a virtual configuration space for
      4 *               exported PCI Devices.
      5 *               It's dangerous to allow PCI Driver Domains to change their
      6 *               device's resources (memory, i/o ports, interrupts). We need to
      7 *               restrict changes to certain PCI Configuration registers:
      8 *               BARs, INTERRUPT_PIN, most registers in the header...
      9 *
     10 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
     11 */
     12
     13#define dev_fmt(fmt) DRV_NAME ": " fmt
     14
     15#include <linux/kernel.h>
     16#include <linux/moduleparam.h>
     17#include <linux/pci.h>
     18#include "pciback.h"
     19#include "conf_space.h"
     20#include "conf_space_quirks.h"
     21
     22bool xen_pcibk_permissive;
     23module_param_named(permissive, xen_pcibk_permissive, bool, 0644);
     24
     25/* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
     26 * xen_pcibk_write_config_word, and xen_pcibk_write_config_byte are created. */
     27#define DEFINE_PCI_CONFIG(op, size, type)			\
     28int xen_pcibk_##op##_config_##size				\
     29(struct pci_dev *dev, int offset, type value, void *data)	\
     30{								\
     31	return pci_##op##_config_##size(dev, offset, value);	\
     32}
     33
     34DEFINE_PCI_CONFIG(read, byte, u8 *)
     35DEFINE_PCI_CONFIG(read, word, u16 *)
     36DEFINE_PCI_CONFIG(read, dword, u32 *)
     37
     38DEFINE_PCI_CONFIG(write, byte, u8)
     39DEFINE_PCI_CONFIG(write, word, u16)
     40DEFINE_PCI_CONFIG(write, dword, u32)
     41
     42static int conf_space_read(struct pci_dev *dev,
     43			   const struct config_field_entry *entry,
     44			   int offset, u32 *value)
     45{
     46	int ret = 0;
     47	const struct config_field *field = entry->field;
     48
     49	*value = 0;
     50
     51	switch (field->size) {
     52	case 1:
     53		if (field->u.b.read)
     54			ret = field->u.b.read(dev, offset, (u8 *) value,
     55					      entry->data);
     56		break;
     57	case 2:
     58		if (field->u.w.read)
     59			ret = field->u.w.read(dev, offset, (u16 *) value,
     60					      entry->data);
     61		break;
     62	case 4:
     63		if (field->u.dw.read)
     64			ret = field->u.dw.read(dev, offset, value, entry->data);
     65		break;
     66	}
     67	return ret;
     68}
     69
     70static int conf_space_write(struct pci_dev *dev,
     71			    const struct config_field_entry *entry,
     72			    int offset, u32 value)
     73{
     74	int ret = 0;
     75	const struct config_field *field = entry->field;
     76
     77	switch (field->size) {
     78	case 1:
     79		if (field->u.b.write)
     80			ret = field->u.b.write(dev, offset, (u8) value,
     81					       entry->data);
     82		break;
     83	case 2:
     84		if (field->u.w.write)
     85			ret = field->u.w.write(dev, offset, (u16) value,
     86					       entry->data);
     87		break;
     88	case 4:
     89		if (field->u.dw.write)
     90			ret = field->u.dw.write(dev, offset, value,
     91						entry->data);
     92		break;
     93	}
     94	return ret;
     95}
     96
     97static inline u32 get_mask(int size)
     98{
     99	if (size == 1)
    100		return 0xff;
    101	else if (size == 2)
    102		return 0xffff;
    103	else
    104		return 0xffffffff;
    105}
    106
    107static inline int valid_request(int offset, int size)
    108{
    109	/* Validate request (no un-aligned requests) */
    110	if ((size == 1 || size == 2 || size == 4) && (offset % size) == 0)
    111		return 1;
    112	return 0;
    113}
    114
    115static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
    116			      int offset)
    117{
    118	if (offset >= 0) {
    119		new_val_mask <<= (offset * 8);
    120		new_val <<= (offset * 8);
    121	} else {
    122		new_val_mask >>= (offset * -8);
    123		new_val >>= (offset * -8);
    124	}
    125	val = (val & ~new_val_mask) | (new_val & new_val_mask);
    126
    127	return val;
    128}
    129
    130static int xen_pcibios_err_to_errno(int err)
    131{
    132	switch (err) {
    133	case PCIBIOS_SUCCESSFUL:
    134		return XEN_PCI_ERR_success;
    135	case PCIBIOS_DEVICE_NOT_FOUND:
    136		return XEN_PCI_ERR_dev_not_found;
    137	case PCIBIOS_BAD_REGISTER_NUMBER:
    138		return XEN_PCI_ERR_invalid_offset;
    139	case PCIBIOS_FUNC_NOT_SUPPORTED:
    140		return XEN_PCI_ERR_not_implemented;
    141	case PCIBIOS_SET_FAILED:
    142		return XEN_PCI_ERR_access_denied;
    143	}
    144	return err;
    145}
    146
    147int xen_pcibk_config_read(struct pci_dev *dev, int offset, int size,
    148			  u32 *ret_val)
    149{
    150	int err = 0;
    151	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
    152	const struct config_field_entry *cfg_entry;
    153	const struct config_field *field;
    154	int field_start, field_end;
    155	/* if read fails for any reason, return 0
    156	 * (as if device didn't respond) */
    157	u32 value = 0, tmp_val;
    158
    159	dev_dbg(&dev->dev, "read %d bytes at 0x%x\n", size, offset);
    160
    161	if (!valid_request(offset, size)) {
    162		err = XEN_PCI_ERR_invalid_offset;
    163		goto out;
    164	}
    165
    166	/* Get the real value first, then modify as appropriate */
    167	switch (size) {
    168	case 1:
    169		err = pci_read_config_byte(dev, offset, (u8 *) &value);
    170		break;
    171	case 2:
    172		err = pci_read_config_word(dev, offset, (u16 *) &value);
    173		break;
    174	case 4:
    175		err = pci_read_config_dword(dev, offset, &value);
    176		break;
    177	}
    178
    179	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
    180		field = cfg_entry->field;
    181
    182		field_start = OFFSET(cfg_entry);
    183		field_end = OFFSET(cfg_entry) + field->size;
    184
    185		if (offset + size > field_start && field_end > offset) {
    186			err = conf_space_read(dev, cfg_entry, field_start,
    187					      &tmp_val);
    188			if (err)
    189				goto out;
    190
    191			value = merge_value(value, tmp_val,
    192					    get_mask(field->size),
    193					    field_start - offset);
    194		}
    195	}
    196
    197out:
    198	dev_dbg(&dev->dev, "read %d bytes at 0x%x = %x\n", size, offset, value);
    199
    200	*ret_val = value;
    201	return xen_pcibios_err_to_errno(err);
    202}
    203
    204int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
    205{
    206	int err = 0, handled = 0;
    207	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
    208	const struct config_field_entry *cfg_entry;
    209	const struct config_field *field;
    210	u32 tmp_val;
    211	int field_start, field_end;
    212
    213	dev_dbg(&dev->dev, "write request %d bytes at 0x%x = %x\n",
    214		size, offset, value);
    215
    216	if (!valid_request(offset, size))
    217		return XEN_PCI_ERR_invalid_offset;
    218
    219	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
    220		field = cfg_entry->field;
    221
    222		field_start = OFFSET(cfg_entry);
    223		field_end = OFFSET(cfg_entry) + field->size;
    224
    225		if (offset + size > field_start && field_end > offset) {
    226			err = conf_space_read(dev, cfg_entry, field_start,
    227					      &tmp_val);
    228			if (err)
    229				break;
    230
    231			tmp_val = merge_value(tmp_val, value, get_mask(size),
    232					      offset - field_start);
    233
    234			err = conf_space_write(dev, cfg_entry, field_start,
    235					       tmp_val);
    236
    237			/* handled is set true here, but not every byte
    238			 * may have been written! Properly detecting if
    239			 * every byte is handled is unnecessary as the
    240			 * flag is used to detect devices that need
    241			 * special helpers to work correctly.
    242			 */
    243			handled = 1;
    244		}
    245	}
    246
    247	if (!handled && !err) {
    248		/* By default, anything not specificially handled above is
    249		 * read-only. The permissive flag changes this behavior so
    250		 * that anything not specifically handled above is writable.
    251		 * This means that some fields may still be read-only because
    252		 * they have entries in the config_field list that intercept
    253		 * the write and do nothing. */
    254		if (dev_data->permissive || xen_pcibk_permissive) {
    255			switch (size) {
    256			case 1:
    257				err = pci_write_config_byte(dev, offset,
    258							    (u8) value);
    259				break;
    260			case 2:
    261				err = pci_write_config_word(dev, offset,
    262							    (u16) value);
    263				break;
    264			case 4:
    265				err = pci_write_config_dword(dev, offset,
    266							     (u32) value);
    267				break;
    268			}
    269		} else if (!dev_data->warned_on_write) {
    270			dev_data->warned_on_write = 1;
    271			dev_warn(&dev->dev, "Driver tried to write to a "
    272				 "read-only configuration space field at offset"
    273				 " 0x%x, size %d. This may be harmless, but if "
    274				 "you have problems with your device:\n"
    275				 "1) see permissive attribute in sysfs\n"
    276				 "2) report problems to the xen-devel "
    277				 "mailing list along with details of your "
    278				 "device obtained from lspci.\n", offset, size);
    279		}
    280	}
    281
    282	return xen_pcibios_err_to_errno(err);
    283}
    284
    285int xen_pcibk_get_interrupt_type(struct pci_dev *dev)
    286{
    287	int err;
    288	u16 val;
    289	int ret = 0;
    290
    291	err = pci_read_config_word(dev, PCI_COMMAND, &val);
    292	if (err)
    293		return err;
    294	if (!(val & PCI_COMMAND_INTX_DISABLE))
    295		ret |= INTERRUPT_TYPE_INTX;
    296
    297	/*
    298	 * Do not trust dev->msi(x)_enabled here, as enabling could be done
    299	 * bypassing the pci_*msi* functions, by the qemu.
    300	 */
    301	if (dev->msi_cap) {
    302		err = pci_read_config_word(dev,
    303				dev->msi_cap + PCI_MSI_FLAGS,
    304				&val);
    305		if (err)
    306			return err;
    307		if (val & PCI_MSI_FLAGS_ENABLE)
    308			ret |= INTERRUPT_TYPE_MSI;
    309	}
    310	if (dev->msix_cap) {
    311		err = pci_read_config_word(dev,
    312				dev->msix_cap + PCI_MSIX_FLAGS,
    313				&val);
    314		if (err)
    315			return err;
    316		if (val & PCI_MSIX_FLAGS_ENABLE)
    317			ret |= INTERRUPT_TYPE_MSIX;
    318	}
    319	return ret ?: INTERRUPT_TYPE_NONE;
    320}
    321
    322void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev)
    323{
    324	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
    325	struct config_field_entry *cfg_entry, *t;
    326	const struct config_field *field;
    327
    328	dev_dbg(&dev->dev, "free-ing dynamically allocated virtual "
    329			   "configuration space fields\n");
    330	if (!dev_data)
    331		return;
    332
    333	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
    334		field = cfg_entry->field;
    335
    336		if (field->clean) {
    337			field->clean((struct config_field *)field);
    338
    339			kfree(cfg_entry->data);
    340
    341			list_del(&cfg_entry->list);
    342			kfree(cfg_entry);
    343		}
    344
    345	}
    346}
    347
    348void xen_pcibk_config_reset_dev(struct pci_dev *dev)
    349{
    350	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
    351	const struct config_field_entry *cfg_entry;
    352	const struct config_field *field;
    353
    354	dev_dbg(&dev->dev, "resetting virtual configuration space\n");
    355	if (!dev_data)
    356		return;
    357
    358	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
    359		field = cfg_entry->field;
    360
    361		if (field->reset)
    362			field->reset(dev, OFFSET(cfg_entry), cfg_entry->data);
    363	}
    364}
    365
    366void xen_pcibk_config_free_dev(struct pci_dev *dev)
    367{
    368	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
    369	struct config_field_entry *cfg_entry, *t;
    370	const struct config_field *field;
    371
    372	dev_dbg(&dev->dev, "free-ing virtual configuration space fields\n");
    373	if (!dev_data)
    374		return;
    375
    376	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
    377		list_del(&cfg_entry->list);
    378
    379		field = cfg_entry->field;
    380
    381		if (field->release)
    382			field->release(dev, OFFSET(cfg_entry), cfg_entry->data);
    383
    384		kfree(cfg_entry);
    385	}
    386}
    387
    388int xen_pcibk_config_add_field_offset(struct pci_dev *dev,
    389				    const struct config_field *field,
    390				    unsigned int base_offset)
    391{
    392	int err = 0;
    393	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
    394	struct config_field_entry *cfg_entry;
    395	void *tmp;
    396
    397	cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
    398	if (!cfg_entry) {
    399		err = -ENOMEM;
    400		goto out;
    401	}
    402
    403	cfg_entry->data = NULL;
    404	cfg_entry->field = field;
    405	cfg_entry->base_offset = base_offset;
    406
    407	/* silently ignore duplicate fields */
    408	err = xen_pcibk_field_is_dup(dev, OFFSET(cfg_entry));
    409	if (err)
    410		goto out;
    411
    412	if (field->init) {
    413		tmp = field->init(dev, OFFSET(cfg_entry));
    414
    415		if (IS_ERR(tmp)) {
    416			err = PTR_ERR(tmp);
    417			goto out;
    418		}
    419
    420		cfg_entry->data = tmp;
    421	}
    422
    423	dev_dbg(&dev->dev, "added config field at offset 0x%02x\n",
    424		OFFSET(cfg_entry));
    425	list_add_tail(&cfg_entry->list, &dev_data->config_fields);
    426
    427out:
    428	if (err)
    429		kfree(cfg_entry);
    430
    431	return err;
    432}
    433
    434/* This sets up the device's virtual configuration space to keep track of
    435 * certain registers (like the base address registers (BARs) so that we can
    436 * keep the client from manipulating them directly.
    437 */
    438int xen_pcibk_config_init_dev(struct pci_dev *dev)
    439{
    440	int err = 0;
    441	struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
    442
    443	dev_dbg(&dev->dev, "initializing virtual configuration space\n");
    444
    445	INIT_LIST_HEAD(&dev_data->config_fields);
    446
    447	err = xen_pcibk_config_header_add_fields(dev);
    448	if (err)
    449		goto out;
    450
    451	err = xen_pcibk_config_capability_add_fields(dev);
    452	if (err)
    453		goto out;
    454
    455	err = xen_pcibk_config_quirks_init(dev);
    456
    457out:
    458	return err;
    459}
    460
    461int xen_pcibk_config_init(void)
    462{
    463	return xen_pcibk_config_capability_init();
    464}