Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request kata-containers#595 from amshinde/use-main-bus-for…
Browse files Browse the repository at this point in the history
…-hotplug

vfio: Add configuration to support VFIO hotplug on root bus
  • Loading branch information
Julio Montes authored Aug 21, 2018
2 parents 0c0e17f + 31e2925 commit d6a773c
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 8 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ DEFENABLESWAP := false
DEFENABLEDEBUG := false
DEFDISABLENESTINGCHECKS := false
DEFMSIZE9P := 8192
DEFHOTPLUGVFIOONROOTBUS := false

SED = sed

Expand Down Expand Up @@ -202,6 +203,7 @@ USER_VARS += DEFENABLESWAP
USER_VARS += DEFENABLEDEBUG
USER_VARS += DEFDISABLENESTINGCHECKS
USER_VARS += DEFMSIZE9P
USER_VARS += DEFHOTPLUGVFIOONROOTBUS

V = @
Q = $(V:1=)
Expand Down Expand Up @@ -296,6 +298,7 @@ const defaultEnableSwap bool = $(DEFENABLESWAP)
const defaultEnableDebug bool = $(DEFENABLEDEBUG)
const defaultDisableNestingChecks bool = $(DEFDISABLENESTINGCHECKS)
const defaultMsize9p uint32 = $(DEFMSIZE9P)
const defaultHotplugVFIOOnRootBus bool = $(DEFHOTPLUGVFIOONROOTBUS)

// Default config file used by stateless systems.
var defaultRuntimeConfiguration = "$(CONFIG_PATH)"
Expand Down Expand Up @@ -382,6 +385,7 @@ $(GENERATED_FILES): %: %.in Makefile VERSION
-e "s|@DEFENABLEDEBUG@|$(DEFENABLEDEBUG)|g" \
-e "s|@DEFDISABLENESTINGCHECKS@|$(DEFDISABLENESTINGCHECKS)|g" \
-e "s|@DEFMSIZE9P@|$(DEFMSIZE9P)|g" \
-e "s|@DEFHOTPLUGONROOTBUS@|$(DEFHOTPLUGVFIOONROOTBUS)|g" \
$< > $@

generate-config: $(CONFIG)
Expand Down
5 changes: 4 additions & 1 deletion cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ type hypervisor struct {
MachineAccelerators string `toml:"machine_accelerators"`
KernelParams string `toml:"kernel_params"`
MachineType string `toml:"machine_type"`
BlockDeviceDriver string `toml:"block_device_driver"`
DefaultVCPUs int32 `toml:"default_vcpus"`
DefaultMaxVCPUs uint32 `toml:"default_maxvcpus"`
DefaultMemSz uint32 `toml:"default_memory"`
DefaultBridges uint32 `toml:"default_bridges"`
Msize9p uint32 `toml:"msize_9p"`
BlockDeviceDriver string `toml:"block_device_driver"`
DisableBlockDeviceUse bool `toml:"disable_block_device_use"`
MemPrealloc bool `toml:"enable_mem_prealloc"`
HugePages bool `toml:"enable_hugepages"`
Expand All @@ -93,6 +93,7 @@ type hypervisor struct {
DisableNestingChecks bool `toml:"disable_nesting_checks"`
EnableIOThreads bool `toml:"enable_iothreads"`
UseVSock bool `toml:"use_vsock"`
HotplugVFIOOnRootBus bool `toml:"hotplug_vfio_on_root_bus"`
}

type proxy struct {
Expand Down Expand Up @@ -373,6 +374,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
EnableIOThreads: h.EnableIOThreads,
Msize9p: h.msize9p(),
UseVSock: useVSock,
HotplugVFIOOnRootBus: h.HotplugVFIOOnRootBus,
}, nil
}

Expand Down Expand Up @@ -489,6 +491,7 @@ func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPat
BlockDeviceDriver: defaultBlockDeviceDriver,
EnableIOThreads: defaultEnableIOThreads,
Msize9p: defaultMsize9p,
HotplugVFIOOnRootBus: defaultHotplugVFIOOnRootBus,
}

err = config.InterNetworkModel.SetModel(defaultInterNetworkingModel)
Expand Down
7 changes: 7 additions & 0 deletions cli/config/configuration.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ enable_iothreads = @DEFENABLEIOTHREADS@
# Default false
#use_vsock = true

# VFIO devices are hotplugged on a bridge by default.
# Enable hotplugging on root bus. This may be required for devices with
# a large PCI bar, as this is a current limitation with hotplugging on
# a bridge. This value is valid for "pc" machine type.
# Default false
#hotplug_vfio_on_root_bus = true

[factory]
# VM templating support. Once enabled, new VMs are created from template
# using vm cloning. They will share the same initial kernel, initramfs and
Expand Down
14 changes: 12 additions & 2 deletions cli/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type testRuntimeConfig struct {
LogPath string
}

