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_iov.c (2235B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright IBM Corp. 2020
      4 *
      5 * Author(s):
      6 *   Niklas Schnelle <schnelle@linux.ibm.com>
      7 *
      8 */
      9
     10#define KMSG_COMPONENT "zpci"
     11#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
     12
     13#include <linux/kernel.h>
     14#include <linux/pci.h>
     15
     16#include "pci_iov.h"
     17
     18static struct resource iov_res = {
     19	.name	= "PCI IOV res",
     20	.start	= 0,
     21	.end	= -1,
     22	.flags	= IORESOURCE_MEM,
     23};
     24
     25void zpci_iov_map_resources(struct pci_dev *pdev)
     26{
     27	resource_size_t len;
     28	int i;
     29
     30	for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
     31		int bar = i + PCI_IOV_RESOURCES;
     32
     33		len = pci_resource_len(pdev, bar);
     34		if (!len)
     35			continue;
     36		pdev->resource[bar].parent = &iov_res;
     37	}
     38}
     39
     40void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn)
     41{
     42	pci_lock_rescan_remove();
     43	/* Linux' vfid's start at 0 vfn at 1 */
     44	pci_iov_remove_virtfn(pdev->physfn, vfn - 1);
     45	pci_unlock_rescan_remove();
     46}
     47
     48static int zpci_iov_link_virtfn(struct pci_dev *pdev, struct pci_dev *virtfn, int vfid)
     49{
     50	int rc;
     51
     52	rc = pci_iov_sysfs_link(pdev, virtfn, vfid);
     53	if (rc)
     54		return rc;
     55
     56	virtfn->is_virtfn = 1;
     57	virtfn->multifunction = 0;
     58	virtfn->physfn = pci_dev_get(pdev);
     59
     60	return 0;
     61}
     62
     63int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn)
     64{
     65	int i, cand_devfn;
     66	struct zpci_dev *zdev;
     67	struct pci_dev *pdev;
     68	int vfid = vfn - 1; /* Linux' vfid's start at 0 vfn at 1*/
     69	int rc = 0;
     70
     71	if (!zbus->multifunction)
     72		return 0;
     73
     74	/* If the parent PF for the given VF is also configured in the
     75	 * instance, it must be on the same zbus.
     76	 * We can then identify the parent PF by checking what
     77	 * devfn the VF would have if it belonged to that PF using the PF's
     78	 * stride and offset. Only if this candidate devfn matches the
     79	 * actual devfn will we link both functions.
     80	 */
     81	for (i = 0; i < ZPCI_FUNCTIONS_PER_BUS; i++) {
     82		zdev = zbus->function[i];
     83		if (zdev && zdev->is_physfn) {
     84			pdev = pci_get_slot(zbus->bus, zdev->devfn);
     85			if (!pdev)
     86				continue;
     87			cand_devfn = pci_iov_virtfn_devfn(pdev, vfid);
     88			if (cand_devfn == virtfn->devfn) {
     89				rc = zpci_iov_link_virtfn(pdev, virtfn, vfid);
     90				/* balance pci_get_slot() */
     91				pci_dev_put(pdev);
     92				break;
     93			}
     94			/* balance pci_get_slot() */
     95			pci_dev_put(pdev);
     96		}
     97	}
     98	return rc;
     99}