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

vfio_pci_zdev.c (3224B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * VFIO ZPCI devices support
      4 *
      5 * Copyright (C) IBM Corp. 2020.  All rights reserved.
      6 *	Author(s): Pierre Morel <pmorel@linux.ibm.com>
      7 *                 Matthew Rosato <mjrosato@linux.ibm.com>
      8 */
      9#include <linux/io.h>
     10#include <linux/pci.h>
     11#include <linux/uaccess.h>
     12#include <linux/vfio.h>
     13#include <linux/vfio_zdev.h>
     14#include <asm/pci_clp.h>
     15#include <asm/pci_io.h>
     16
     17#include <linux/vfio_pci_core.h>
     18
     19/*
     20 * Add the Base PCI Function information to the device info region.
     21 */
     22static int zpci_base_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
     23{
     24	struct vfio_device_info_cap_zpci_base cap = {
     25		.header.id = VFIO_DEVICE_INFO_CAP_ZPCI_BASE,
     26		.header.version = 1,
     27		.start_dma = zdev->start_dma,
     28		.end_dma = zdev->end_dma,
     29		.pchid = zdev->pchid,
     30		.vfn = zdev->vfn,
     31		.fmb_length = zdev->fmb_length,
     32		.pft = zdev->pft,
     33		.gid = zdev->pfgid
     34	};
     35
     36	return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
     37}
     38
     39/*
     40 * Add the Base PCI Function Group information to the device info region.
     41 */
     42static int zpci_group_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
     43{
     44	struct vfio_device_info_cap_zpci_group cap = {
     45		.header.id = VFIO_DEVICE_INFO_CAP_ZPCI_GROUP,
     46		.header.version = 1,
     47		.dasm = zdev->dma_mask,
     48		.msi_addr = zdev->msi_addr,
     49		.flags = VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH,
     50		.mui = zdev->fmb_update,
     51		.noi = zdev->max_msi,
     52		.maxstbl = ZPCI_MAX_WRITE_SIZE,
     53		.version = zdev->version
     54	};
     55
     56	return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
     57}
     58
     59/*
     60 * Add the device utility string to the device info region.
     61 */
     62static int zpci_util_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
     63{
     64	struct vfio_device_info_cap_zpci_util *cap;
     65	int cap_size = sizeof(*cap) + CLP_UTIL_STR_LEN;
     66	int ret;
     67
     68	cap = kmalloc(cap_size, GFP_KERNEL);
     69	if (!cap)
     70		return -ENOMEM;
     71
     72	cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_UTIL;
     73	cap->header.version = 1;
     74	cap->size = CLP_UTIL_STR_LEN;
     75	memcpy(cap->util_str, zdev->util_str, cap->size);
     76
     77	ret = vfio_info_add_capability(caps, &cap->header, cap_size);
     78
     79	kfree(cap);
     80
     81	return ret;
     82}
     83
     84/*
     85 * Add the function path string to the device info region.
     86 */
     87static int zpci_pfip_cap(struct zpci_dev *zdev, struct vfio_info_cap *caps)
     88{
     89	struct vfio_device_info_cap_zpci_pfip *cap;
     90	int cap_size = sizeof(*cap) + CLP_PFIP_NR_SEGMENTS;
     91	int ret;
     92
     93	cap = kmalloc(cap_size, GFP_KERNEL);
     94	if (!cap)
     95		return -ENOMEM;
     96
     97	cap->header.id = VFIO_DEVICE_INFO_CAP_ZPCI_PFIP;
     98	cap->header.version = 1;
     99	cap->size = CLP_PFIP_NR_SEGMENTS;
    100	memcpy(cap->pfip, zdev->pfip, cap->size);
    101
    102	ret = vfio_info_add_capability(caps, &cap->header, cap_size);
    103
    104	kfree(cap);
    105
    106	return ret;
    107}
    108
    109/*
    110 * Add all supported capabilities to the VFIO_DEVICE_GET_INFO capability chain.
    111 */
    112int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
    113				struct vfio_info_cap *caps)
    114{
    115	struct zpci_dev *zdev = to_zpci(vdev->pdev);
    116	int ret;
    117
    118	if (!zdev)
    119		return -ENODEV;
    120
    121	ret = zpci_base_cap(zdev, caps);
    122	if (ret)
    123		return ret;
    124
    125	ret = zpci_group_cap(zdev, caps);
    126	if (ret)
    127		return ret;
    128
    129	if (zdev->util_str_avail) {
    130		ret = zpci_util_cap(zdev, caps);
    131		if (ret)
    132			return ret;
    133	}
    134
    135	ret = zpci_pfip_cap(zdev, caps);
    136
    137	return ret;
    138}