mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-27 07:48:55 +00:00
agent: Bring in VFIO-AP device handling again
This PR is a continuing work for (kata-containers#3679). This generalizes the previous VFIO device handling which only focuses on PCI to include AP (IBM Z specific). Fixes: kata-containers#3678 Signed-off-by: Hyounggyu Choi <Hyounggyu.Choi@ibm.com>
This commit is contained in:
parent
f666f8e2df
commit
96baa83895
@ -1,18 +1,18 @@
|
|||||||
// Copyright (c) IBM Corp. 2022
|
// Copyright (c) IBM Corp. 2023
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
|
|
||||||
// IBM Adjunct Processor (AP) is the bus used by IBM Crypto Express hardware security modules on
|
// IBM Adjunct Processor (AP) is used for cryptographic operations
|
||||||
// IBM Z & LinuxONE (s390x)
|
// by IBM Crypto Express hardware security modules on IBM zSystem & LinuxONE (s390x).
|
||||||
// AP bus ID follow the format <xx>.<xxxx> [1, p. 476], where
|
// In Linux, virtual cryptographic devices are called AP queues.
|
||||||
// - <xx> is the adapter ID, i.e. the card and
|
// The name of an AP queue respects a format <xx>.<xxxx> in hexadecimal notation [1, p.467]:
|
||||||
// - <xxxx> is the adapter domain.
|
// - <xx> is an adapter ID
|
||||||
|
// - <xxxx> is an adapter domain ID
|
||||||
// [1] https://www.ibm.com/docs/en/linuxonibm/pdf/lku5dd05.pdf
|
// [1] https://www.ibm.com/docs/en/linuxonibm/pdf/lku5dd05.pdf
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -37,17 +37,17 @@ impl FromStr for Address {
|
|||||||
let split: Vec<&str> = s.split('.').collect();
|
let split: Vec<&str> = s.split('.').collect();
|
||||||
if split.len() != 2 {
|
if split.len() != 2 {
|
||||||
return Err(anyhow!(
|
return Err(anyhow!(
|
||||||
"Wrong AP bus format. It needs to be in the form <xx>.<xxxx>, got {:?}",
|
"Wrong AP bus format. It needs to be in the form <xx>.<xxxx> (e.g. 0a.003f), got {:?}",
|
||||||
s
|
s
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let adapter_id = u8::from_str_radix(split[0], 16).context(format!(
|
let adapter_id = u8::from_str_radix(split[0], 16).context(format!(
|
||||||
"Wrong AP bus format. AP ID needs to be in the form <xx>, got {:?}",
|
"Wrong AP bus format. AP ID needs to be in the form <xx> (e.g. 0a), got {:?}",
|
||||||
split[0]
|
split[0]
|
||||||
))?;
|
))?;
|
||||||
let adapter_domain = u16::from_str_radix(split[1], 16).context(format!(
|
let adapter_domain = u16::from_str_radix(split[1], 16).context(format!(
|
||||||
"Wrong AP bus format. AP domain needs to be in the form <xxxx>, got {:?}",
|
"Wrong AP bus format. AP domain needs to be in the form <xxxx> (e.g. 003f), got {:?}",
|
||||||
split[1]
|
split[1]
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
|
@ -764,8 +764,8 @@ async fn vfio_pci_device_handler(
|
|||||||
let mut group = None;
|
let mut group = None;
|
||||||
|
|
||||||
for opt in device.options.iter() {
|
for opt in device.options.iter() {
|
||||||
let (host, pcipath) =
|
let (host, pcipath) = split_vfio_pci_option(opt)
|
||||||
split_vfio_pci_option(opt).ok_or_else(|| anyhow!("Malformed VFIO option {:?}", opt))?;
|
.ok_or_else(|| anyhow!("Malformed VFIO PCI option {:?}", opt))?;
|
||||||
let host =
|
let host =
|
||||||
pci::Address::from_str(host).context("Bad host PCI address in VFIO option {:?}")?;
|
pci::Address::from_str(host).context("Bad host PCI address in VFIO option {:?}")?;
|
||||||
let pcipath = pci::Path::from_str(pcipath)?;
|
let pcipath = pci::Path::from_str(pcipath)?;
|
||||||
@ -809,7 +809,7 @@ async fn vfio_pci_device_handler(
|
|||||||
|
|
||||||
// The VFIO AP (Adjunct Processor) device handler takes all the APQNs provided as device options
|
// The VFIO AP (Adjunct Processor) device handler takes all the APQNs provided as device options
|
||||||
// and awaits them. It sets the minimum AP rescan time of 5 seconds and temporarily adds that
|
// and awaits them. It sets the minimum AP rescan time of 5 seconds and temporarily adds that
|
||||||
// amoutn to the hotplug timeout.
|
// amount to the hotplug timeout.
|
||||||
#[cfg(target_arch = "s390x")]
|
#[cfg(target_arch = "s390x")]
|
||||||
#[instrument]
|
#[instrument]
|
||||||
async fn vfio_ap_device_handler(
|
async fn vfio_ap_device_handler(
|
||||||
|
@ -118,6 +118,8 @@ func (device *VFIODevice) Attach(ctx context.Context, devReceiver api.DeviceRece
|
|||||||
Type: config.VFIOAPDeviceMediatedType,
|
Type: config.VFIOAPDeviceMediatedType,
|
||||||
APDevices: devices,
|
APDevices: devices,
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Failed to append device: VFIO device type unrecognized")
|
||||||
}
|
}
|
||||||
device.VfioDevs = append(device.VfioDevs, &vfio)
|
device.VfioDevs = append(device.VfioDevs, &vfio)
|
||||||
}
|
}
|
||||||
@ -216,12 +218,9 @@ func (device *VFIODevice) Load(ds config.DeviceState) {
|
|||||||
for _, dev := range ds.VFIODevs {
|
for _, dev := range ds.VFIODevs {
|
||||||
var vfio config.VFIODev
|
var vfio config.VFIODev
|
||||||
|
|
||||||
if (*device.VfioDevs[0]).GetType() == config.VFIOAPDeviceMediatedType {
|
vfioDeviceType := (*device.VfioDevs[0]).GetType()
|
||||||
vfio = config.VFIOAPDev{
|
switch vfioDeviceType {
|
||||||
ID: *(*dev).GetID(),
|
case config.VFIOPCIDeviceNormalType, config.VFIOPCIDeviceMediatedType:
|
||||||
SysfsDev: *(*dev).GetSysfsDev(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bdf := ""
|
bdf := ""
|
||||||
if pciDev, ok := (*dev).(config.VFIOPCIDev); ok {
|
if pciDev, ok := (*dev).(config.VFIOPCIDev); ok {
|
||||||
bdf = pciDev.BDF
|
bdf = pciDev.BDF
|
||||||
@ -232,6 +231,16 @@ func (device *VFIODevice) Load(ds config.DeviceState) {
|
|||||||
BDF: bdf,
|
BDF: bdf,
|
||||||
SysfsDev: *(*dev).GetSysfsDev(),
|
SysfsDev: *(*dev).GetSysfsDev(),
|
||||||
}
|
}
|
||||||
|
case config.VFIOAPDeviceMediatedType:
|
||||||
|
vfio = config.VFIOAPDev{
|
||||||
|
ID: *(*dev).GetID(),
|
||||||
|
SysfsDev: *(*dev).GetSysfsDev(),
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
deviceLogger().WithError(
|
||||||
|
fmt.Errorf("VFIO device type unrecognized"),
|
||||||
|
).Error("Failed to append device")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
device.VfioDevs = append(device.VfioDevs, &vfio)
|
device.VfioDevs = append(device.VfioDevs, &vfio)
|
||||||
|
@ -856,13 +856,8 @@ func (clh *cloudHypervisor) hotPlugVFIODevice(device *config.VFIODev) error {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), clhHotPlugAPITimeout*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), clhHotPlugAPITimeout*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
pciDevice, ok := (*device).(config.VFIOPCIDev)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("VFIO device %+v is not PCI, only PCI is supported in Cloud Hypervisor", device)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the clh device config via the constructor to ensure default values are properly assigned
|
// Create the clh device config via the constructor to ensure default values are properly assigned
|
||||||
clhDevice := *chclient.NewDeviceConfig(device.SysfsDev)
|
clhDevice := *chclient.NewDeviceConfig(*(*device).GetSysfsDev())
|
||||||
pciInfo, _, err := cl.VmAddDevicePut(ctx, clhDevice)
|
pciInfo, _, err := cl.VmAddDevicePut(ctx, clhDevice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to hotplug device %+v %s", device, openAPIClientError(err))
|
return fmt.Errorf("Failed to hotplug device %+v %s", device, openAPIClientError(err))
|
||||||
@ -885,6 +880,11 @@ func (clh *cloudHypervisor) hotPlugVFIODevice(device *config.VFIODev) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guestPciPath, err := types.PciPathFromString(tokens[0])
|
guestPciPath, err := types.PciPathFromString(tokens[0])
|
||||||
|
|
||||||
|
pciDevice, ok := (*device).(config.VFIOPCIDev)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("VFIO device %+v is not PCI, only PCI is supported in Cloud Hypervisor", device)
|
||||||
|
}
|
||||||
pciDevice.GuestPciPath = guestPciPath
|
pciDevice.GuestPciPath = guestPciPath
|
||||||
*device = pciDevice
|
*device = pciDevice
|
||||||
|
|
||||||
|
@ -141,18 +141,6 @@ func GetDevicePathAndFsTypeOptions(mountPoint string) (devicePath, fsType string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAPVFIOMediatedDevice decides whether a device is a VFIO-AP device
|
|
||||||
// by checking for the existence of "vfio_ap" in the path
|
|
||||||
func IsAPVFIOMediatedDevice(sysfsdev string) bool {
|
|
||||||
split := strings.Split(sysfsdev, string(os.PathSeparator))
|
|
||||||
for _, el := range split {
|
|
||||||
if el == vfioAPSysfsDir {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func waitProcessUsingPidfd(pid int, timeoutSecs uint, logger *logrus.Entry) (bool, error) {
|
func waitProcessUsingPidfd(pid int, timeoutSecs uint, logger *logrus.Entry) (bool, error) {
|
||||||
pidfd, err := unix.PidfdOpen(pid, 0)
|
pidfd, err := unix.PidfdOpen(pid, 0)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user