| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package guestman
- import (
- "fmt"
- "strconv"
- "strings"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/onecloud/pkg/hostman/guestman/desc"
- "yunion.io/x/onecloud/pkg/hostman/guestman/qemu"
- "yunion.io/x/onecloud/pkg/hostman/monitor"
- "yunion.io/x/onecloud/pkg/hostman/options"
- "yunion.io/x/onecloud/pkg/scheduler/api"
- "yunion.io/x/onecloud/pkg/util/fileutils2"
- )
- func (s *SKVMGuestInstance) addPCIController(controllerType, bus desc.PCI_CONTROLLER_TYPE) *desc.PCIController {
- cont := desc.NewPCIController(controllerType)
- cont.PCIDevice = desc.NewPCIDevice(bus, "", "")
- if s.Desc.PCIControllers == nil {
- s.Desc.PCIControllers = make([]*desc.PCIController, 0)
- }
- s.Desc.PCIControllers = append(s.Desc.PCIControllers, cont)
- return cont
- }
- func (s *SKVMGuestInstance) pciControllerFind(cont desc.PCI_CONTROLLER_TYPE) *desc.PCIController {
- for i := 0; i < len(s.Desc.PCIControllers); i++ {
- if s.Desc.PCIControllers[i].CType == cont {
- return s.Desc.PCIControllers[i]
- }
- }
- return nil
- }
- func (s *SKVMGuestInstance) initGuestDesc() error {
- err := s.initCpuDesc(0)
- if err != nil {
- return err
- }
- err = s.initMemDesc(s.Desc.Mem)
- if err != nil {
- return errors.Wrap(err, "initMemDesc")
- }
- s.initMachineDesc()
- pciRoot, pciBridge := s.initGuestPciControllers(s.manager.host.IsKvmSupport())
- err = s.initGuestPciAddresses()
- if err != nil {
- return errors.Wrap(err, "init guest pci addresses")
- }
- err = s.initGuestDevicesDesc(pciRoot, pciBridge)
- if err != nil {
- return err
- }
- if err := s.initMachineDefaultAddresses(); err != nil {
- return errors.Wrap(err, "init machine default devices")
- }
- return s.ensurePciAddresses()
- }
- func (s *SKVMGuestInstance) initGuestDevicesDesc(pciRoot, pciBridge *desc.PCIController) error {
- // vdi device for spice
- s.Desc.VdiDevice = new(desc.SGuestVdi)
- if s.IsVdiSpice() {
- s.initSpiceDevices(pciRoot)
- }
- s.initVirtioSerial(pciRoot)
- s.initGuestVga(pciRoot)
- s.initCdromDesc()
- s.initFloppyDesc()
- s.initGuestDisks(pciRoot, pciBridge, false)
- if err := s.initGuestNetworks(pciRoot, pciBridge); err != nil {
- return errors.Wrap(err, "init guest networks")
- }
- s.initIsolatedDevices(pciRoot, pciBridge)
- s.initUsbController(pciRoot)
- s.initRandomDevice(pciRoot, options.HostOptions.EnableVirtioRngDevice)
- s.initQgaDesc()
- s.initPvpanicDesc()
- s.initIsaSerialDesc()
- s.initTpmDesc()
- return nil
- }
- func (s *SKVMGuestInstance) loadGuestPciAddresses() error {
- err := s.initGuestPciAddresses()
- if err != nil {
- return errors.Wrap(err, "init guest pci addresses")
- }
- if err := s.initMachineDefaultAddresses(); err != nil {
- return errors.Wrap(err, "init machine default devices")
- }
- err = s.ensurePciAddresses()
- if err != nil {
- return errors.Wrap(err, "load desc ensure pci address")
- }
- if err = SaveLiveDesc(s, s.Desc); err != nil {
- return errors.Wrap(err, "loadGuestPciAddresses save desc")
- }
- return nil
- }
- func (s *SKVMGuestInstance) initMachineDefaultAddresses() error {
- switch s.Desc.Machine {
- case "pc":
- I440FXSlot1 := &desc.PCIDevice{
- PCIAddr: &desc.PCIAddr{Bus: 0, Slot: 1},
- Controller: desc.CONTROLLER_TYPE_PCI_ROOT,
- }
- // ISA bridge
- multiFunc := true
- if err := s.ensureDevicePciAddress(I440FXSlot1, 0, &multiFunc); err != nil {
- return err
- }
- // primary IDE controller
- if err := s.ensureDevicePciAddress(I440FXSlot1, 1, nil); err != nil {
- return err
- }
- // PIIX3 USB controller
- if err := s.ensureDevicePciAddress(I440FXSlot1, 2, nil); err != nil {
- return err
- }
- // ACPI (power management) and SMBus controller
- if err := s.ensureDevicePciAddress(I440FXSlot1, 3, nil); err != nil {
- return err
- }
- case "q35":
- Q35Slot31 := &desc.PCIDevice{
- PCIAddr: &desc.PCIAddr{Bus: 0, Slot: 31},
- Controller: desc.CONTROLLER_TYPE_PCIE_ROOT,
- }
- // ISA bridge
- multiFunc := true
- if err := s.ensureDevicePciAddress(Q35Slot31, 0, &multiFunc); err != nil {
- return err
- }
- // primary SATA controller
- if err := s.ensureDevicePciAddress(Q35Slot31, 2, nil); err != nil {
- return err
- }
- // SMBus
- if err := s.ensureDevicePciAddress(Q35Slot31, 3, nil); err != nil {
- return err
- }
- // usb controllers
- Q35Slot29 := &desc.PCIDevice{
- PCIAddr: &desc.PCIAddr{Bus: 0, Slot: 29},
- Controller: desc.CONTROLLER_TYPE_PCIE_ROOT,
- }
- multiFunc = true
- if err := s.ensureDevicePciAddress(Q35Slot29, 0, &multiFunc); err != nil {
- return err
- }
- if err := s.ensureDevicePciAddress(Q35Slot29, 1, nil); err != nil {
- return err
- }
- if err := s.ensureDevicePciAddress(Q35Slot29, 2, nil); err != nil {
- return err
- }
- if err := s.ensureDevicePciAddress(Q35Slot29, 7, nil); err != nil {
- return err
- }
- case "virt":
- // do nothing
- }
- return nil
- }
- func (s *SKVMGuestInstance) isMachineDefaultAddress(pciAddr *desc.PCIAddr) bool {
- switch s.Desc.Machine {
- case "pc":
- if pciAddr.Bus == 0 && pciAddr.Slot == 1 && pciAddr.Function < 4 {
- return true
- }
- case "q35":
- if pciAddr.Bus == 0 && pciAddr.Slot == 29 {
- switch pciAddr.Function {
- case 0, 1, 2, 7:
- return true
- }
- } else if pciAddr.Bus == 0 && pciAddr.Slot == 31 {
- switch pciAddr.Function {
- case 0, 2, 3:
- return true
- }
- }
- }
- return false
- }
- func (s *SKVMGuestInstance) initGuestPciControllers(pciExtend bool) (*desc.PCIController, *desc.PCIController) {
- var pciRoot, pciBridge *desc.PCIController
- if len(s.Desc.PCIControllers) > 0 {
- pciRoot = s.Desc.PCIControllers[0]
- if len(s.Desc.PCIControllers) > 1 {
- pciBridge = s.Desc.PCIControllers[1]
- }
- return pciRoot, pciBridge
- }
- if s.isPcie() {
- pciRoot = s.addPCIController(desc.CONTROLLER_TYPE_PCIE_ROOT, "")
- if pciExtend {
- s.addPCIController(desc.CONTROLLER_TYPE_PCIE_TO_PCI_BRIDGE, desc.CONTROLLER_TYPE_PCIE_ROOT)
- pciBridge = s.addPCIController(desc.CONTROLLER_TYPE_PCI_BRIDGE, desc.CONTROLLER_TYPE_PCIE_TO_PCI_BRIDGE)
- for i := 0; i < s.vfioDevCount()+options.HostOptions.PcieRootPortCount; i++ {
- s.addPCIController(desc.CONTROLLER_TYPE_PCIE_ROOT_PORT, desc.CONTROLLER_TYPE_PCIE_ROOT)
- }
- }
- } else {
- pciRoot = s.addPCIController(desc.CONTROLLER_TYPE_PCI_ROOT, "")
- }
- return pciRoot, pciBridge
- }
- func (s *SKVMGuestInstance) initGuestPciAddresses() error {
- s.pciAddrs = &desc.SGuestPCIAddresses{
- Buses: make([]*desc.SGuestPCIAddressBus, len(s.Desc.PCIControllers)),
- }
- var err error
- for i := 0; i < len(s.pciAddrs.Buses); i++ {
- s.pciAddrs.Buses[i], err = desc.NewGuestPCIAddressBus(s.Desc.PCIControllers[i].CType)
- if err != nil {
- return err
- }
- }
- return nil
- }
- func (s *SKVMGuestInstance) cleanGuestPciAddressed() {
- s.pciAddrs = nil
- }
- func (s *SKVMGuestInstance) initRandomDevice(pciRoot *desc.PCIController, enableVirtioRngDevice bool) {
- if !enableVirtioRngDevice {
- return
- }
- var randev string
- if fileutils2.Exists("/dev/urandom") {
- randev = "/dev/urandom"
- } else if fileutils2.Exists("/dev/random") {
- randev = "/dev/random"
- } else {
- return
- }
- s.Desc.Rng = &desc.SGuestRng{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-rng-pci", "random0"),
- RngRandom: desc.NewObject("rng-random", "rng0"),
- }
- s.Desc.Rng.Options = map[string]string{
- "max-bytes": "1024",
- "period": "1000",
- }
- s.Desc.Rng.RngRandom.Options = map[string]string{
- "filename": randev,
- }
- }
- func (s *SKVMGuestInstance) initUsbController(pciRoot *desc.PCIController) {
- contType := s.getUsbControllerType()
- s.Desc.Usb = &desc.UsbController{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, contType, "usb"),
- }
- }
- func (s *SKVMGuestInstance) initGuestNetworks(pciRoot, pciBridge *desc.PCIController) error {
- cont := pciRoot
- if pciBridge != nil {
- cont = pciBridge
- }
- if s.GetOsName() == OS_NAME_ANDROID {
- s.Desc.Nics = s.Desc.Nics[:1]
- }
- for i := 0; i < len(s.Desc.Nics); i++ {
- if err := s.generateNicScripts(s.Desc.Nics[i]); err != nil {
- return errors.Wrapf(err, "generateNicScripts for nic: %v", s.Desc.Nics[i])
- }
- s.Desc.Nics[i].UpscriptPath = s.getNicUpScriptPath(s.Desc.Nics[i])
- s.Desc.Nics[i].DownscriptPath = s.getNicDownScriptPath(s.Desc.Nics[i])
- if s.Desc.Nics[i].Driver != "vfio-pci" {
- switch s.GetOsName() {
- case OS_NAME_MACOS:
- vectors := 0
- s.Desc.Nics[i].Vectors = &vectors
- s.Desc.Nics[i].Driver = "e1000"
- case OS_NAME_VMWARE:
- s.Desc.Nics[i].Driver = "vmxnet3"
- }
- if s.Desc.Nics[i].NumQueues > 1 {
- vectors := s.Desc.Nics[i].NumQueues*2 + 1
- s.Desc.Nics[i].Vectors = &vectors
- }
- id := fmt.Sprintf("netdev-%s", s.Desc.Nics[i].Ifname)
- switch s.Desc.Nics[i].Driver {
- case "virtio":
- s.Desc.Nics[i].Pci = desc.NewPCIDevice(cont.CType, "virtio-net-pci", id)
- case "e1000":
- s.Desc.Nics[i].Pci = desc.NewPCIDevice(cont.CType, "e1000-82545em", id)
- case "vmxnet3":
- s.Desc.Nics[i].Pci = desc.NewPCIDevice(cont.CType, "vmxnet3", id)
- case "rtl8139":
- s.Desc.Nics[i].Pci = desc.NewPCIDevice(cont.CType, "rtl8139", id)
- }
- }
- }
- return nil
- }
- func (s *SKVMGuestInstance) initIsolatedDevices(pciRoot, pciBridge *desc.PCIController) {
- cType := s.getVfioDeviceHotPlugPciControllerType()
- if cType == nil {
- cType = &pciRoot.CType
- if pciBridge != nil {
- cType = &pciBridge.CType
- }
- }
- manager := s.manager.GetHost().GetIsolatedDeviceManager()
- for i := 0; i < len(s.Desc.IsolatedDevices); i++ {
- dev := manager.GetDeviceByAddr(s.Desc.IsolatedDevices[i].Addr)
- if s.Desc.IsolatedDevices[i].DevType == api.USB_TYPE {
- s.Desc.IsolatedDevices[i].Usb = desc.NewUsbDevice("usb-host", dev.GetQemuId())
- s.Desc.IsolatedDevices[i].Usb.Options = dev.GetPassthroughOptions()
- } else {
- id := dev.GetQemuId()
- s.Desc.IsolatedDevices[i].VfioDevs = make([]*desc.VFIODevice, 0)
- vfioDev := desc.NewVfioDevice(
- *cType, "vfio-pci", id, dev.GetAddr(), s.Desc.IsolatedDevices[i].DevType == api.GPU_VGA_TYPE,
- )
- s.Desc.IsolatedDevices[i].VfioDevs = append(s.Desc.IsolatedDevices[i].VfioDevs, vfioDev)
- groupDevAddrs := dev.GetIOMMUGroupRestAddrs()
- for j := 0; j < len(groupDevAddrs); j++ {
- gid := fmt.Sprintf("%s-%d", id, j+1)
- vfioDev = desc.NewVfioDevice(*cType, "vfio-pci", gid, groupDevAddrs[j], false)
- s.Desc.IsolatedDevices[i].VfioDevs = append(
- s.Desc.IsolatedDevices[i].VfioDevs, vfioDev,
- )
- }
- }
- }
- }
- func (s *SKVMGuestInstance) initCdromDesc() {
- if s.Desc.Cdroms == nil {
- s.Desc.Cdroms = make([]*desc.SGuestCdrom, options.HostOptions.CdromCount)
- for i := range s.Desc.Cdroms {
- s.Desc.Cdroms[i] = new(desc.SGuestCdrom)
- s.Desc.Cdroms[i].Ordinal = int64(i)
- }
- }
- for i := range s.Desc.Cdroms {
- s.archMan.GenerateCdromDesc(s.GetOsName(), s.Desc.Cdroms[i])
- }
- }
- func (s *SKVMGuestInstance) initFloppyDesc() {
- if s.Desc.Machine != "pc" || s.GetOsName() != OS_NAME_WINDOWS {
- return
- }
- if s.Desc.Floppys == nil {
- s.Desc.Floppys = make([]*desc.SGuestFloppy, options.HostOptions.FloppyCount)
- for i := range s.Desc.Floppys {
- s.Desc.Floppys[i] = new(desc.SGuestFloppy)
- s.Desc.Floppys[i].Ordinal = int64(i)
- }
- }
- for i := range s.Desc.Floppys {
- s.archMan.GenerateFloppyDesc(s.GetOsName(), s.Desc.Floppys[i])
- }
- }
- func (s *SKVMGuestInstance) initGuestDisks(pciRoot, pciBridge *desc.PCIController, loadGuest bool) {
- if !loadGuest {
- hasVirtioScsi, hasPvScsi, hasSataDisk := s.fixDiskDriver()
- if hasVirtioScsi && s.Desc.VirtioScsi == nil {
- s.Desc.VirtioScsi = &desc.SGuestVirtioScsi{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-scsi-pci", "scsi"),
- }
- } else if hasPvScsi && s.Desc.PvScsi == nil {
- s.Desc.PvScsi = &desc.SGuestPvScsi{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "pvscsi", "scsi"),
- }
- } else if hasSataDisk {
- s.Desc.SataController = &desc.SGuestAhciDevice{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "ahci", "ahci0"),
- }
- }
- }
- cont := pciRoot
- if pciBridge != nil {
- cont = pciBridge
- }
- for i := 0; i < len(s.Desc.Disks); i++ {
- devType := qemu.GetDiskDeviceModel(s.Desc.Disks[i].Driver)
- id := fmt.Sprintf("drive_%d", s.Desc.Disks[i].Index)
- if s.Desc.Disks[i].Pci != nil || s.Desc.Disks[i].Scsi != nil {
- log.Infof("guest %s disk %v has been init", s.Desc.Uuid, s.Desc.Disks[i].Index)
- continue
- }
- switch s.Desc.Disks[i].Driver {
- case DISK_DRIVER_VIRTIO:
- if s.Desc.Disks[i].Pci == nil {
- s.Desc.Disks[i].Pci = desc.NewPCIDevice(cont.CType, devType, id)
- }
- case DISK_DRIVER_SCSI:
- if s.Desc.VirtioScsi == nil {
- s.Desc.VirtioScsi = &desc.SGuestVirtioScsi{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-scsi-pci", "scsi"),
- }
- }
- s.Desc.Disks[i].Scsi = desc.NewScsiDevice(s.Desc.VirtioScsi.Id, devType, id)
- case DISK_DRIVER_PVSCSI:
- if s.Desc.PvScsi == nil {
- s.Desc.PvScsi = &desc.SGuestPvScsi{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "pvscsi", "scsi"),
- }
- }
- s.Desc.Disks[i].Scsi = desc.NewScsiDevice(s.Desc.PvScsi.Id, devType, id)
- case DISK_DRIVER_IDE:
- s.Desc.Disks[i].Ide = desc.NewIdeDevice(devType, id)
- case DISK_DRIVER_SATA: // -device ahci,id=ahci pci device
- s.Desc.Disks[i].Ide = desc.NewIdeDevice(devType, id)
- }
- }
- }
- func (s *SKVMGuestInstance) fixDiskDriver() (bool, bool, bool) {
- var virtioScsi, pvScsi, sataDisk = false, false, false
- isX86 := s.manager.host.IsX8664()
- osname := s.GetOsName()
- for i := 0; i < len(s.Desc.Disks); i++ {
- if !isX86 && (s.Desc.Disks[i].Driver == DISK_DRIVER_IDE ||
- s.Desc.Disks[i].Driver == DISK_DRIVER_SATA) {
- s.Desc.Disks[i].Driver = DISK_DRIVER_SCSI
- } else if osname == OS_NAME_MACOS {
- s.Desc.Disks[i].Driver = DISK_DRIVER_SATA
- }
- switch s.Desc.Disks[i].Driver {
- case DISK_DRIVER_SCSI:
- virtioScsi = true
- case DISK_DRIVER_PVSCSI:
- pvScsi = true
- case DISK_DRIVER_SATA:
- sataDisk = true
- }
- }
- return virtioScsi, pvScsi, sataDisk
- }
- func (s *SKVMGuestInstance) initVirtioSerial(pciRoot *desc.PCIController) {
- s.Desc.VirtioSerial = new(desc.SGuestVirtioSerial)
- s.Desc.VirtioSerial.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "virtio-serial-pci", "virtio-serial0")
- }
- func (s *SKVMGuestInstance) initGuestVga(pciRoot *desc.PCIController) {
- var isNotX86 = !s.manager.host.IsX8664()
- if s.gpusHasVga() {
- s.Desc.Vga = "none"
- } else if isNotX86 {
- s.Desc.Vga = "virtio-gpu"
- } else if s.Desc.Vga == "" {
- s.Desc.Vga = "std"
- }
- s.Desc.VgaDevice = new(desc.SGuestVga)
- var vgaDevName string
- var options map[string]string
- switch s.Desc.Vga {
- case "std":
- vgaDevName = "VGA"
- case "qxl":
- vgaDevName = "qxl-vga"
- options = map[string]string{
- "ram_size": "141557760",
- "vram_size": "141557760",
- }
- case "cirros":
- vgaDevName = "cirrus-vga"
- case "vmware":
- vgaDevName = "vmware-svga"
- case "virtio":
- vgaDevName = "virtio-vga"
- case "virtio-gpu":
- vgaDevName = "virtio-gpu-pci"
- options = map[string]string{
- "max_outputs": "1",
- }
- case "", "none":
- vgaDevName = "none"
- }
- if vgaDevName != "none" {
- s.Desc.VgaDevice.PCIDevice = desc.NewPCIDevice(pciRoot.CType, vgaDevName, "video0")
- s.Desc.VgaDevice.PCIDevice.Options = options
- }
- }
- func (s *SKVMGuestInstance) initSpiceDevices(pciRoot *desc.PCIController) {
- spice := new(desc.SSpiceDesc)
- spice.IntelHDA = &desc.SoundCard{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "intel-hda", "sound0"),
- Codec: &desc.Codec{
- Id: "sound0-codec0",
- Type: "hda-duplex",
- Cad: 0,
- },
- }
- var ehciId = "usbspice"
- spice.UsbRedirct = &desc.UsbRedirctDesc{
- EHCI1: desc.NewUsbController("", -1),
- UHCI1: desc.NewUsbController(ehciId, 0),
- UHCI2: desc.NewUsbController(ehciId, 2),
- UHCI3: desc.NewUsbController(ehciId, 4),
- }
- spice.UsbRedirct.UsbRedirDev1 = &desc.UsbRedir{
- Id: "usbredirdev1",
- Source: desc.NewCharDev("spicevmc", "usbredirchardev1", "usbredir"),
- }
- spice.UsbRedirct.UsbRedirDev2 = &desc.UsbRedir{
- Id: "usbredirdev2",
- Source: desc.NewCharDev("spicevmc", "usbredirchardev2", "usbredir"),
- }
- spice.UsbRedirct.EHCI1.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "ich9-usb-ehci1", ehciId)
- spice.UsbRedirct.UHCI1.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "ich9-usb-uhci1", "uhci1")
- spice.UsbRedirct.UHCI2.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "ich9-usb-uhci2", "uhci2")
- spice.UsbRedirct.UHCI3.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "ich9-usb-uhci3", "uhci3")
- spice.VdagentSerial = &desc.SGuestVirtioSerial{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-serial-pci", "vdagent-serial0"),
- }
- spice.Vdagent = desc.NewCharDev("spicevmc", "vdagent", "vdagent")
- spice.VdagentSerialPort = &desc.VirtSerialPort{
- Chardev: "vdagent",
- Name: "com.redhat.spice.0",
- Options: map[string]string{
- "nr": "1",
- },
- }
- spice.Options = map[string]string{
- "disable-ticketing": "off",
- "seamless-migration": "on",
- }
- s.Desc.VdiDevice.Spice = spice
- }
- func (s *SKVMGuestInstance) ensureDevicePciAddress(
- dev *desc.PCIDevice, function int, multiFunc *bool,
- ) error {
- if function >= 8 {
- return errors.Errorf("invalid function %x", function)
- } else if function < 0 {
- // if function not given, give them default function 0
- if dev.PCIAddr != nil {
- function = int(dev.Function)
- } else {
- function = 0
- }
- }
- if dev.PCIAddr != nil {
- dev.Function = uint(function)
- return s.pciAddrs.Buses[dev.Bus].EnsureSlotFunction(dev.Slot, dev.Function)
- }
- bus, slot, found := s.findUnusedSlotForController(dev.Controller, function)
- if !found {
- return errors.Errorf("no valid pci address found ?")
- }
- s.pciAddrs.Buses[bus].EnsureSlotFunction(uint(slot), uint(function))
- dev.PCIAddr = &desc.PCIAddr{
- Bus: uint(bus),
- Slot: uint(slot),
- Function: uint(function),
- Multi: multiFunc,
- }
- return nil
- }
- func (s *SKVMGuestInstance) findUnusedSlotForController(cont desc.PCI_CONTROLLER_TYPE, function int) (int, int, bool) {
- var (
- bus, slot = 0, 0
- found = false
- )
- for ; bus < len(s.pciAddrs.Buses); bus++ {
- if cont == s.pciAddrs.Buses[bus].Contorller {
- slot = s.pciAddrs.Buses[bus].FindNextUnusedSlot(uint(function))
- if slot >= 0 {
- found = true
- break
- }
- }
- }
- return bus, slot, found
- }
- func (s *SKVMGuestInstance) ensurePciAddresses() error {
- var err error
- if s.Desc.VgaDevice != nil && s.Desc.VgaDevice.PCIDevice != nil {
- err = s.ensureDevicePciAddress(s.Desc.VgaDevice.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure vga pci address")
- }
- }
- if s.Desc.VirtioSerial != nil {
- err = s.ensureDevicePciAddress(s.Desc.VirtioSerial.PCIDevice, -1, nil)
- }
- if s.Desc.VdiDevice != nil && s.Desc.VdiDevice.Spice != nil {
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.IntelHDA.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure vdi hda pci address")
- }
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.VdagentSerial.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure vdagent serial pci address")
- }
- multiFunc := true
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIDevice, 0, &multiFunc)
- if err != nil {
- return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
- }
- s.Desc.VdiDevice.Spice.UsbRedirct.UHCI2.PCIAddr = s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIAddr.Copy()
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI2.PCIDevice, 1, &multiFunc)
- if err != nil {
- return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
- }
- s.Desc.VdiDevice.Spice.UsbRedirct.UHCI3.PCIAddr = s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIAddr.Copy()
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI3.PCIDevice, 2, &multiFunc)
- if err != nil {
- return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
- }
- s.Desc.VdiDevice.Spice.UsbRedirct.EHCI1.PCIAddr = s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIAddr.Copy()
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.EHCI1.PCIDevice, 7, &multiFunc)
- if err != nil {
- return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
- }
- }
- if s.Desc.VirtioScsi != nil {
- err = s.ensureDevicePciAddress(s.Desc.VirtioScsi.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure virtio scsi pci address")
- }
- } else if s.Desc.PvScsi != nil {
- err = s.ensureDevicePciAddress(s.Desc.PvScsi.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure pvscsi pci address")
- }
- }
- if s.Desc.SataController != nil {
- err = s.ensureDevicePciAddress(s.Desc.SataController.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure SataController pci address")
- }
- }
- // skip pci root or pcie root
- for i := 1; i < len(s.Desc.PCIControllers); i++ {
- err = s.ensureDevicePciAddress(s.Desc.PCIControllers[i].PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure pci controllers address")
- }
- }
- for i := 0; i < len(s.Desc.Disks); i++ {
- if s.Desc.Disks[i].Pci != nil {
- err = s.ensureDevicePciAddress(s.Desc.Disks[i].Pci, -1, nil)
- if err != nil {
- return errors.Wrapf(err, "ensure disk %d pci address", s.Desc.Disks[i].Index)
- }
- }
- }
- for i := 0; i < len(s.Desc.Nics); i++ {
- if s.Desc.Nics[i].Pci != nil {
- err = s.ensureDevicePciAddress(s.Desc.Nics[i].Pci, -1, nil)
- if err != nil {
- return errors.Wrapf(err, "ensure nic %s pci address", s.Desc.Nics[i].Ifname)
- }
- }
- }
- for i := 0; i < len(s.Desc.IsolatedDevices); i++ {
- if len(s.Desc.IsolatedDevices[i].VfioDevs) > 0 {
- multiFunc := len(s.Desc.IsolatedDevices[i].VfioDevs) > 1
- err = s.ensureDevicePciAddress(s.Desc.IsolatedDevices[i].VfioDevs[0].PCIDevice, 0, &multiFunc)
- if err != nil {
- return errors.Wrapf(err, "ensure isolated device %s pci address", s.Desc.IsolatedDevices[i].VfioDevs[0].PCIAddr)
- }
- for j := 1; j < len(s.Desc.IsolatedDevices[i].VfioDevs); j++ {
- s.Desc.IsolatedDevices[i].VfioDevs[j].PCIAddr = s.Desc.IsolatedDevices[i].VfioDevs[0].PCIAddr.Copy()
- err = s.ensureDevicePciAddress(s.Desc.IsolatedDevices[i].VfioDevs[j].PCIDevice, j, nil)
- if err != nil {
- return errors.Wrapf(err, "ensure isolated device %s pci address", s.Desc.IsolatedDevices[i].VfioDevs[j].PCIAddr)
- }
- }
- }
- }
- if s.Desc.Usb != nil {
- err = s.ensureDevicePciAddress(s.Desc.Usb.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure usb controller pci address")
- }
- }
- if s.Desc.Rng != nil {
- err = s.ensureDevicePciAddress(s.Desc.Rng.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure random device pci address")
- }
- }
- anonymousPCIDevs := s.Desc.AnonymousPCIDevs[:0]
- for i := 0; i < len(s.Desc.AnonymousPCIDevs); i++ {
- if s.isMachineDefaultAddress(s.Desc.AnonymousPCIDevs[i].PCIAddr) {
- if _, inUse := s.pciAddrs.IsAddrInUse(s.Desc.AnonymousPCIDevs[i].PCIAddr); inUse {
- log.Infof("guest %s anonymous dev addr %s in use", s.GetName(), s.Desc.AnonymousPCIDevs[i].String())
- continue
- }
- }
- err = s.ensureDevicePciAddress(s.Desc.AnonymousPCIDevs[i], -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure anonymous pci dev pci address")
- }
- anonymousPCIDevs = append(anonymousPCIDevs, s.Desc.AnonymousPCIDevs[i])
- }
- if len(anonymousPCIDevs) == 0 {
- anonymousPCIDevs = nil
- }
- s.Desc.AnonymousPCIDevs = anonymousPCIDevs
- return nil
- }
- func (s *SKVMGuestInstance) getNetdevOfThePciAddress(qtree string, addr *desc.PCIAddr) string {
- var slotFunc = fmt.Sprintf("addr = %02x.%x", addr.Slot, addr.Function)
- var addressFound = false
- var lines = strings.Split(strings.TrimSuffix(qtree, "\r\n"), "\\r\\n")
- var currentIndentLevel = -1
- for _, line := range lines {
- trimmedLine := strings.TrimSpace(line)
- if trimmedLine == "" {
- continue
- }
- if currentIndentLevel > 0 {
- newIndentLevel := len(line) - len(trimmedLine)
- if newIndentLevel <= currentIndentLevel {
- if addressFound {
- break
- }
- currentIndentLevel = -1
- continue
- }
- if strings.HasPrefix(trimmedLine, slotFunc) {
- addressFound = true
- continue
- }
- if strings.HasPrefix(trimmedLine, "netdev =") {
- segs := strings.Split(trimmedLine, " ")
- netdev := strings.Trim(segs[2], `\\"`)
- log.Infof("found netdev %s: %s", netdev, trimmedLine)
- return netdev
- } else {
- continue
- }
- }
- if strings.HasPrefix(trimmedLine, "dev: virtio-net-pci") {
- currentIndentLevel = len(line) - len(trimmedLine)
- } else {
- continue
- }
- }
- return ""
- }
- // guests description no pci description before host-agent assign pci device address info
- // in this case wo need query pci address info by `query-pci` command. Also memory devices.
- func (s *SKVMGuestInstance) initGuestDescFromExistingGuest(
- cpuList []monitor.HotpluggableCPU, pciInfoList []monitor.PCIInfo,
- memoryDevicesInfoList []monitor.MemoryDeviceInfo, memDevs []monitor.Memdev,
- scsiNumQueues int64, qtree string,
- ) error {
- if len(pciInfoList) > 1 {
- return errors.Errorf("unsupported pci info list with multi bus")
- }
- unknownDevices := make([]monitor.PCIDeviceInfo, 0)
- err := s.initCpuDesc(uint(len(cpuList)))
- if err != nil {
- return err
- }
- err = s.initMemDescFromMemoryInfo(memoryDevicesInfoList, memDevs)
- if err != nil {
- return errors.Wrap(err, "init guest memory devices")
- }
- s.initMachineDesc()
- if s.manager.host.IsX8664() && !s.hasHpet(qtree) {
- noHpet := true
- s.Desc.NoHpet = &noHpet
- }
- // This code is designed to ensure compatibility with older guests.
- // However, it is not recommended for new guests to generate a desc file from it
- pciRoot, _ := s.initGuestPciControllers(false)
- err = s.initGuestPciAddresses()
- if err != nil {
- return errors.Wrap(err, "init guest pci addresses")
- }
- if err := s.initGuestNetworks(pciRoot, nil); err != nil {
- return errors.Wrap(err, "init guest networks")
- }
- //s.initIsolatedDevices(pciRoot, nil)
- s.initQgaDesc()
- s.initPvpanicDesc()
- s.initIsaSerialDesc()
- s.Desc.VdiDevice = new(desc.SGuestVdi)
- for i := 0; i < len(pciInfoList[0].Devices); i++ {
- pciAddr := &desc.PCIAddr{
- Bus: uint(pciInfoList[0].Devices[i].Bus),
- Slot: uint(pciInfoList[0].Devices[i].Slot),
- Function: uint(pciInfoList[0].Devices[i].Function),
- }
- switch pciInfoList[0].Devices[i].QdevID {
- case "scsi":
- _, hasPvScsi, _ := s.fixDiskDriver()
- if hasPvScsi && s.Desc.PvScsi == nil {
- s.Desc.PvScsi = &desc.SGuestPvScsi{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "pvscsi", "scsi"),
- }
- } else if s.Desc.VirtioScsi == nil {
- s.Desc.VirtioScsi = &desc.SGuestVirtioScsi{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-scsi-pci", "scsi"),
- }
- }
- if s.Desc.VirtioScsi != nil {
- s.Desc.VirtioScsi.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VirtioScsi.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure virtio scsi pci address")
- }
- if scsiNumQueues > 1 {
- numQueues := uint8(scsiNumQueues)
- s.Desc.VirtioScsi.NumQueues = &numQueues
- }
- } else if s.Desc.PvScsi != nil {
- s.Desc.PvScsi.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.PvScsi.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure pvscsi pci address")
- }
- }
- case "video0", "video1":
- if s.Desc.VgaDevice == nil {
- s.initGuestVga(pciRoot)
- }
- s.Desc.VgaDevice.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VgaDevice.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure vga pci address")
- }
- case "random0":
- if s.Desc.Rng == nil {
- // in case rng device disable by host options
- s.initRandomDevice(pciRoot, true)
- }
- s.Desc.Rng.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.Rng.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure random device pci address")
- }
- case "usb":
- if s.Desc.Usb == nil {
- s.initUsbController(pciRoot)
- }
- s.Desc.Usb.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.Usb.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure usb controller pci address")
- }
- case "sound0":
- if s.Desc.VdiDevice.Spice == nil {
- s.Desc.Vdi = "spice"
- s.initSpiceDevices(pciRoot)
- }
- s.Desc.VdiDevice.Spice.IntelHDA.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.IntelHDA.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure vdi hda pci address")
- }
- case "vdagent-serial0":
- if s.Desc.VdiDevice.Spice == nil {
- s.Desc.Vdi = "spice"
- s.initSpiceDevices(pciRoot)
- }
- s.Desc.VdiDevice.Spice.VdagentSerial.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.VdagentSerial.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure vdagent serial pci address")
- }
- case "virtio-serial0":
- if s.Desc.VirtioSerial == nil {
- s.initVirtioSerial(pciRoot)
- }
- s.Desc.VirtioSerial.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VirtioSerial.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure virtio serial address")
- }
- case "usbspice":
- if s.Desc.VdiDevice.Spice == nil {
- s.Desc.Vdi = "spice"
- s.initSpiceDevices(pciRoot)
- }
- s.Desc.VdiDevice.Spice.UsbRedirct.EHCI1.PCIAddr = pciAddr
- multiFunc := true
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.EHCI1.PCIDevice, -1, &multiFunc)
- if err != nil {
- return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
- }
- case "uhci1":
- if s.Desc.VdiDevice.Spice == nil {
- s.Desc.Vdi = "spice"
- s.initSpiceDevices(pciRoot)
- }
- multiFunc := true
- s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIDevice, -1, &multiFunc)
- if err != nil {
- return errors.Wrap(err, "ensure vdi usb uhci1 pci address")
- }
- case "uhci2":
- if s.Desc.VdiDevice.Spice == nil {
- s.Desc.Vdi = "spice"
- s.initSpiceDevices(pciRoot)
- }
- multiFunc := true
- s.Desc.VdiDevice.Spice.UsbRedirct.UHCI2.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI2.PCIDevice, -1, &multiFunc)
- if err != nil {
- return errors.Wrap(err, "ensure vdi usb uhci2 pci address")
- }
- case "uhci3":
- if s.Desc.VdiDevice.Spice == nil {
- s.Desc.Vdi = "spice"
- s.initSpiceDevices(pciRoot)
- }
- multiFunc := true
- s.Desc.VdiDevice.Spice.UsbRedirct.UHCI3.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI3.PCIDevice, -1, &multiFunc)
- if err != nil {
- return errors.Wrap(err, "ensure vdi usb uhci3 pci address")
- }
- case "ahci0":
- if s.Desc.SataController == nil {
- s.Desc.SataController = &desc.SGuestAhciDevice{
- PCIDevice: desc.NewPCIDevice(pciRoot.CType, "ahci", "ahci0"),
- }
- }
- s.Desc.SataController.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.SataController.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure SataController pci address")
- }
- default:
- switch {
- case strings.HasPrefix(pciInfoList[0].Devices[i].QdevID, "drive_"):
- indexStr := strings.TrimPrefix(pciInfoList[0].Devices[i].QdevID, "drive_")
- index, err := strconv.Atoi(indexStr)
- if err != nil {
- log.Errorf("failed parse disk pci id %s", pciInfoList[0].Devices[i].QdevID)
- unknownDevices = append(unknownDevices, pciInfoList[0].Devices[i])
- continue
- }
- for i := 0; i < len(s.Desc.Disks); i++ {
- if s.Desc.Disks[i].Index == int8(index) {
- if s.Desc.Disks[i].Pci == nil {
- devType := qemu.GetDiskDeviceModel(DISK_DRIVER_VIRTIO)
- s.Desc.Disks[i].Pci = desc.NewPCIDevice(pciRoot.CType, devType, pciInfoList[0].Devices[i].QdevID)
- s.Desc.Disks[i].Scsi = nil
- s.Desc.Disks[i].Ide = nil
- s.Desc.Disks[i].Driver = DISK_DRIVER_VIRTIO
- }
- s.Desc.Disks[i].Pci.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.Disks[i].Pci, -1, nil)
- if err != nil {
- return errors.Wrapf(err, "ensure disk %d pci address", s.Desc.Disks[i].Index)
- }
- }
- }
- case strings.HasPrefix(pciInfoList[0].Devices[i].QdevID, "netdev-"):
- ifname := strings.TrimPrefix(pciInfoList[0].Devices[i].QdevID, "netdev-")
- for i := 0; i < len(s.Desc.Nics); i++ {
- if s.Desc.Nics[i].Ifname == ifname {
- s.Desc.Nics[i].Pci.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.Nics[i].Pci, -1, nil)
- if err != nil {
- return errors.Wrapf(err, "ensure nic %s pci address", s.Desc.Nics[i].Ifname)
- }
- }
- }
- default:
- class := pciInfoList[0].Devices[i].ClassInfo.Class
- vendor := pciInfoList[0].Devices[i].ID.Vendor
- device := pciInfoList[0].Devices[i].ID.Device
- switch { // qemu: docs/specs/pci-ids.txt
- case class == 3075 && vendor == 6966 && device == 13: // { 0x0c03, "USB controller", "usb"}, 1b36:000d PCI xhci usb host adapter
- if s.Desc.Usb == nil {
- s.initUsbController(pciRoot)
- }
- s.Desc.Usb.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.Usb.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure usb controller pci address")
- }
- case class == 255 && vendor == 6900 && device == 4101: // 0x00ff, 1af4:1005 entropy generator device (legacy)
- if s.Desc.Rng == nil {
- // in case rng device disable by host options
- s.initRandomDevice(pciRoot, true)
- }
- s.Desc.Rng.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.Rng.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure random device pci address")
- }
- case class == 1920 && vendor == 6900 && device == 4099: // 0x0780, 1af4:1003 console device (legacy)
- if s.Desc.VirtioSerial == nil {
- s.initVirtioSerial(pciRoot)
- }
- s.Desc.VirtioSerial.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VirtioSerial.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure virtio serial address")
- }
- case class == 768 && vendor == 4660 && device == 4369: // { 0x0300, "VGA controller", "display", 0x00ff}, PCI ID: 1234:1111
- if s.Desc.VgaDevice == nil {
- s.initGuestVga(pciRoot)
- }
- s.Desc.VgaDevice.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.VgaDevice.PCIDevice, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure vga pci address")
- }
- case class == 512 && vendor == 6900 && device == 4096: // { 0x0200, "Ethernet controller", "ethernet"}, 1af4:1000 network device (legacy)
- // virtio nics has no ids
- ifname := s.getNetdevOfThePciAddress(qtree, pciAddr)
- index := 0
- for ; index < len(s.Desc.Nics); index++ {
- if s.Desc.Nics[index].Ifname == ifname {
- s.Desc.Nics[index].Pci.PCIAddr = pciAddr
- err = s.ensureDevicePciAddress(s.Desc.Nics[index].Pci, -1, nil)
- if err != nil {
- return errors.Wrapf(err, "ensure nic %s pci address", s.Desc.Nics[index].Ifname)
- }
- break
- }
- }
- if index >= len(s.Desc.Nics) {
- return errors.Errorf("failed find nics ifname")
- }
- default:
- unknownDevices = append(unknownDevices, pciInfoList[0].Devices[i])
- }
- }
- }
- }
- s.initGuestDisks(pciRoot, nil, true)
- for i := 0; i < len(unknownDevices); i++ {
- if unknownDevices[i].Bus == 0 && unknownDevices[i].Slot == 0 {
- continue // host bridge
- }
- pciDev := desc.NewPCIDevice(pciRoot.CType, "", unknownDevices[i].QdevID)
- pciDev.PCIAddr = &desc.PCIAddr{
- Bus: uint(unknownDevices[i].Bus),
- Slot: uint(unknownDevices[i].Slot),
- Function: uint(unknownDevices[i].Function),
- }
- err = s.ensureDevicePciAddress(pciDev, -1, nil)
- if err != nil {
- return errors.Wrap(err, "ensure anonymous pci dev address")
- }
- if s.isMachineDefaultAddress(pciDev.PCIAddr) {
- continue
- }
- if s.Desc.AnonymousPCIDevs == nil {
- s.Desc.AnonymousPCIDevs = make([]*desc.PCIDevice, 0)
- }
- s.Desc.AnonymousPCIDevs = append(s.Desc.AnonymousPCIDevs, pciDev)
- }
- return nil
- }
|