1 Star 1 Fork 0

孙磊 / runtime

Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
Clone or Download
qemu_arch_base.go 21.19 KB
Copy Edit Raw Blame History
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"context"
"encoding/hex"
"errors"
"fmt"
"os"
"strconv"
"strings"
govmmQemu "github.com/intel/govmm/qemu"
"github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/types"
"github.com/kata-containers/runtime/virtcontainers/utils"
)
type qemuArch interface {
// enableNestingChecks nesting checks will be honoured
enableNestingChecks()
// disableNestingChecks nesting checks will be ignored
disableNestingChecks()
// runNested indicates if the hypervisor runs in a nested environment
runNested() bool
// enableVhostNet vhost will be enabled
enableVhostNet()
// disableVhostNet vhost will be disabled
disableVhostNet()
// machine returns the machine type
machine() (govmmQemu.Machine, error)
// qemuPath returns the path to the QEMU binary
qemuPath() (string, error)
// kernelParameters returns the kernel parameters
// if debug is true then kernel debug parameters are included
kernelParameters(debug bool) []Param
//capabilities returns the capabilities supported by QEMU
capabilities() types.Capabilities
// bridges sets the number bridges for the machine type
bridges(number uint32)
// cpuTopology returns the CPU topology for the given amount of vcpus
cpuTopology(vcpus, maxvcpus uint32) govmmQemu.SMP
// cpuModel returns the CPU model for the machine type
cpuModel() string
// memoryTopology returns the memory topology using the given amount of memoryMb and hostMemoryMb
memoryTopology(memoryMb, hostMemoryMb uint64, slots uint8) govmmQemu.Memory
// appendConsole appends a console to devices
appendConsole(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error)
// appendImage appends an image to devices
appendImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error)
// appendBlockImage appends an image as block device
appendBlockImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error)
// appendNvdimmImage appends an image as nvdimm device
appendNvdimmImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error)
// appendSCSIController appens a SCSI controller to devices
appendSCSIController(devices []govmmQemu.Device, enableIOThreads bool) ([]govmmQemu.Device, *govmmQemu.IOThread, error)
// appendBridges appends bridges to devices
appendBridges(devices []govmmQemu.Device) []govmmQemu.Device
// append9PVolume appends a 9P volume to devices
append9PVolume(devices []govmmQemu.Device, volume types.Volume) ([]govmmQemu.Device, error)
// appendSocket appends a socket to devices
appendSocket(devices []govmmQemu.Device, socket types.Socket) []govmmQemu.Device
// appendVSock appends a vsock PCI to devices
appendVSock(devices []govmmQemu.Device, vsock types.VSock) ([]govmmQemu.Device, error)
// appendNetwork appends a endpoint device to devices
appendNetwork(devices []govmmQemu.Device, endpoint Endpoint) ([]govmmQemu.Device, error)
// appendBlockDevice appends a block drive to devices
appendBlockDevice(devices []govmmQemu.Device, drive config.BlockDrive) ([]govmmQemu.Device, error)
// appendVhostUserDevice appends a vhost user device to devices
appendVhostUserDevice(devices []govmmQemu.Device, drive config.VhostUserDeviceAttrs) ([]govmmQemu.Device, error)
// appendVFIODevice appends a VFIO device to devices
appendVFIODevice(devices []govmmQemu.Device, vfioDevice config.VFIODev) []govmmQemu.Device
// appendRNGDevice appends a RNG device to devices
appendRNGDevice(devices []govmmQemu.Device, rngDevice config.RNGDev) ([]govmmQemu.Device, error)
// addDeviceToBridge adds devices to the bus
addDeviceToBridge(ID string, t types.Type) (string, types.Bridge, error)
// removeDeviceFromBridge removes devices to the bus
removeDeviceFromBridge(ID string) error
// getBridges grants access to Bridges
getBridges() []types.Bridge
// setBridges grants access to Bridges
setBridges(bridges []types.Bridge)
// addBridge adds a new Bridge to the list of Bridges
addBridge(types.Bridge)
// handleImagePath handles the Hypervisor Config image path
handleImagePath(config HypervisorConfig)
// supportGuestMemoryHotplug returns if the guest supports memory hotplug
supportGuestMemoryHotplug() bool
// setIgnoreSharedMemoryMigrationCaps set bypass-shared-memory capability for migration
setIgnoreSharedMemoryMigrationCaps(context.Context, *govmmQemu.QMP) error
// appendPCIeRootPortDevice appends a pcie-root-port device to pcie.0 bus
appendPCIeRootPortDevice(devices []govmmQemu.Device, number uint32) []govmmQemu.Device
}
type qemuArchBase struct {
machineType string
memoryOffset uint32
nestedRun bool
vhost bool
disableNvdimm bool
dax bool
networkIndex int
qemuPaths map[string]string
supportedQemuMachines []govmmQemu.Machine
kernelParamsNonDebug []Param
kernelParamsDebug []Param
kernelParams []Param
Bridges []types.Bridge
}
const (
defaultCores uint32 = 1
defaultThreads uint32 = 1
defaultCPUModel = "host"
defaultBridgeBus = "pcie.0"
defaultPCBridgeBus = "pci.0"
maxDevIDSize = 31
defaultMsize9p = 8192
pcieRootPortPrefix = "rp"
)
// This is the PCI start address assigned to the first bridge that
// is added on the qemu command line. In case of x86_64, the first two PCI
// addresses (0 and 1) are used by the platform while in case of ARM, address
// 0 is reserved.
const bridgePCIStartAddr = 2
const (
// QemuPCLite is the QEMU pc-lite machine type for amd64
QemuPCLite = "pc-lite"
// QemuPC is the QEMU pc machine type for amd64
QemuPC = "pc"
// QemuQ35 is the QEMU Q35 machine type for amd64
QemuQ35 = "q35"
// QemuMicrovm is the QEMU microvm machine type for amd64
QemuMicrovm = "microvm"
// QemuVirt is the QEMU virt machine type for aarch64 or amd64
QemuVirt = "virt"
// QemuPseries is a QEMU virt machine type for ppc64le
QemuPseries = "pseries"
// QemuCCWVirtio is a QEMU virt machine type for for s390x
QemuCCWVirtio = "s390-ccw-virtio"
qmpCapMigrationIgnoreShared = "x-ignore-shared"
qemuNvdimmOption = "nvdimm"
)
// kernelParamsNonDebug is a list of the default kernel
// parameters that will be used in standard (non-debug) mode.
var kernelParamsNonDebug = []Param{
{"quiet", ""},
}
// kernelParamsSystemdNonDebug is a list of the default systemd related
// kernel parameters that will be used in standard (non-debug) mode.
var kernelParamsSystemdNonDebug = []Param{
{"systemd.show_status", "false"},
}
// kernelParamsDebug is a list of the default kernel
// parameters that will be used in debug mode (as much boot output as
// possible).
var kernelParamsDebug = []Param{
{"debug", ""},
}
// kernelParamsSystemdDebug is a list of the default systemd related kernel
// parameters that will be used in debug mode (as much boot output as
// possible).
var kernelParamsSystemdDebug = []Param{
{"systemd.show_status", "true"},
{"systemd.log_level", "debug"},
}
func (q *qemuArchBase) enableNestingChecks() {
q.nestedRun = true
}
func (q *qemuArchBase) disableNestingChecks() {
q.nestedRun = false
}
func (q *qemuArchBase) runNested() bool {
return q.nestedRun
}
func (q *qemuArchBase) enableVhostNet() {
q.vhost = true
}
func (q *qemuArchBase) disableVhostNet() {
q.vhost = false
}
func (q *qemuArchBase) machine() (govmmQemu.Machine, error) {
for _, m := range q.supportedQemuMachines {
if m.Type == q.machineType {
return m, nil
}
}
return govmmQemu.Machine{}, fmt.Errorf("unrecognised machine type: %v", q.machineType)
}
func (q *qemuArchBase) qemuPath() (string, error) {
p, ok := q.qemuPaths[q.machineType]
if !ok {
return "", fmt.Errorf("Unknown machine type: %s", q.machineType)
}
return p, nil
}
func (q *qemuArchBase) kernelParameters(debug bool) []Param {
params := q.kernelParams
if debug {
params = append(params, q.kernelParamsDebug...)
} else {
params = append(params, q.kernelParamsNonDebug...)
}
return params
}
func (q *qemuArchBase) capabilities() types.Capabilities {
var caps types.Capabilities
caps.SetBlockDeviceHotplugSupport()
caps.SetMultiQueueSupport()
caps.SetFsSharingSupport()
return caps
}
func (q *qemuArchBase) bridges(number uint32) {
for i := uint32(0); i < number; i++ {
q.Bridges = append(q.Bridges, types.NewBridge(types.PCI, fmt.Sprintf("%s-bridge-%d", types.PCI, i), make(map[uint32]string), 0))
}
}
func (q *qemuArchBase) cpuTopology(vcpus, maxvcpus uint32) govmmQemu.SMP {
smp := govmmQemu.SMP{
CPUs: vcpus,
Sockets: maxvcpus,
Cores: defaultCores,
Threads: defaultThreads,
MaxCPUs: maxvcpus,
}
return smp
}
func (q *qemuArchBase) cpuModel() string {
return defaultCPUModel
}
func (q *qemuArchBase) memoryTopology(memoryMb, hostMemoryMb uint64, slots uint8) govmmQemu.Memory {
memMax := fmt.Sprintf("%dM", hostMemoryMb)
mem := fmt.Sprintf("%dM", memoryMb)
memory := govmmQemu.Memory{
Size: mem,
Slots: slots,
MaxMem: memMax,
}
return memory
}
func (q *qemuArchBase) appendConsole(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
serial := govmmQemu.SerialDevice{
Driver: govmmQemu.VirtioSerial,
ID: "serial0",
DisableModern: q.nestedRun,
}
devices = append(devices, serial)
console := govmmQemu.CharDevice{
Driver: govmmQemu.Console,
Backend: govmmQemu.Socket,
DeviceID: "console0",
ID: "charconsole0",
Path: path,
}
devices = append(devices, console)
return devices, nil
}
func genericImage(path string) (config.BlockDrive, error) {
if _, err := os.Stat(path); os.IsNotExist(err) {
return config.BlockDrive{}, err
}
randBytes, err := utils.GenerateRandomBytes(8)
if err != nil {
return config.BlockDrive{}, err
}
id := utils.MakeNameID("image", hex.EncodeToString(randBytes), maxDevIDSize)
drive := config.BlockDrive{
File: path,
Format: "raw",
ID: id,
ShareRW: true,
ReadOnly: true,
}
return drive, nil
}
func (q *qemuArchBase) appendNvdimmImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
imageFile, err := os.Open(path)
if err != nil {
return nil, err
}
defer imageFile.Close()
imageStat, err := imageFile.Stat()
if err != nil {
return nil, err
}
object := govmmQemu.Object{
Driver: govmmQemu.NVDIMM,
Type: govmmQemu.MemoryBackendFile,
DeviceID: "nv0",
ID: "mem0",
MemPath: path,
Size: (uint64)(imageStat.Size()),
}
devices = append(devices, object)
return devices, nil
}
func (q *qemuArchBase) appendImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
return q.appendBlockImage(devices, path)
}
func (q *qemuArchBase) appendBlockImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
drive, err := genericImage(path)
if err != nil {
return nil, err
}
devices, err = q.appendBlockDevice(devices, drive)
if err != nil {
return nil, err
}
return devices, nil
}
func genericSCSIController(enableIOThreads, nestedRun bool) (govmmQemu.SCSIController, *govmmQemu.IOThread) {
scsiController := govmmQemu.SCSIController{
ID: scsiControllerID,
DisableModern: nestedRun,
}
var t *govmmQemu.IOThread
if enableIOThreads {
randBytes, _ := utils.GenerateRandomBytes(8)
t = &govmmQemu.IOThread{
ID: fmt.Sprintf("%s-%s", "iothread", hex.EncodeToString(randBytes)),
}
scsiController.IOThread = t.ID
}
return scsiController, t
}
func (q *qemuArchBase) appendSCSIController(devices []govmmQemu.Device, enableIOThreads bool) ([]govmmQemu.Device, *govmmQemu.IOThread, error) {
d, t := genericSCSIController(enableIOThreads, q.nestedRun)
devices = append(devices, d)
return devices, t, nil
}
// appendBridges appends to devices the given bridges
func (q *qemuArchBase) appendBridges(devices []govmmQemu.Device) []govmmQemu.Device {
for idx, b := range q.Bridges {
if b.Type == types.CCW {
continue
}
t := govmmQemu.PCIBridge
if b.Type == types.PCIE {
t = govmmQemu.PCIEBridge
}
q.Bridges[idx].Addr = bridgePCIStartAddr + idx
devices = append(devices,
govmmQemu.BridgeDevice{
Type: t,
Bus: defaultBridgeBus,
ID: b.ID,
// Each bridge is required to be assigned a unique chassis id > 0
Chassis: idx + 1,
SHPC: true,
Addr: strconv.FormatInt(int64(q.Bridges[idx].Addr), 10),
},
)
}
return devices
}
func generic9PVolume(volume types.Volume, nestedRun bool) govmmQemu.FSDevice {
devID := fmt.Sprintf("extra-9p-%s", volume.MountTag)
if len(devID) > maxDevIDSize {
devID = devID[:maxDevIDSize]
}
return govmmQemu.FSDevice{
Driver: govmmQemu.Virtio9P,
FSDriver: govmmQemu.Local,
ID: devID,
Path: volume.HostPath,
MountTag: volume.MountTag,
SecurityModel: govmmQemu.None,
DisableModern: nestedRun,
}
}
func (q *qemuArchBase) append9PVolume(devices []govmmQemu.Device, volume types.Volume) ([]govmmQemu.Device, error) {
if volume.MountTag == "" || volume.HostPath == "" {
return devices, nil
}
d := generic9PVolume(volume, q.nestedRun)
devices = append(devices, d)
return devices, nil
}
func (q *qemuArchBase) appendSocket(devices []govmmQemu.Device, socket types.Socket) []govmmQemu.Device {
devID := socket.ID
if len(devID) > maxDevIDSize {
devID = devID[:maxDevIDSize]
}
devices = append(devices,
govmmQemu.CharDevice{
Driver: govmmQemu.VirtioSerialPort,
Backend: govmmQemu.Socket,
DeviceID: socket.DeviceID,
ID: devID,
Path: socket.HostPath,
Name: socket.Name,
},
)
return devices
}
func (q *qemuArchBase) appendVSock(devices []govmmQemu.Device, vsock types.VSock) ([]govmmQemu.Device, error) {
devices = append(devices,
govmmQemu.VSOCKDevice{
ID: fmt.Sprintf("vsock-%d", vsock.ContextID),
ContextID: vsock.ContextID,
VHostFD: vsock.VhostFd,
DisableModern: q.nestedRun,
},
)
return devices, nil
}
func networkModelToQemuType(model NetInterworkingModel) govmmQemu.NetDeviceType {
switch model {
case NetXConnectMacVtapModel:
return govmmQemu.MACVTAP
default:
//TAP should work for most other cases
return govmmQemu.TAP
}
}
func genericNetwork(endpoint Endpoint, vhost, nestedRun bool, index int) (govmmQemu.NetDevice, error) {
var d govmmQemu.NetDevice
switch ep := endpoint.(type) {
case *VethEndpoint, *BridgedMacvlanEndpoint, *IPVlanEndpoint:
netPair := ep.NetworkPair()
d = govmmQemu.NetDevice{
Type: networkModelToQemuType(netPair.NetInterworkingModel),
Driver: govmmQemu.VirtioNet,
ID: fmt.Sprintf("network-%d", index),
IFName: netPair.TAPIface.Name,
MACAddress: netPair.TAPIface.HardAddr,
DownScript: "no",
Script: "no",
VHost: vhost,
DisableModern: nestedRun,
FDs: netPair.VMFds,
VhostFDs: netPair.VhostFds,
}
case *MacvtapEndpoint:
d = govmmQemu.NetDevice{
Type: govmmQemu.MACVTAP,
Driver: govmmQemu.VirtioNet,
ID: fmt.Sprintf("network-%d", index),
IFName: ep.Name(),
MACAddress: ep.HardwareAddr(),
DownScript: "no",
Script: "no",
VHost: vhost,
DisableModern: nestedRun,
FDs: ep.VMFds,
VhostFDs: ep.VhostFds,
}
case *TuntapEndpoint:
netPair := ep.NetworkPair()
d = govmmQemu.NetDevice{
Type: govmmQemu.NetDeviceType("tap"),
Driver: govmmQemu.VirtioNet,
ID: fmt.Sprintf("network-%d", index),
IFName: netPair.TAPIface.Name,
MACAddress: netPair.TAPIface.HardAddr,
DownScript: "no",
Script: "no",
VHost: vhost,
DisableModern: nestedRun,
FDs: netPair.VMFds,
VhostFDs: netPair.VhostFds,
}
default:
return govmmQemu.NetDevice{}, fmt.Errorf("Unknown type for endpoint")
}
return d, nil
}
func (q *qemuArchBase) appendNetwork(devices []govmmQemu.Device, endpoint Endpoint) ([]govmmQemu.Device, error) {
d, err := genericNetwork(endpoint, q.vhost, q.nestedRun, q.networkIndex)
if err != nil {
return devices, fmt.Errorf("Failed to append network %v", err)
}
q.networkIndex++
devices = append(devices, d)
return devices, nil
}
func genericBlockDevice(drive config.BlockDrive, nestedRun bool) (govmmQemu.BlockDevice, error) {
if drive.File == "" || drive.ID == "" || drive.Format == "" {
return govmmQemu.BlockDevice{}, fmt.Errorf("Empty File, ID or Format for drive %v", drive)
}
if len(drive.ID) > maxDevIDSize {
drive.ID = drive.ID[:maxDevIDSize]
}
return govmmQemu.BlockDevice{
Driver: govmmQemu.VirtioBlock,
ID: drive.ID,
File: drive.File,
AIO: govmmQemu.Threads,
Format: govmmQemu.BlockDeviceFormat(drive.Format),
Interface: "none",
DisableModern: nestedRun,
ShareRW: drive.ShareRW,
ReadOnly: drive.ReadOnly,
}, nil
}
func (q *qemuArchBase) appendBlockDevice(devices []govmmQemu.Device, drive config.BlockDrive) ([]govmmQemu.Device, error) {
d, err := genericBlockDevice(drive, q.nestedRun)
if err != nil {
return devices, fmt.Errorf("Failed to append block device %v", err)
}
devices = append(devices, d)
return devices, nil
}
func (q *qemuArchBase) appendVhostUserDevice(devices []govmmQemu.Device, attr config.VhostUserDeviceAttrs) ([]govmmQemu.Device, error) {
qemuVhostUserDevice := govmmQemu.VhostUserDevice{}
switch attr.Type {
case config.VhostUserNet:
qemuVhostUserDevice.TypeDevID = utils.MakeNameID("net", attr.DevID, maxDevIDSize)
qemuVhostUserDevice.Address = attr.MacAddress
qemuVhostUserDevice.VhostUserType = govmmQemu.VhostUserNet
case config.VhostUserSCSI:
qemuVhostUserDevice.TypeDevID = utils.MakeNameID("scsi", attr.DevID, maxDevIDSize)
qemuVhostUserDevice.VhostUserType = govmmQemu.VhostUserSCSI
case config.VhostUserBlk:
qemuVhostUserDevice.VhostUserType = govmmQemu.VhostUserBlk
case config.VhostUserFS:
qemuVhostUserDevice.TypeDevID = utils.MakeNameID("fs", attr.DevID, maxDevIDSize)
qemuVhostUserDevice.Tag = attr.Tag
qemuVhostUserDevice.CacheSize = attr.CacheSize
qemuVhostUserDevice.VhostUserType = govmmQemu.VhostUserFS
}
qemuVhostUserDevice.SocketPath = attr.SocketPath
qemuVhostUserDevice.CharDevID = utils.MakeNameID("char", attr.DevID, maxDevIDSize)
devices = append(devices, qemuVhostUserDevice)
return devices, nil
}
func (q *qemuArchBase) appendVFIODevice(devices []govmmQemu.Device, vfioDev config.VFIODev) []govmmQemu.Device {
if vfioDev.BDF == "" {
return devices
}
devices = append(devices,
govmmQemu.VFIODevice{
BDF: vfioDev.BDF,
VendorID: vfioDev.VendorID,
DeviceID: vfioDev.DeviceID,
Bus: vfioDev.Bus,
},
)
return devices
}
func (q *qemuArchBase) appendRNGDevice(devices []govmmQemu.Device, rngDev config.RNGDev) ([]govmmQemu.Device, error) {
devices = append(devices,
govmmQemu.RngDevice{
ID: rngDev.ID,
Filename: rngDev.Filename,
},
)
return devices, nil
}
func (q *qemuArchBase) handleImagePath(config HypervisorConfig) {
if config.ImagePath != "" {
kernelRootParams := commonVirtioblkKernelRootParams
if !q.disableNvdimm {
for i := range q.supportedQemuMachines {
q.supportedQemuMachines[i].Options = strings.Join([]string{
q.supportedQemuMachines[i].Options,
qemuNvdimmOption,
}, ",")
}
if q.dax {
kernelRootParams = commonNvdimmKernelRootParams
} else {
kernelRootParams = commonNvdimmNoDAXKernelRootParams
}
}
q.kernelParams = append(q.kernelParams, kernelRootParams...)
q.kernelParamsNonDebug = append(q.kernelParamsNonDebug, kernelParamsSystemdNonDebug...)
q.kernelParamsDebug = append(q.kernelParamsDebug, kernelParamsSystemdDebug...)
}
}
func (q *qemuArchBase) supportGuestMemoryHotplug() bool {
return true
}
func (q *qemuArchBase) setIgnoreSharedMemoryMigrationCaps(ctx context.Context, qmp *govmmQemu.QMP) error {
err := qmp.ExecSetMigrationCaps(ctx, []map[string]interface{}{
{
"capability": qmpCapMigrationIgnoreShared,
"state": true,
},
})
return err
}
func (q *qemuArchBase) addDeviceToBridge(ID string, t types.Type) (string, types.Bridge, error) {
var err error
var addr uint32
if len(q.Bridges) == 0 {
return "", types.Bridge{}, errors.New("failed to get available address from bridges")
}
// looking for an empty address in the bridges
for _, b := range q.Bridges {
if t != b.Type {
continue
}
addr, err = b.AddDevice(ID)
if err == nil {
switch t {
case types.CCW:
return fmt.Sprintf("%04x", addr), b, nil
case types.PCI, types.PCIE:
return fmt.Sprintf("%02x", addr), b, nil
}
}
}
return "", types.Bridge{}, fmt.Errorf("no more bridge slots available")
}
func (q *qemuArchBase) removeDeviceFromBridge(ID string) error {
var err error
for _, b := range q.Bridges {
err = b.RemoveDevice(ID)
if err == nil {
// device was removed correctly
return nil
}
}
return err
}
func (q *qemuArchBase) getBridges() []types.Bridge {
return q.Bridges
}
func (q *qemuArchBase) setBridges(bridges []types.Bridge) {
q.Bridges = bridges
}
func (q *qemuArchBase) addBridge(b types.Bridge) {
q.Bridges = append(q.Bridges, b)
}
// appendPCIeRootPortDevice appends to devices the given pcie-root-port
func (q *qemuArchBase) appendPCIeRootPortDevice(devices []govmmQemu.Device, number uint32) []govmmQemu.Device {
return genericAppendPCIeRootPort(devices, number, q.machineType)
}
1
https://gitee.com/leisunstar/runtime.git
git@gitee.com:leisunstar/runtime.git
leisunstar
runtime
runtime
5cef3e7b53f9

Search