1*4882a593Smuzhiyun.. include:: <isonum.txt> 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun===================== 4*4882a593SmuzhiyunVFIO Mediated devices 5*4882a593Smuzhiyun===================== 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun:Copyright: |copy| 2016, NVIDIA CORPORATION. All rights reserved. 8*4882a593Smuzhiyun:Author: Neo Jia <cjia@nvidia.com> 9*4882a593Smuzhiyun:Author: Kirti Wankhede <kwankhede@nvidia.com> 10*4882a593Smuzhiyun 11*4882a593SmuzhiyunThis program is free software; you can redistribute it and/or modify 12*4882a593Smuzhiyunit under the terms of the GNU General Public License version 2 as 13*4882a593Smuzhiyunpublished by the Free Software Foundation. 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunVirtual Function I/O (VFIO) Mediated devices[1] 17*4882a593Smuzhiyun=============================================== 18*4882a593Smuzhiyun 19*4882a593SmuzhiyunThe number of use cases for virtualizing DMA devices that do not have built-in 20*4882a593SmuzhiyunSR_IOV capability is increasing. Previously, to virtualize such devices, 21*4882a593Smuzhiyundevelopers had to create their own management interfaces and APIs, and then 22*4882a593Smuzhiyunintegrate them with user space software. To simplify integration with user space 23*4882a593Smuzhiyunsoftware, we have identified common requirements and a unified management 24*4882a593Smuzhiyuninterface for such devices. 25*4882a593Smuzhiyun 26*4882a593SmuzhiyunThe VFIO driver framework provides unified APIs for direct device access. It is 27*4882a593Smuzhiyunan IOMMU/device-agnostic framework for exposing direct device access to user 28*4882a593Smuzhiyunspace in a secure, IOMMU-protected environment. This framework is used for 29*4882a593Smuzhiyunmultiple devices, such as GPUs, network adapters, and compute accelerators. With 30*4882a593Smuzhiyundirect device access, virtual machines or user space applications have direct 31*4882a593Smuzhiyunaccess to the physical device. This framework is reused for mediated devices. 32*4882a593Smuzhiyun 33*4882a593SmuzhiyunThe mediated core driver provides a common interface for mediated device 34*4882a593Smuzhiyunmanagement that can be used by drivers of different devices. This module 35*4882a593Smuzhiyunprovides a generic interface to perform these operations: 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun* Create and destroy a mediated device 38*4882a593Smuzhiyun* Add a mediated device to and remove it from a mediated bus driver 39*4882a593Smuzhiyun* Add a mediated device to and remove it from an IOMMU group 40*4882a593Smuzhiyun 41*4882a593SmuzhiyunThe mediated core driver also provides an interface to register a bus driver. 42*4882a593SmuzhiyunFor example, the mediated VFIO mdev driver is designed for mediated devices and 43*4882a593Smuzhiyunsupports VFIO APIs. The mediated bus driver adds a mediated device to and 44*4882a593Smuzhiyunremoves it from a VFIO group. 45*4882a593Smuzhiyun 46*4882a593SmuzhiyunThe following high-level block diagram shows the main components and interfaces 47*4882a593Smuzhiyunin the VFIO mediated driver framework. The diagram shows NVIDIA, Intel, and IBM 48*4882a593Smuzhiyundevices as examples, as these devices are the first devices to use this module:: 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun +---------------+ 51*4882a593Smuzhiyun | | 52*4882a593Smuzhiyun | +-----------+ | mdev_register_driver() +--------------+ 53*4882a593Smuzhiyun | | | +<------------------------+ | 54*4882a593Smuzhiyun | | mdev | | | | 55*4882a593Smuzhiyun | | bus | +------------------------>+ vfio_mdev.ko |<-> VFIO user 56*4882a593Smuzhiyun | | driver | | probe()/remove() | | APIs 57*4882a593Smuzhiyun | | | | +--------------+ 58*4882a593Smuzhiyun | +-----------+ | 59*4882a593Smuzhiyun | | 60*4882a593Smuzhiyun | MDEV CORE | 61*4882a593Smuzhiyun | MODULE | 62*4882a593Smuzhiyun | mdev.ko | 63*4882a593Smuzhiyun | +-----------+ | mdev_register_device() +--------------+ 64*4882a593Smuzhiyun | | | +<------------------------+ | 65*4882a593Smuzhiyun | | | | | nvidia.ko |<-> physical 66*4882a593Smuzhiyun | | | +------------------------>+ | device 67*4882a593Smuzhiyun | | | | callbacks +--------------+ 68*4882a593Smuzhiyun | | Physical | | 69*4882a593Smuzhiyun | | device | | mdev_register_device() +--------------+ 70*4882a593Smuzhiyun | | interface | |<------------------------+ | 71*4882a593Smuzhiyun | | | | | i915.ko |<-> physical 72*4882a593Smuzhiyun | | | +------------------------>+ | device 73*4882a593Smuzhiyun | | | | callbacks +--------------+ 74*4882a593Smuzhiyun | | | | 75*4882a593Smuzhiyun | | | | mdev_register_device() +--------------+ 76*4882a593Smuzhiyun | | | +<------------------------+ | 77*4882a593Smuzhiyun | | | | | ccw_device.ko|<-> physical 78*4882a593Smuzhiyun | | | +------------------------>+ | device 79*4882a593Smuzhiyun | | | | callbacks +--------------+ 80*4882a593Smuzhiyun | +-----------+ | 81*4882a593Smuzhiyun +---------------+ 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun 84*4882a593SmuzhiyunRegistration Interfaces 85*4882a593Smuzhiyun======================= 86*4882a593Smuzhiyun 87*4882a593SmuzhiyunThe mediated core driver provides the following types of registration 88*4882a593Smuzhiyuninterfaces: 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun* Registration interface for a mediated bus driver 91*4882a593Smuzhiyun* Physical device driver interface 92*4882a593Smuzhiyun 93*4882a593SmuzhiyunRegistration Interface for a Mediated Bus Driver 94*4882a593Smuzhiyun------------------------------------------------ 95*4882a593Smuzhiyun 96*4882a593SmuzhiyunThe registration interface for a mediated bus driver provides the following 97*4882a593Smuzhiyunstructure to represent a mediated device's driver:: 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun /* 100*4882a593Smuzhiyun * struct mdev_driver [2] - Mediated device's driver 101*4882a593Smuzhiyun * @name: driver name 102*4882a593Smuzhiyun * @probe: called when new device created 103*4882a593Smuzhiyun * @remove: called when device removed 104*4882a593Smuzhiyun * @driver: device driver structure 105*4882a593Smuzhiyun */ 106*4882a593Smuzhiyun struct mdev_driver { 107*4882a593Smuzhiyun const char *name; 108*4882a593Smuzhiyun int (*probe) (struct device *dev); 109*4882a593Smuzhiyun void (*remove) (struct device *dev); 110*4882a593Smuzhiyun struct device_driver driver; 111*4882a593Smuzhiyun }; 112*4882a593Smuzhiyun 113*4882a593SmuzhiyunA mediated bus driver for mdev should use this structure in the function calls 114*4882a593Smuzhiyunto register and unregister itself with the core driver: 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun* Register:: 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun extern int mdev_register_driver(struct mdev_driver *drv, 119*4882a593Smuzhiyun struct module *owner); 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun* Unregister:: 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun extern void mdev_unregister_driver(struct mdev_driver *drv); 124*4882a593Smuzhiyun 125*4882a593SmuzhiyunThe mediated bus driver is responsible for adding mediated devices to the VFIO 126*4882a593Smuzhiyungroup when devices are bound to the driver and removing mediated devices from 127*4882a593Smuzhiyunthe VFIO when devices are unbound from the driver. 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun 130*4882a593SmuzhiyunPhysical Device Driver Interface 131*4882a593Smuzhiyun-------------------------------- 132*4882a593Smuzhiyun 133*4882a593SmuzhiyunThe physical device driver interface provides the mdev_parent_ops[3] structure 134*4882a593Smuzhiyunto define the APIs to manage work in the mediated core driver that is related 135*4882a593Smuzhiyunto the physical device. 136*4882a593Smuzhiyun 137*4882a593SmuzhiyunThe structures in the mdev_parent_ops structure are as follows: 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun* dev_attr_groups: attributes of the parent device 140*4882a593Smuzhiyun* mdev_attr_groups: attributes of the mediated device 141*4882a593Smuzhiyun* supported_config: attributes to define supported configurations 142*4882a593Smuzhiyun 143*4882a593SmuzhiyunThe functions in the mdev_parent_ops structure are as follows: 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun* create: allocate basic resources in a driver for a mediated device 146*4882a593Smuzhiyun* remove: free resources in a driver when a mediated device is destroyed 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun(Note that mdev-core provides no implicit serialization of create/remove 149*4882a593Smuzhiyuncallbacks per mdev parent device, per mdev type, or any other categorization. 150*4882a593SmuzhiyunVendor drivers are expected to be fully asynchronous in this respect or 151*4882a593Smuzhiyunprovide their own internal resource protection.) 152*4882a593Smuzhiyun 153*4882a593SmuzhiyunThe callbacks in the mdev_parent_ops structure are as follows: 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun* open: open callback of mediated device 156*4882a593Smuzhiyun* close: close callback of mediated device 157*4882a593Smuzhiyun* ioctl: ioctl callback of mediated device 158*4882a593Smuzhiyun* read : read emulation callback 159*4882a593Smuzhiyun* write: write emulation callback 160*4882a593Smuzhiyun* mmap: mmap emulation callback 161*4882a593Smuzhiyun 162*4882a593SmuzhiyunA driver should use the mdev_parent_ops structure in the function call to 163*4882a593Smuzhiyunregister itself with the mdev core driver:: 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun extern int mdev_register_device(struct device *dev, 166*4882a593Smuzhiyun const struct mdev_parent_ops *ops); 167*4882a593Smuzhiyun 168*4882a593SmuzhiyunHowever, the mdev_parent_ops structure is not required in the function call 169*4882a593Smuzhiyunthat a driver should use to unregister itself with the mdev core driver:: 170*4882a593Smuzhiyun 171*4882a593Smuzhiyun extern void mdev_unregister_device(struct device *dev); 172*4882a593Smuzhiyun 173*4882a593Smuzhiyun 174*4882a593SmuzhiyunMediated Device Management Interface Through sysfs 175*4882a593Smuzhiyun================================================== 176*4882a593Smuzhiyun 177*4882a593SmuzhiyunThe management interface through sysfs enables user space software, such as 178*4882a593Smuzhiyunlibvirt, to query and configure mediated devices in a hardware-agnostic fashion. 179*4882a593SmuzhiyunThis management interface provides flexibility to the underlying physical 180*4882a593Smuzhiyundevice's driver to support features such as: 181*4882a593Smuzhiyun 182*4882a593Smuzhiyun* Mediated device hot plug 183*4882a593Smuzhiyun* Multiple mediated devices in a single virtual machine 184*4882a593Smuzhiyun* Multiple mediated devices from different physical devices 185*4882a593Smuzhiyun 186*4882a593SmuzhiyunLinks in the mdev_bus Class Directory 187*4882a593Smuzhiyun------------------------------------- 188*4882a593SmuzhiyunThe /sys/class/mdev_bus/ directory contains links to devices that are registered 189*4882a593Smuzhiyunwith the mdev core driver. 190*4882a593Smuzhiyun 191*4882a593SmuzhiyunDirectories and files under the sysfs for Each Physical Device 192*4882a593Smuzhiyun-------------------------------------------------------------- 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun:: 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun |- [parent physical device] 197*4882a593Smuzhiyun |--- Vendor-specific-attributes [optional] 198*4882a593Smuzhiyun |--- [mdev_supported_types] 199*4882a593Smuzhiyun | |--- [<type-id>] 200*4882a593Smuzhiyun | | |--- create 201*4882a593Smuzhiyun | | |--- name 202*4882a593Smuzhiyun | | |--- available_instances 203*4882a593Smuzhiyun | | |--- device_api 204*4882a593Smuzhiyun | | |--- description 205*4882a593Smuzhiyun | | |--- [devices] 206*4882a593Smuzhiyun | |--- [<type-id>] 207*4882a593Smuzhiyun | | |--- create 208*4882a593Smuzhiyun | | |--- name 209*4882a593Smuzhiyun | | |--- available_instances 210*4882a593Smuzhiyun | | |--- device_api 211*4882a593Smuzhiyun | | |--- description 212*4882a593Smuzhiyun | | |--- [devices] 213*4882a593Smuzhiyun | |--- [<type-id>] 214*4882a593Smuzhiyun | |--- create 215*4882a593Smuzhiyun | |--- name 216*4882a593Smuzhiyun | |--- available_instances 217*4882a593Smuzhiyun | |--- device_api 218*4882a593Smuzhiyun | |--- description 219*4882a593Smuzhiyun | |--- [devices] 220*4882a593Smuzhiyun 221*4882a593Smuzhiyun* [mdev_supported_types] 222*4882a593Smuzhiyun 223*4882a593Smuzhiyun The list of currently supported mediated device types and their details. 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun [<type-id>], device_api, and available_instances are mandatory attributes 226*4882a593Smuzhiyun that should be provided by vendor driver. 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun* [<type-id>] 229*4882a593Smuzhiyun 230*4882a593Smuzhiyun The [<type-id>] name is created by adding the device driver string as a prefix 231*4882a593Smuzhiyun to the string provided by the vendor driver. This format of this name is as 232*4882a593Smuzhiyun follows:: 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name); 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun (or using mdev_parent_dev(mdev) to arrive at the parent device outside 237*4882a593Smuzhiyun of the core mdev code) 238*4882a593Smuzhiyun 239*4882a593Smuzhiyun* device_api 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun This attribute should show which device API is being created, for example, 242*4882a593Smuzhiyun "vfio-pci" for a PCI device. 243*4882a593Smuzhiyun 244*4882a593Smuzhiyun* available_instances 245*4882a593Smuzhiyun 246*4882a593Smuzhiyun This attribute should show the number of devices of type <type-id> that can be 247*4882a593Smuzhiyun created. 248*4882a593Smuzhiyun 249*4882a593Smuzhiyun* [device] 250*4882a593Smuzhiyun 251*4882a593Smuzhiyun This directory contains links to the devices of type <type-id> that have been 252*4882a593Smuzhiyun created. 253*4882a593Smuzhiyun 254*4882a593Smuzhiyun* name 255*4882a593Smuzhiyun 256*4882a593Smuzhiyun This attribute should show human readable name. This is optional attribute. 257*4882a593Smuzhiyun 258*4882a593Smuzhiyun* description 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun This attribute should show brief features/description of the type. This is 261*4882a593Smuzhiyun optional attribute. 262*4882a593Smuzhiyun 263*4882a593SmuzhiyunDirectories and Files Under the sysfs for Each mdev Device 264*4882a593Smuzhiyun---------------------------------------------------------- 265*4882a593Smuzhiyun 266*4882a593Smuzhiyun:: 267*4882a593Smuzhiyun 268*4882a593Smuzhiyun |- [parent phy device] 269*4882a593Smuzhiyun |--- [$MDEV_UUID] 270*4882a593Smuzhiyun |--- remove 271*4882a593Smuzhiyun |--- mdev_type {link to its type} 272*4882a593Smuzhiyun |--- vendor-specific-attributes [optional] 273*4882a593Smuzhiyun 274*4882a593Smuzhiyun* remove (write only) 275*4882a593Smuzhiyun 276*4882a593SmuzhiyunWriting '1' to the 'remove' file destroys the mdev device. The vendor driver can 277*4882a593Smuzhiyunfail the remove() callback if that device is active and the vendor driver 278*4882a593Smuzhiyundoesn't support hot unplug. 279*4882a593Smuzhiyun 280*4882a593SmuzhiyunExample:: 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun # echo 1 > /sys/bus/mdev/devices/$mdev_UUID/remove 283*4882a593Smuzhiyun 284*4882a593SmuzhiyunMediated device Hot plug 285*4882a593Smuzhiyun------------------------ 286*4882a593Smuzhiyun 287*4882a593SmuzhiyunMediated devices can be created and assigned at runtime. The procedure to hot 288*4882a593Smuzhiyunplug a mediated device is the same as the procedure to hot plug a PCI device. 289*4882a593Smuzhiyun 290*4882a593SmuzhiyunTranslation APIs for Mediated Devices 291*4882a593Smuzhiyun===================================== 292*4882a593Smuzhiyun 293*4882a593SmuzhiyunThe following APIs are provided for translating user pfn to host pfn in a VFIO 294*4882a593Smuzhiyundriver:: 295*4882a593Smuzhiyun 296*4882a593Smuzhiyun extern int vfio_pin_pages(struct device *dev, unsigned long *user_pfn, 297*4882a593Smuzhiyun int npage, int prot, unsigned long *phys_pfn); 298*4882a593Smuzhiyun 299*4882a593Smuzhiyun extern int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn, 300*4882a593Smuzhiyun int npage); 301*4882a593Smuzhiyun 302*4882a593SmuzhiyunThese functions call back into the back-end IOMMU module by using the pin_pages 303*4882a593Smuzhiyunand unpin_pages callbacks of the struct vfio_iommu_driver_ops[4]. Currently 304*4882a593Smuzhiyunthese callbacks are supported in the TYPE1 IOMMU module. To enable them for 305*4882a593Smuzhiyunother IOMMU backend modules, such as PPC64 sPAPR module, they need to provide 306*4882a593Smuzhiyunthese two callback functions. 307*4882a593Smuzhiyun 308*4882a593SmuzhiyunUsing the Sample Code 309*4882a593Smuzhiyun===================== 310*4882a593Smuzhiyun 311*4882a593Smuzhiyunmtty.c in samples/vfio-mdev/ directory is a sample driver program to 312*4882a593Smuzhiyundemonstrate how to use the mediated device framework. 313*4882a593Smuzhiyun 314*4882a593SmuzhiyunThe sample driver creates an mdev device that simulates a serial port over a PCI 315*4882a593Smuzhiyuncard. 316*4882a593Smuzhiyun 317*4882a593Smuzhiyun1. Build and load the mtty.ko module. 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun This step creates a dummy device, /sys/devices/virtual/mtty/mtty/ 320*4882a593Smuzhiyun 321*4882a593Smuzhiyun Files in this device directory in sysfs are similar to the following:: 322*4882a593Smuzhiyun 323*4882a593Smuzhiyun # tree /sys/devices/virtual/mtty/mtty/ 324*4882a593Smuzhiyun /sys/devices/virtual/mtty/mtty/ 325*4882a593Smuzhiyun |-- mdev_supported_types 326*4882a593Smuzhiyun | |-- mtty-1 327*4882a593Smuzhiyun | | |-- available_instances 328*4882a593Smuzhiyun | | |-- create 329*4882a593Smuzhiyun | | |-- device_api 330*4882a593Smuzhiyun | | |-- devices 331*4882a593Smuzhiyun | | `-- name 332*4882a593Smuzhiyun | `-- mtty-2 333*4882a593Smuzhiyun | |-- available_instances 334*4882a593Smuzhiyun | |-- create 335*4882a593Smuzhiyun | |-- device_api 336*4882a593Smuzhiyun | |-- devices 337*4882a593Smuzhiyun | `-- name 338*4882a593Smuzhiyun |-- mtty_dev 339*4882a593Smuzhiyun | `-- sample_mtty_dev 340*4882a593Smuzhiyun |-- power 341*4882a593Smuzhiyun | |-- autosuspend_delay_ms 342*4882a593Smuzhiyun | |-- control 343*4882a593Smuzhiyun | |-- runtime_active_time 344*4882a593Smuzhiyun | |-- runtime_status 345*4882a593Smuzhiyun | `-- runtime_suspended_time 346*4882a593Smuzhiyun |-- subsystem -> ../../../../class/mtty 347*4882a593Smuzhiyun `-- uevent 348*4882a593Smuzhiyun 349*4882a593Smuzhiyun2. Create a mediated device by using the dummy device that you created in the 350*4882a593Smuzhiyun previous step:: 351*4882a593Smuzhiyun 352*4882a593Smuzhiyun # echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1001" > \ 353*4882a593Smuzhiyun /sys/devices/virtual/mtty/mtty/mdev_supported_types/mtty-2/create 354*4882a593Smuzhiyun 355*4882a593Smuzhiyun3. Add parameters to qemu-kvm:: 356*4882a593Smuzhiyun 357*4882a593Smuzhiyun -device vfio-pci,\ 358*4882a593Smuzhiyun sysfsdev=/sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1001 359*4882a593Smuzhiyun 360*4882a593Smuzhiyun4. Boot the VM. 361*4882a593Smuzhiyun 362*4882a593Smuzhiyun In the Linux guest VM, with no hardware on the host, the device appears 363*4882a593Smuzhiyun as follows:: 364*4882a593Smuzhiyun 365*4882a593Smuzhiyun # lspci -s 00:05.0 -xxvv 366*4882a593Smuzhiyun 00:05.0 Serial controller: Device 4348:3253 (rev 10) (prog-if 02 [16550]) 367*4882a593Smuzhiyun Subsystem: Device 4348:3253 368*4882a593Smuzhiyun Physical Slot: 5 369*4882a593Smuzhiyun Control: I/O+ Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- 370*4882a593Smuzhiyun Stepping- SERR- FastB2B- DisINTx- 371*4882a593Smuzhiyun Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- 372*4882a593Smuzhiyun <TAbort- <MAbort- >SERR- <PERR- INTx- 373*4882a593Smuzhiyun Interrupt: pin A routed to IRQ 10 374*4882a593Smuzhiyun Region 0: I/O ports at c150 [size=8] 375*4882a593Smuzhiyun Region 1: I/O ports at c158 [size=8] 376*4882a593Smuzhiyun Kernel driver in use: serial 377*4882a593Smuzhiyun 00: 48 43 53 32 01 00 00 02 10 02 00 07 00 00 00 00 378*4882a593Smuzhiyun 10: 51 c1 00 00 59 c1 00 00 00 00 00 00 00 00 00 00 379*4882a593Smuzhiyun 20: 00 00 00 00 00 00 00 00 00 00 00 00 48 43 53 32 380*4882a593Smuzhiyun 30: 00 00 00 00 00 00 00 00 00 00 00 00 0a 01 00 00 381*4882a593Smuzhiyun 382*4882a593Smuzhiyun In the Linux guest VM, dmesg output for the device is as follows: 383*4882a593Smuzhiyun 384*4882a593Smuzhiyun serial 0000:00:05.0: PCI INT A -> Link[LNKA] -> GSI 10 (level, high) -> IRQ 10 385*4882a593Smuzhiyun 0000:00:05.0: ttyS1 at I/O 0xc150 (irq = 10) is a 16550A 386*4882a593Smuzhiyun 0000:00:05.0: ttyS2 at I/O 0xc158 (irq = 10) is a 16550A 387*4882a593Smuzhiyun 388*4882a593Smuzhiyun 389*4882a593Smuzhiyun5. In the Linux guest VM, check the serial ports:: 390*4882a593Smuzhiyun 391*4882a593Smuzhiyun # setserial -g /dev/ttyS* 392*4882a593Smuzhiyun /dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4 393*4882a593Smuzhiyun /dev/ttyS1, UART: 16550A, Port: 0xc150, IRQ: 10 394*4882a593Smuzhiyun /dev/ttyS2, UART: 16550A, Port: 0xc158, IRQ: 10 395*4882a593Smuzhiyun 396*4882a593Smuzhiyun6. Using minicom or any terminal emulation program, open port /dev/ttyS1 or 397*4882a593Smuzhiyun /dev/ttyS2 with hardware flow control disabled. 398*4882a593Smuzhiyun 399*4882a593Smuzhiyun7. Type data on the minicom terminal or send data to the terminal emulation 400*4882a593Smuzhiyun program and read the data. 401*4882a593Smuzhiyun 402*4882a593Smuzhiyun Data is loop backed from hosts mtty driver. 403*4882a593Smuzhiyun 404*4882a593Smuzhiyun8. Destroy the mediated device that you created:: 405*4882a593Smuzhiyun 406*4882a593Smuzhiyun # echo 1 > /sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1001/remove 407*4882a593Smuzhiyun 408*4882a593SmuzhiyunReferences 409*4882a593Smuzhiyun========== 410*4882a593Smuzhiyun 411*4882a593Smuzhiyun1. See Documentation/driver-api/vfio.rst for more information on VFIO. 412*4882a593Smuzhiyun2. struct mdev_driver in include/linux/mdev.h 413*4882a593Smuzhiyun3. struct mdev_parent_ops in include/linux/mdev.h 414*4882a593Smuzhiyun4. struct vfio_iommu_driver_ops in include/linux/vfio.h 415