func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool) string {
func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool, hotplugVFIOOnRootBus bool) string {
return `
# Runtime configuration file
Expand All @@ -49,6 +49,7 @@ func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath
default_memory = ` + strconv.FormatUint(uint64(defaultMemSize), 10) + `
disable_block_device_use = ` + strconv.FormatBool(disableBlock) + `
enable_iothreads = ` + strconv.FormatBool(enableIOThreads) + `
hotplug_vfio_on_root_bus = ` + strconv.FormatBool(hotplugVFIOOnRootBus) + `
msize_9p = ` + strconv.FormatUint(uint64(defaultMsize9p), 10) + `
[proxy.kata]
Expand Down Expand Up @@ -97,8 +98,9 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
disableBlockDevice := true
blockDeviceDriver := "virtio-scsi"
enableIOThreads := true
hotplugVFIOOnRootBus := true

runtimeConfigFileData := makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, logPath, disableBlockDevice, blockDeviceDriver, enableIOThreads)
runtimeConfigFileData := makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, logPath, disableBlockDevice, blockDeviceDriver, enableIOThreads, hotplugVFIOOnRootBus)

configPath := path.Join(dir, "runtime.toml")
err = createConfig(configPath, runtimeConfigFileData)
Expand Down Expand Up @@ -138,6 +140,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
DefaultBridges: defaultBridgesCount,
Mlock: !defaultEnableSwap,
EnableIOThreads: enableIOThreads,
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
Msize9p: defaultMsize9p,
}

Expand Down Expand Up @@ -617,6 +620,7 @@ func TestNewQemuHypervisorConfig(t *testing.T) {
machineType := "machineType"
disableBlock := true
enableIOThreads := true
hotplugVFIOOnRootBus := true
orgVSockDevicePath := utils.VSockDevicePath
orgVHostVSockDevicePath := utils.VHostVSockDevicePath
defer func() {
Expand All @@ -633,6 +637,7 @@ func TestNewQemuHypervisorConfig(t *testing.T) {
MachineType: machineType,
DisableBlockDeviceUse: disableBlock,
EnableIOThreads: enableIOThreads,
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
UseVSock: true,
}

Expand Down Expand Up @@ -688,6 +693,9 @@ func TestNewQemuHypervisorConfig(t *testing.T) {
t.Errorf("Expected value for enable IOThreads %v, got %v", enableIOThreads, config.EnableIOThreads)
}

if config.HotplugVFIOOnRootBus != hotplugVFIOOnRootBus {
t.Errorf("Expected value for HotplugVFIOOnRootBus %v, got %v", hotplugVFIOOnRootBus, config.HotplugVFIOOnRootBus)
}
}

func TestNewQemuHypervisorConfigImageAndInitrd(t *testing.T) {
Expand All @@ -710,6 +718,7 @@ func TestNewQemuHypervisorConfigImageAndInitrd(t *testing.T) {
machineType := "machineType"
disableBlock := true
enableIOThreads := true
hotplugVFIOOnRootBus := true

hypervisor := hypervisor{
Path: hypervisorPath,
Expand All @@ -719,6 +728,7 @@ func TestNewQemuHypervisorConfigImageAndInitrd(t *testing.T) {
MachineType: machineType,
DisableBlockDeviceUse: disableBlock,
EnableIOThreads: enableIOThreads,
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
}

_, err = newQemuHypervisorConfig(hypervisor)
Expand Down
2 changes: 2 additions & 0 deletions cli/kata-env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
disableBlock := true
blockStorageDriver := "virtio-scsi"
enableIOThreads := true
hotplugVFIOOnRootBus := true

// override
defaultProxyPath = proxyPath
Expand Down Expand Up @@ -109,6 +110,7 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
disableBlock,
blockStorageDriver,
enableIOThreads,
hotplugVFIOOnRootBus,
)

configFile = path.Join(prefixDir, "runtime.toml")
Expand Down
4 changes: 4 additions & 0 deletions virtcontainers/hypervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ type HypervisorConfig struct {
// UseVSock use a vsock for agent communication
UseVSock bool

// HotplugVFIOOnRootBus is used to indicate if devices need to be hotplugged on the
// root bus instead of a bridge.
HotplugVFIOOnRootBus bool

// BootToBeTemplate used to indicate if the VM is created to be a template VM
BootToBeTemplate bool

Expand Down
22 changes: 17 additions & 5 deletions virtcontainers/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ type CPUDevice struct {
type QemuState struct {
Bridges []Bridge
// HotpluggedCPUs is the list of CPUs that were hot-added
HotpluggedVCPUs []CPUDevice
HotpluggedMemory int
UUID string
HotpluggedVCPUs []CPUDevice
HotpluggedMemory int
UUID string
HotplugVFIOOnRootBus bool
}

// qemu is an Hypervisor interface implementation for the Linux qemu hypervisor.
Expand Down Expand Up @@ -195,6 +196,8 @@ func (q *qemu) init(id string, hypervisorConfig *HypervisorConfig, vmConfig Reso
q.Logger().Debug("Creating UUID")
q.state.UUID = uuid.Generate().String()

q.state.HotplugVFIOOnRootBus = q.config.HotplugVFIOOnRootBus

// The path might already exist, but in case of VM templating,
// we have to create it since the sandbox has not created it yet.
if err = os.MkdirAll(filepath.Join(runStoragePath, id), dirMode); err != nil {
Expand Down Expand Up @@ -736,6 +739,13 @@ func (q *qemu) hotplugVFIODevice(device *config.VFIODev, op operation) error {
devID := device.ID

if op == addDevice {
// In case HotplugVFIOOnRootBus is true, devices are hotplugged on the root bus
// for pc machine type instead of bridge. This is useful for devices that require
// a large PCI BAR which is a currently a limitation with PCI bridges.
if q.state.HotplugVFIOOnRootBus {
return q.qmpMonitorCh.qmp.ExecuteVFIODeviceAdd(q.qmpMonitorCh.ctx, devID, device.BDF)
}

addr, bridge, err := q.addDeviceToBridge(devID)
if err != nil {
return err
Expand All @@ -745,8 +755,10 @@ func (q *qemu) hotplugVFIODevice(device *config.VFIODev, op operation) error {
return err
}
} else {
if err := q.removeDeviceFromBridge(devID); err != nil {
return err
if !q.state.HotplugVFIOOnRootBus {
if err := q.removeDeviceFromBridge(devID); err != nil {
return err
}
}

if err := q.qmpMonitorCh.qmp.ExecuteDeviceDel(q.qmpMonitorCh.ctx, devID); err != nil {
Expand Down

0 comments on commit d6a773c

Please sign in to comment.