pci.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package guestman
  15. import (
  16. "fmt"
  17. "strconv"
  18. "strings"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/onecloud/pkg/hostman/guestman/desc"
  22. "yunion.io/x/onecloud/pkg/hostman/guestman/qemu"
  23. "yunion.io/x/onecloud/pkg/hostman/monitor"
  24. "yunion.io/x/onecloud/pkg/hostman/options"
  25. "yunion.io/x/onecloud/pkg/scheduler/api"
  26. "yunion.io/x/onecloud/pkg/util/fileutils2"
  27. )
  28. func (s *SKVMGuestInstance) addPCIController(controllerType, bus desc.PCI_CONTROLLER_TYPE) *desc.PCIController {
  29. cont := desc.NewPCIController(controllerType)
  30. cont.PCIDevice = desc.NewPCIDevice(bus, "", "")
  31. if s.Desc.PCIControllers == nil {
  32. s.Desc.PCIControllers = make([]*desc.PCIController, 0)
  33. }
  34. s.Desc.PCIControllers = append(s.Desc.PCIControllers, cont)
  35. return cont
  36. }
  37. func (s *SKVMGuestInstance) pciControllerFind(cont desc.PCI_CONTROLLER_TYPE) *desc.PCIController {
  38. for i := 0; i < len(s.Desc.PCIControllers); i++ {
  39. if s.Desc.PCIControllers[i].CType == cont {
  40. return s.Desc.PCIControllers[i]
  41. }
  42. }
  43. return nil
  44. }
  45. func (s *SKVMGuestInstance) initGuestDesc() error {
  46. err := s.initCpuDesc(0)
  47. if err != nil {
  48. return err
  49. }
  50. err = s.initMemDesc(s.Desc.Mem)
  51. if err != nil {
  52. return errors.Wrap(err, "initMemDesc")
  53. }
  54. s.initMachineDesc()
  55. pciRoot, pciBridge := s.initGuestPciControllers(s.manager.host.IsKvmSupport())
  56. err = s.initGuestPciAddresses()
  57. if err != nil {
  58. return errors.Wrap(err, "init guest pci addresses")
  59. }
  60. err = s.initGuestDevicesDesc(pciRoot, pciBridge)
  61. if err != nil {
  62. return err
  63. }
  64. if err := s.initMachineDefaultAddresses(); err != nil {
  65. return errors.Wrap(err, "init machine default devices")
  66. }
  67. return s.ensurePciAddresses()
  68. }
  69. func (s *SKVMGuestInstance) initGuestDevicesDesc(pciRoot, pciBridge *desc.PCIController) error {
  70. // vdi device for spice
  71. s.Desc.VdiDevice = new(desc.SGuestVdi)
  72. if s.IsVdiSpice() {
  73. s.initSpiceDevices(pciRoot)
  74. }
  75. s.initVirtioSerial(pciRoot)
  76. s.initGuestVga(pciRoot)
  77. s.initCdromDesc()
  78. s.initFloppyDesc()
  79. s.initGuestDisks(pciRoot, pciBridge, false)
  80. if err := s.initGuestNetworks(pciRoot, pciBridge); err != nil {
  81. return errors.Wrap(err, "init guest networks")
  82. }
  83. s.initIsolatedDevices(pciRoot, pciBridge)
  84. s.initUsbController(pciRoot)
  85. s.initRandomDevice(pciRoot, options.HostOptions.EnableVirtioRngDevice)
  86. s.initQgaDesc()
  87. s.initPvpanicDesc()
  88. s.initIsaSerialDesc()
  89. s.initTpmDesc()
  90. return nil
  91. }
  92. func (s *SKVMGuestInstance) loadGuestPciAddresses() error {
  93. err := s.initGuestPciAddresses()
  94. if err != nil {
  95. return errors.Wrap(err, "init guest pci addresses")
  96. }
  97. if err := s.initMachineDefaultAddresses(); err != nil {
  98. return errors.Wrap(err, "init machine default devices")
  99. }
  100. err = s.ensurePciAddresses()
  101. if err != nil {
  102. return errors.Wrap(err, "load desc ensure pci address")
  103. }
  104. if err = SaveLiveDesc(s, s.Desc); err != nil {
  105. return errors.Wrap(err, "loadGuestPciAddresses save desc")
  106. }
  107. return nil
  108. }
  109. func (s *SKVMGuestInstance) initMachineDefaultAddresses() error {
  110. switch s.Desc.Machine {
  111. case "pc":
  112. I440FXSlot1 := &desc.PCIDevice{
  113. PCIAddr: &desc.PCIAddr{Bus: 0, Slot: 1},
  114. Controller: desc.CONTROLLER_TYPE_PCI_ROOT,
  115. }
  116. // ISA bridge
  117. multiFunc := true
  118. if err := s.ensureDevicePciAddress(I440FXSlot1, 0, &multiFunc); err != nil {
  119. return err
  120. }
  121. // primary IDE controller
  122. if err := s.ensureDevicePciAddress(I440FXSlot1, 1, nil); err != nil {
  123. return err
  124. }
  125. // PIIX3 USB controller
  126. if err := s.ensureDevicePciAddress(I440FXSlot1, 2, nil); err != nil {
  127. return err
  128. }
  129. // ACPI (power management) and SMBus controller
  130. if err := s.ensureDevicePciAddress(I440FXSlot1, 3, nil); err != nil {
  131. return err
  132. }
  133. case "q35":
  134. Q35Slot31 := &desc.PCIDevice{
  135. PCIAddr: &desc.PCIAddr{Bus: 0, Slot: 31},
  136. Controller: desc.CONTROLLER_TYPE_PCIE_ROOT,
  137. }
  138. // ISA bridge
  139. multiFunc := true
  140. if err := s.ensureDevicePciAddress(Q35Slot31, 0, &multiFunc); err != nil {
  141. return err
  142. }
  143. // primary SATA controller
  144. if err := s.ensureDevicePciAddress(Q35Slot31, 2, nil); err != nil {
  145. return err
  146. }
  147. // SMBus
  148. if err := s.ensureDevicePciAddress(Q35Slot31, 3, nil); err != nil {
  149. return err
  150. }
  151. // usb controllers
  152. Q35Slot29 := &desc.PCIDevice{
  153. PCIAddr: &desc.PCIAddr{Bus: 0, Slot: 29},
  154. Controller: desc.CONTROLLER_TYPE_PCIE_ROOT,
  155. }
  156. multiFunc = true
  157. if err := s.ensureDevicePciAddress(Q35Slot29, 0, &multiFunc); err != nil {
  158. return err
  159. }
  160. if err := s.ensureDevicePciAddress(Q35Slot29, 1, nil); err != nil {
  161. return err
  162. }
  163. if err := s.ensureDevicePciAddress(Q35Slot29, 2, nil); err != nil {
  164. return err
  165. }
  166. if err := s.ensureDevicePciAddress(Q35Slot29, 7, nil); err != nil {
  167. return err
  168. }
  169. case "virt":
  170. // do nothing
  171. }
  172. return nil
  173. }
  174. func (s *SKVMGuestInstance) isMachineDefaultAddress(pciAddr *desc.PCIAddr) bool {
  175. switch s.Desc.Machine {
  176. case "pc":
  177. if pciAddr.Bus == 0 && pciAddr.Slot == 1 && pciAddr.Function < 4 {
  178. return true
  179. }
  180. case "q35":
  181. if pciAddr.Bus == 0 && pciAddr.Slot == 29 {
  182. switch pciAddr.Function {
  183. case 0, 1, 2, 7:
  184. return true
  185. }
  186. } else if pciAddr.Bus == 0 && pciAddr.Slot == 31 {
  187. switch pciAddr.Function {
  188. case 0, 2, 3:
  189. return true
  190. }
  191. }
  192. }
  193. return false
  194. }
  195. func (s *SKVMGuestInstance) initGuestPciControllers(pciExtend bool) (*desc.PCIController, *desc.PCIController) {
  196. var pciRoot, pciBridge *desc.PCIController
  197. if len(s.Desc.PCIControllers) > 0 {
  198. pciRoot = s.Desc.PCIControllers[0]
  199. if len(s.Desc.PCIControllers) > 1 {
  200. pciBridge = s.Desc.PCIControllers[1]
  201. }
  202. return pciRoot, pciBridge
  203. }
  204. if s.isPcie() {
  205. pciRoot = s.addPCIController(desc.CONTROLLER_TYPE_PCIE_ROOT, "")
  206. if pciExtend {
  207. s.addPCIController(desc.CONTROLLER_TYPE_PCIE_TO_PCI_BRIDGE, desc.CONTROLLER_TYPE_PCIE_ROOT)
  208. pciBridge = s.addPCIController(desc.CONTROLLER_TYPE_PCI_BRIDGE, desc.CONTROLLER_TYPE_PCIE_TO_PCI_BRIDGE)
  209. for i := 0; i < s.vfioDevCount()+options.HostOptions.PcieRootPortCount; i++ {
  210. s.addPCIController(desc.CONTROLLER_TYPE_PCIE_ROOT_PORT, desc.CONTROLLER_TYPE_PCIE_ROOT)
  211. }
  212. }
  213. } else {
  214. pciRoot = s.addPCIController(desc.CONTROLLER_TYPE_PCI_ROOT, "")
  215. }
  216. return pciRoot, pciBridge
  217. }
  218. func (s *SKVMGuestInstance) initGuestPciAddresses() error {
  219. s.pciAddrs = &desc.SGuestPCIAddresses{
  220. Buses: make([]*desc.SGuestPCIAddressBus, len(s.Desc.PCIControllers)),
  221. }
  222. var err error
  223. for i := 0; i < len(s.pciAddrs.Buses); i++ {
  224. s.pciAddrs.Buses[i], err = desc.NewGuestPCIAddressBus(s.Desc.PCIControllers[i].CType)
  225. if err != nil {
  226. return err
  227. }
  228. }
  229. return nil
  230. }
  231. func (s *SKVMGuestInstance) cleanGuestPciAddressed() {
  232. s.pciAddrs = nil
  233. }
  234. func (s *SKVMGuestInstance) initRandomDevice(pciRoot *desc.PCIController, enableVirtioRngDevice bool) {
  235. if !enableVirtioRngDevice {
  236. return
  237. }
  238. var randev string
  239. if fileutils2.Exists("/dev/urandom") {
  240. randev = "/dev/urandom"
  241. } else if fileutils2.Exists("/dev/random") {
  242. randev = "/dev/random"
  243. } else {
  244. return
  245. }
  246. s.Desc.Rng = &desc.SGuestRng{
  247. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-rng-pci", "random0"),
  248. RngRandom: desc.NewObject("rng-random", "rng0"),
  249. }
  250. s.Desc.Rng.Options = map[string]string{
  251. "max-bytes": "1024",
  252. "period": "1000",
  253. }
  254. s.Desc.Rng.RngRandom.Options = map[string]string{
  255. "filename": randev,
  256. }
  257. }
  258. func (s *SKVMGuestInstance) initUsbController(pciRoot *desc.PCIController) {
  259. contType := s.getUsbControllerType()
  260. s.Desc.Usb = &desc.UsbController{
  261. PCIDevice: desc.NewPCIDevice(pciRoot.CType, contType, "usb"),
  262. }
  263. }
  264. func (s *SKVMGuestInstance) initGuestNetworks(pciRoot, pciBridge *desc.PCIController) error {
  265. cont := pciRoot
  266. if pciBridge != nil {
  267. cont = pciBridge
  268. }
  269. if s.GetOsName() == OS_NAME_ANDROID {
  270. s.Desc.Nics = s.Desc.Nics[:1]
  271. }
  272. for i := 0; i < len(s.Desc.Nics); i++ {
  273. if err := s.generateNicScripts(s.Desc.Nics[i]); err != nil {
  274. return errors.Wrapf(err, "generateNicScripts for nic: %v", s.Desc.Nics[i])
  275. }
  276. s.Desc.Nics[i].UpscriptPath = s.getNicUpScriptPath(s.Desc.Nics[i])
  277. s.Desc.Nics[i].DownscriptPath = s.getNicDownScriptPath(s.Desc.Nics[i])
  278. if s.Desc.Nics[i].Driver != "vfio-pci" {
  279. switch s.GetOsName() {
  280. case OS_NAME_MACOS:
  281. vectors := 0
  282. s.Desc.Nics[i].Vectors = &vectors
  283. s.Desc.Nics[i].Driver = "e1000"
  284. case OS_NAME_VMWARE:
  285. s.Desc.Nics[i].Driver = "vmxnet3"
  286. }
  287. if s.Desc.Nics[i].NumQueues > 1 {
  288. vectors := s.Desc.Nics[i].NumQueues*2 + 1
  289. s.Desc.Nics[i].Vectors = &vectors
  290. }
  291. id := fmt.Sprintf("netdev-%s", s.Desc.Nics[i].Ifname)
  292. switch s.Desc.Nics[i].Driver {
  293. case "virtio":
  294. s.Desc.Nics[i].Pci = desc.NewPCIDevice(cont.CType, "virtio-net-pci", id)
  295. case "e1000":
  296. s.Desc.Nics[i].Pci = desc.NewPCIDevice(cont.CType, "e1000-82545em", id)
  297. case "vmxnet3":
  298. s.Desc.Nics[i].Pci = desc.NewPCIDevice(cont.CType, "vmxnet3", id)
  299. case "rtl8139":
  300. s.Desc.Nics[i].Pci = desc.NewPCIDevice(cont.CType, "rtl8139", id)
  301. }
  302. }
  303. }
  304. return nil
  305. }
  306. func (s *SKVMGuestInstance) initIsolatedDevices(pciRoot, pciBridge *desc.PCIController) {
  307. cType := s.getVfioDeviceHotPlugPciControllerType()
  308. if cType == nil {
  309. cType = &pciRoot.CType
  310. if pciBridge != nil {
  311. cType = &pciBridge.CType
  312. }
  313. }
  314. manager := s.manager.GetHost().GetIsolatedDeviceManager()
  315. for i := 0; i < len(s.Desc.IsolatedDevices); i++ {
  316. dev := manager.GetDeviceByAddr(s.Desc.IsolatedDevices[i].Addr)
  317. if s.Desc.IsolatedDevices[i].DevType == api.USB_TYPE {
  318. s.Desc.IsolatedDevices[i].Usb = desc.NewUsbDevice("usb-host", dev.GetQemuId())
  319. s.Desc.IsolatedDevices[i].Usb.Options = dev.GetPassthroughOptions()
  320. } else {
  321. id := dev.GetQemuId()
  322. s.Desc.IsolatedDevices[i].VfioDevs = make([]*desc.VFIODevice, 0)
  323. vfioDev := desc.NewVfioDevice(
  324. *cType, "vfio-pci", id, dev.GetAddr(), s.Desc.IsolatedDevices[i].DevType == api.GPU_VGA_TYPE,
  325. )
  326. s.Desc.IsolatedDevices[i].VfioDevs = append(s.Desc.IsolatedDevices[i].VfioDevs, vfioDev)
  327. groupDevAddrs := dev.GetIOMMUGroupRestAddrs()
  328. for j := 0; j < len(groupDevAddrs); j++ {
  329. gid := fmt.Sprintf("%s-%d", id, j+1)
  330. vfioDev = desc.NewVfioDevice(*cType, "vfio-pci", gid, groupDevAddrs[j], false)
  331. s.Desc.IsolatedDevices[i].VfioDevs = append(
  332. s.Desc.IsolatedDevices[i].VfioDevs, vfioDev,
  333. )
  334. }
  335. }
  336. }
  337. }
  338. func (s *SKVMGuestInstance) initCdromDesc() {
  339. if s.Desc.Cdroms == nil {
  340. s.Desc.Cdroms = make([]*desc.SGuestCdrom, options.HostOptions.CdromCount)
  341. for i := range s.Desc.Cdroms {
  342. s.Desc.Cdroms[i] = new(desc.SGuestCdrom)
  343. s.Desc.Cdroms[i].Ordinal = int64(i)
  344. }
  345. }
  346. for i := range s.Desc.Cdroms {
  347. s.archMan.GenerateCdromDesc(s.GetOsName(), s.Desc.Cdroms[i])
  348. }
  349. }
  350. func (s *SKVMGuestInstance) initFloppyDesc() {
  351. if s.Desc.Machine != "pc" || s.GetOsName() != OS_NAME_WINDOWS {
  352. return
  353. }
  354. if s.Desc.Floppys == nil {
  355. s.Desc.Floppys = make([]*desc.SGuestFloppy, options.HostOptions.FloppyCount)
  356. for i := range s.Desc.Floppys {
  357. s.Desc.Floppys[i] = new(desc.SGuestFloppy)
  358. s.Desc.Floppys[i].Ordinal = int64(i)
  359. }
  360. }
  361. for i := range s.Desc.Floppys {
  362. s.archMan.GenerateFloppyDesc(s.GetOsName(), s.Desc.Floppys[i])
  363. }
  364. }
  365. func (s *SKVMGuestInstance) initGuestDisks(pciRoot, pciBridge *desc.PCIController, loadGuest bool) {
  366. if !loadGuest {
  367. hasVirtioScsi, hasPvScsi, hasSataDisk := s.fixDiskDriver()
  368. if hasVirtioScsi && s.Desc.VirtioScsi == nil {
  369. s.Desc.VirtioScsi = &desc.SGuestVirtioScsi{
  370. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-scsi-pci", "scsi"),
  371. }
  372. } else if hasPvScsi && s.Desc.PvScsi == nil {
  373. s.Desc.PvScsi = &desc.SGuestPvScsi{
  374. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "pvscsi", "scsi"),
  375. }
  376. } else if hasSataDisk {
  377. s.Desc.SataController = &desc.SGuestAhciDevice{
  378. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "ahci", "ahci0"),
  379. }
  380. }
  381. }
  382. cont := pciRoot
  383. if pciBridge != nil {
  384. cont = pciBridge
  385. }
  386. for i := 0; i < len(s.Desc.Disks); i++ {
  387. devType := qemu.GetDiskDeviceModel(s.Desc.Disks[i].Driver)
  388. id := fmt.Sprintf("drive_%d", s.Desc.Disks[i].Index)
  389. if s.Desc.Disks[i].Pci != nil || s.Desc.Disks[i].Scsi != nil {
  390. log.Infof("guest %s disk %v has been init", s.Desc.Uuid, s.Desc.Disks[i].Index)
  391. continue
  392. }
  393. switch s.Desc.Disks[i].Driver {
  394. case DISK_DRIVER_VIRTIO:
  395. if s.Desc.Disks[i].Pci == nil {
  396. s.Desc.Disks[i].Pci = desc.NewPCIDevice(cont.CType, devType, id)
  397. }
  398. case DISK_DRIVER_SCSI:
  399. if s.Desc.VirtioScsi == nil {
  400. s.Desc.VirtioScsi = &desc.SGuestVirtioScsi{
  401. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-scsi-pci", "scsi"),
  402. }
  403. }
  404. s.Desc.Disks[i].Scsi = desc.NewScsiDevice(s.Desc.VirtioScsi.Id, devType, id)
  405. case DISK_DRIVER_PVSCSI:
  406. if s.Desc.PvScsi == nil {
  407. s.Desc.PvScsi = &desc.SGuestPvScsi{
  408. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "pvscsi", "scsi"),
  409. }
  410. }
  411. s.Desc.Disks[i].Scsi = desc.NewScsiDevice(s.Desc.PvScsi.Id, devType, id)
  412. case DISK_DRIVER_IDE:
  413. s.Desc.Disks[i].Ide = desc.NewIdeDevice(devType, id)
  414. case DISK_DRIVER_SATA: // -device ahci,id=ahci pci device
  415. s.Desc.Disks[i].Ide = desc.NewIdeDevice(devType, id)
  416. }
  417. }
  418. }
  419. func (s *SKVMGuestInstance) fixDiskDriver() (bool, bool, bool) {
  420. var virtioScsi, pvScsi, sataDisk = false, false, false
  421. isX86 := s.manager.host.IsX8664()
  422. osname := s.GetOsName()
  423. for i := 0; i < len(s.Desc.Disks); i++ {
  424. if !isX86 && (s.Desc.Disks[i].Driver == DISK_DRIVER_IDE ||
  425. s.Desc.Disks[i].Driver == DISK_DRIVER_SATA) {
  426. s.Desc.Disks[i].Driver = DISK_DRIVER_SCSI
  427. } else if osname == OS_NAME_MACOS {
  428. s.Desc.Disks[i].Driver = DISK_DRIVER_SATA
  429. }
  430. switch s.Desc.Disks[i].Driver {
  431. case DISK_DRIVER_SCSI:
  432. virtioScsi = true
  433. case DISK_DRIVER_PVSCSI:
  434. pvScsi = true
  435. case DISK_DRIVER_SATA:
  436. sataDisk = true
  437. }
  438. }
  439. return virtioScsi, pvScsi, sataDisk
  440. }
  441. func (s *SKVMGuestInstance) initVirtioSerial(pciRoot *desc.PCIController) {
  442. s.Desc.VirtioSerial = new(desc.SGuestVirtioSerial)
  443. s.Desc.VirtioSerial.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "virtio-serial-pci", "virtio-serial0")
  444. }
  445. func (s *SKVMGuestInstance) initGuestVga(pciRoot *desc.PCIController) {
  446. var isNotX86 = !s.manager.host.IsX8664()
  447. if s.gpusHasVga() {
  448. s.Desc.Vga = "none"
  449. } else if isNotX86 {
  450. s.Desc.Vga = "virtio-gpu"
  451. } else if s.Desc.Vga == "" {
  452. s.Desc.Vga = "std"
  453. }
  454. s.Desc.VgaDevice = new(desc.SGuestVga)
  455. var vgaDevName string
  456. var options map[string]string
  457. switch s.Desc.Vga {
  458. case "std":
  459. vgaDevName = "VGA"
  460. case "qxl":
  461. vgaDevName = "qxl-vga"
  462. options = map[string]string{
  463. "ram_size": "141557760",
  464. "vram_size": "141557760",
  465. }
  466. case "cirros":
  467. vgaDevName = "cirrus-vga"
  468. case "vmware":
  469. vgaDevName = "vmware-svga"
  470. case "virtio":
  471. vgaDevName = "virtio-vga"
  472. case "virtio-gpu":
  473. vgaDevName = "virtio-gpu-pci"
  474. options = map[string]string{
  475. "max_outputs": "1",
  476. }
  477. case "", "none":
  478. vgaDevName = "none"
  479. }
  480. if vgaDevName != "none" {
  481. s.Desc.VgaDevice.PCIDevice = desc.NewPCIDevice(pciRoot.CType, vgaDevName, "video0")
  482. s.Desc.VgaDevice.PCIDevice.Options = options
  483. }
  484. }
  485. func (s *SKVMGuestInstance) initSpiceDevices(pciRoot *desc.PCIController) {
  486. spice := new(desc.SSpiceDesc)
  487. spice.IntelHDA = &desc.SoundCard{
  488. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "intel-hda", "sound0"),
  489. Codec: &desc.Codec{
  490. Id: "sound0-codec0",
  491. Type: "hda-duplex",
  492. Cad: 0,
  493. },
  494. }
  495. var ehciId = "usbspice"
  496. spice.UsbRedirct = &desc.UsbRedirctDesc{
  497. EHCI1: desc.NewUsbController("", -1),
  498. UHCI1: desc.NewUsbController(ehciId, 0),
  499. UHCI2: desc.NewUsbController(ehciId, 2),
  500. UHCI3: desc.NewUsbController(ehciId, 4),
  501. }
  502. spice.UsbRedirct.UsbRedirDev1 = &desc.UsbRedir{
  503. Id: "usbredirdev1",
  504. Source: desc.NewCharDev("spicevmc", "usbredirchardev1", "usbredir"),
  505. }
  506. spice.UsbRedirct.UsbRedirDev2 = &desc.UsbRedir{
  507. Id: "usbredirdev2",
  508. Source: desc.NewCharDev("spicevmc", "usbredirchardev2", "usbredir"),
  509. }
  510. spice.UsbRedirct.EHCI1.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "ich9-usb-ehci1", ehciId)
  511. spice.UsbRedirct.UHCI1.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "ich9-usb-uhci1", "uhci1")
  512. spice.UsbRedirct.UHCI2.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "ich9-usb-uhci2", "uhci2")
  513. spice.UsbRedirct.UHCI3.PCIDevice = desc.NewPCIDevice(pciRoot.CType, "ich9-usb-uhci3", "uhci3")
  514. spice.VdagentSerial = &desc.SGuestVirtioSerial{
  515. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-serial-pci", "vdagent-serial0"),
  516. }
  517. spice.Vdagent = desc.NewCharDev("spicevmc", "vdagent", "vdagent")
  518. spice.VdagentSerialPort = &desc.VirtSerialPort{
  519. Chardev: "vdagent",
  520. Name: "com.redhat.spice.0",
  521. Options: map[string]string{
  522. "nr": "1",
  523. },
  524. }
  525. spice.Options = map[string]string{
  526. "disable-ticketing": "off",
  527. "seamless-migration": "on",
  528. }
  529. s.Desc.VdiDevice.Spice = spice
  530. }
  531. func (s *SKVMGuestInstance) ensureDevicePciAddress(
  532. dev *desc.PCIDevice, function int, multiFunc *bool,
  533. ) error {
  534. if function >= 8 {
  535. return errors.Errorf("invalid function %x", function)
  536. } else if function < 0 {
  537. // if function not given, give them default function 0
  538. if dev.PCIAddr != nil {
  539. function = int(dev.Function)
  540. } else {
  541. function = 0
  542. }
  543. }
  544. if dev.PCIAddr != nil {
  545. dev.Function = uint(function)
  546. return s.pciAddrs.Buses[dev.Bus].EnsureSlotFunction(dev.Slot, dev.Function)
  547. }
  548. bus, slot, found := s.findUnusedSlotForController(dev.Controller, function)
  549. if !found {
  550. return errors.Errorf("no valid pci address found ?")
  551. }
  552. s.pciAddrs.Buses[bus].EnsureSlotFunction(uint(slot), uint(function))
  553. dev.PCIAddr = &desc.PCIAddr{
  554. Bus: uint(bus),
  555. Slot: uint(slot),
  556. Function: uint(function),
  557. Multi: multiFunc,
  558. }
  559. return nil
  560. }
  561. func (s *SKVMGuestInstance) findUnusedSlotForController(cont desc.PCI_CONTROLLER_TYPE, function int) (int, int, bool) {
  562. var (
  563. bus, slot = 0, 0
  564. found = false
  565. )
  566. for ; bus < len(s.pciAddrs.Buses); bus++ {
  567. if cont == s.pciAddrs.Buses[bus].Contorller {
  568. slot = s.pciAddrs.Buses[bus].FindNextUnusedSlot(uint(function))
  569. if slot >= 0 {
  570. found = true
  571. break
  572. }
  573. }
  574. }
  575. return bus, slot, found
  576. }
  577. func (s *SKVMGuestInstance) ensurePciAddresses() error {
  578. var err error
  579. if s.Desc.VgaDevice != nil && s.Desc.VgaDevice.PCIDevice != nil {
  580. err = s.ensureDevicePciAddress(s.Desc.VgaDevice.PCIDevice, -1, nil)
  581. if err != nil {
  582. return errors.Wrap(err, "ensure vga pci address")
  583. }
  584. }
  585. if s.Desc.VirtioSerial != nil {
  586. err = s.ensureDevicePciAddress(s.Desc.VirtioSerial.PCIDevice, -1, nil)
  587. }
  588. if s.Desc.VdiDevice != nil && s.Desc.VdiDevice.Spice != nil {
  589. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.IntelHDA.PCIDevice, -1, nil)
  590. if err != nil {
  591. return errors.Wrap(err, "ensure vdi hda pci address")
  592. }
  593. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.VdagentSerial.PCIDevice, -1, nil)
  594. if err != nil {
  595. return errors.Wrap(err, "ensure vdagent serial pci address")
  596. }
  597. multiFunc := true
  598. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIDevice, 0, &multiFunc)
  599. if err != nil {
  600. return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
  601. }
  602. s.Desc.VdiDevice.Spice.UsbRedirct.UHCI2.PCIAddr = s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIAddr.Copy()
  603. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI2.PCIDevice, 1, &multiFunc)
  604. if err != nil {
  605. return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
  606. }
  607. s.Desc.VdiDevice.Spice.UsbRedirct.UHCI3.PCIAddr = s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIAddr.Copy()
  608. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI3.PCIDevice, 2, &multiFunc)
  609. if err != nil {
  610. return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
  611. }
  612. s.Desc.VdiDevice.Spice.UsbRedirct.EHCI1.PCIAddr = s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIAddr.Copy()
  613. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.EHCI1.PCIDevice, 7, &multiFunc)
  614. if err != nil {
  615. return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
  616. }
  617. }
  618. if s.Desc.VirtioScsi != nil {
  619. err = s.ensureDevicePciAddress(s.Desc.VirtioScsi.PCIDevice, -1, nil)
  620. if err != nil {
  621. return errors.Wrap(err, "ensure virtio scsi pci address")
  622. }
  623. } else if s.Desc.PvScsi != nil {
  624. err = s.ensureDevicePciAddress(s.Desc.PvScsi.PCIDevice, -1, nil)
  625. if err != nil {
  626. return errors.Wrap(err, "ensure pvscsi pci address")
  627. }
  628. }
  629. if s.Desc.SataController != nil {
  630. err = s.ensureDevicePciAddress(s.Desc.SataController.PCIDevice, -1, nil)
  631. if err != nil {
  632. return errors.Wrap(err, "ensure SataController pci address")
  633. }
  634. }
  635. // skip pci root or pcie root
  636. for i := 1; i < len(s.Desc.PCIControllers); i++ {
  637. err = s.ensureDevicePciAddress(s.Desc.PCIControllers[i].PCIDevice, -1, nil)
  638. if err != nil {
  639. return errors.Wrap(err, "ensure pci controllers address")
  640. }
  641. }
  642. for i := 0; i < len(s.Desc.Disks); i++ {
  643. if s.Desc.Disks[i].Pci != nil {
  644. err = s.ensureDevicePciAddress(s.Desc.Disks[i].Pci, -1, nil)
  645. if err != nil {
  646. return errors.Wrapf(err, "ensure disk %d pci address", s.Desc.Disks[i].Index)
  647. }
  648. }
  649. }
  650. for i := 0; i < len(s.Desc.Nics); i++ {
  651. if s.Desc.Nics[i].Pci != nil {
  652. err = s.ensureDevicePciAddress(s.Desc.Nics[i].Pci, -1, nil)
  653. if err != nil {
  654. return errors.Wrapf(err, "ensure nic %s pci address", s.Desc.Nics[i].Ifname)
  655. }
  656. }
  657. }
  658. for i := 0; i < len(s.Desc.IsolatedDevices); i++ {
  659. if len(s.Desc.IsolatedDevices[i].VfioDevs) > 0 {
  660. multiFunc := len(s.Desc.IsolatedDevices[i].VfioDevs) > 1
  661. err = s.ensureDevicePciAddress(s.Desc.IsolatedDevices[i].VfioDevs[0].PCIDevice, 0, &multiFunc)
  662. if err != nil {
  663. return errors.Wrapf(err, "ensure isolated device %s pci address", s.Desc.IsolatedDevices[i].VfioDevs[0].PCIAddr)
  664. }
  665. for j := 1; j < len(s.Desc.IsolatedDevices[i].VfioDevs); j++ {
  666. s.Desc.IsolatedDevices[i].VfioDevs[j].PCIAddr = s.Desc.IsolatedDevices[i].VfioDevs[0].PCIAddr.Copy()
  667. err = s.ensureDevicePciAddress(s.Desc.IsolatedDevices[i].VfioDevs[j].PCIDevice, j, nil)
  668. if err != nil {
  669. return errors.Wrapf(err, "ensure isolated device %s pci address", s.Desc.IsolatedDevices[i].VfioDevs[j].PCIAddr)
  670. }
  671. }
  672. }
  673. }
  674. if s.Desc.Usb != nil {
  675. err = s.ensureDevicePciAddress(s.Desc.Usb.PCIDevice, -1, nil)
  676. if err != nil {
  677. return errors.Wrap(err, "ensure usb controller pci address")
  678. }
  679. }
  680. if s.Desc.Rng != nil {
  681. err = s.ensureDevicePciAddress(s.Desc.Rng.PCIDevice, -1, nil)
  682. if err != nil {
  683. return errors.Wrap(err, "ensure random device pci address")
  684. }
  685. }
  686. anonymousPCIDevs := s.Desc.AnonymousPCIDevs[:0]
  687. for i := 0; i < len(s.Desc.AnonymousPCIDevs); i++ {
  688. if s.isMachineDefaultAddress(s.Desc.AnonymousPCIDevs[i].PCIAddr) {
  689. if _, inUse := s.pciAddrs.IsAddrInUse(s.Desc.AnonymousPCIDevs[i].PCIAddr); inUse {
  690. log.Infof("guest %s anonymous dev addr %s in use", s.GetName(), s.Desc.AnonymousPCIDevs[i].String())
  691. continue
  692. }
  693. }
  694. err = s.ensureDevicePciAddress(s.Desc.AnonymousPCIDevs[i], -1, nil)
  695. if err != nil {
  696. return errors.Wrap(err, "ensure anonymous pci dev pci address")
  697. }
  698. anonymousPCIDevs = append(anonymousPCIDevs, s.Desc.AnonymousPCIDevs[i])
  699. }
  700. if len(anonymousPCIDevs) == 0 {
  701. anonymousPCIDevs = nil
  702. }
  703. s.Desc.AnonymousPCIDevs = anonymousPCIDevs
  704. return nil
  705. }
  706. func (s *SKVMGuestInstance) getNetdevOfThePciAddress(qtree string, addr *desc.PCIAddr) string {
  707. var slotFunc = fmt.Sprintf("addr = %02x.%x", addr.Slot, addr.Function)
  708. var addressFound = false
  709. var lines = strings.Split(strings.TrimSuffix(qtree, "\r\n"), "\\r\\n")
  710. var currentIndentLevel = -1
  711. for _, line := range lines {
  712. trimmedLine := strings.TrimSpace(line)
  713. if trimmedLine == "" {
  714. continue
  715. }
  716. if currentIndentLevel > 0 {
  717. newIndentLevel := len(line) - len(trimmedLine)
  718. if newIndentLevel <= currentIndentLevel {
  719. if addressFound {
  720. break
  721. }
  722. currentIndentLevel = -1
  723. continue
  724. }
  725. if strings.HasPrefix(trimmedLine, slotFunc) {
  726. addressFound = true
  727. continue
  728. }
  729. if strings.HasPrefix(trimmedLine, "netdev =") {
  730. segs := strings.Split(trimmedLine, " ")
  731. netdev := strings.Trim(segs[2], `\\"`)
  732. log.Infof("found netdev %s: %s", netdev, trimmedLine)
  733. return netdev
  734. } else {
  735. continue
  736. }
  737. }
  738. if strings.HasPrefix(trimmedLine, "dev: virtio-net-pci") {
  739. currentIndentLevel = len(line) - len(trimmedLine)
  740. } else {
  741. continue
  742. }
  743. }
  744. return ""
  745. }
  746. // guests description no pci description before host-agent assign pci device address info
  747. // in this case wo need query pci address info by `query-pci` command. Also memory devices.
  748. func (s *SKVMGuestInstance) initGuestDescFromExistingGuest(
  749. cpuList []monitor.HotpluggableCPU, pciInfoList []monitor.PCIInfo,
  750. memoryDevicesInfoList []monitor.MemoryDeviceInfo, memDevs []monitor.Memdev,
  751. scsiNumQueues int64, qtree string,
  752. ) error {
  753. if len(pciInfoList) > 1 {
  754. return errors.Errorf("unsupported pci info list with multi bus")
  755. }
  756. unknownDevices := make([]monitor.PCIDeviceInfo, 0)
  757. err := s.initCpuDesc(uint(len(cpuList)))
  758. if err != nil {
  759. return err
  760. }
  761. err = s.initMemDescFromMemoryInfo(memoryDevicesInfoList, memDevs)
  762. if err != nil {
  763. return errors.Wrap(err, "init guest memory devices")
  764. }
  765. s.initMachineDesc()
  766. if s.manager.host.IsX8664() && !s.hasHpet(qtree) {
  767. noHpet := true
  768. s.Desc.NoHpet = &noHpet
  769. }
  770. // This code is designed to ensure compatibility with older guests.
  771. // However, it is not recommended for new guests to generate a desc file from it
  772. pciRoot, _ := s.initGuestPciControllers(false)
  773. err = s.initGuestPciAddresses()
  774. if err != nil {
  775. return errors.Wrap(err, "init guest pci addresses")
  776. }
  777. if err := s.initGuestNetworks(pciRoot, nil); err != nil {
  778. return errors.Wrap(err, "init guest networks")
  779. }
  780. //s.initIsolatedDevices(pciRoot, nil)
  781. s.initQgaDesc()
  782. s.initPvpanicDesc()
  783. s.initIsaSerialDesc()
  784. s.Desc.VdiDevice = new(desc.SGuestVdi)
  785. for i := 0; i < len(pciInfoList[0].Devices); i++ {
  786. pciAddr := &desc.PCIAddr{
  787. Bus: uint(pciInfoList[0].Devices[i].Bus),
  788. Slot: uint(pciInfoList[0].Devices[i].Slot),
  789. Function: uint(pciInfoList[0].Devices[i].Function),
  790. }
  791. switch pciInfoList[0].Devices[i].QdevID {
  792. case "scsi":
  793. _, hasPvScsi, _ := s.fixDiskDriver()
  794. if hasPvScsi && s.Desc.PvScsi == nil {
  795. s.Desc.PvScsi = &desc.SGuestPvScsi{
  796. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "pvscsi", "scsi"),
  797. }
  798. } else if s.Desc.VirtioScsi == nil {
  799. s.Desc.VirtioScsi = &desc.SGuestVirtioScsi{
  800. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "virtio-scsi-pci", "scsi"),
  801. }
  802. }
  803. if s.Desc.VirtioScsi != nil {
  804. s.Desc.VirtioScsi.PCIAddr = pciAddr
  805. err = s.ensureDevicePciAddress(s.Desc.VirtioScsi.PCIDevice, -1, nil)
  806. if err != nil {
  807. return errors.Wrap(err, "ensure virtio scsi pci address")
  808. }
  809. if scsiNumQueues > 1 {
  810. numQueues := uint8(scsiNumQueues)
  811. s.Desc.VirtioScsi.NumQueues = &numQueues
  812. }
  813. } else if s.Desc.PvScsi != nil {
  814. s.Desc.PvScsi.PCIAddr = pciAddr
  815. err = s.ensureDevicePciAddress(s.Desc.PvScsi.PCIDevice, -1, nil)
  816. if err != nil {
  817. return errors.Wrap(err, "ensure pvscsi pci address")
  818. }
  819. }
  820. case "video0", "video1":
  821. if s.Desc.VgaDevice == nil {
  822. s.initGuestVga(pciRoot)
  823. }
  824. s.Desc.VgaDevice.PCIAddr = pciAddr
  825. err = s.ensureDevicePciAddress(s.Desc.VgaDevice.PCIDevice, -1, nil)
  826. if err != nil {
  827. return errors.Wrap(err, "ensure vga pci address")
  828. }
  829. case "random0":
  830. if s.Desc.Rng == nil {
  831. // in case rng device disable by host options
  832. s.initRandomDevice(pciRoot, true)
  833. }
  834. s.Desc.Rng.PCIAddr = pciAddr
  835. err = s.ensureDevicePciAddress(s.Desc.Rng.PCIDevice, -1, nil)
  836. if err != nil {
  837. return errors.Wrap(err, "ensure random device pci address")
  838. }
  839. case "usb":
  840. if s.Desc.Usb == nil {
  841. s.initUsbController(pciRoot)
  842. }
  843. s.Desc.Usb.PCIAddr = pciAddr
  844. err = s.ensureDevicePciAddress(s.Desc.Usb.PCIDevice, -1, nil)
  845. if err != nil {
  846. return errors.Wrap(err, "ensure usb controller pci address")
  847. }
  848. case "sound0":
  849. if s.Desc.VdiDevice.Spice == nil {
  850. s.Desc.Vdi = "spice"
  851. s.initSpiceDevices(pciRoot)
  852. }
  853. s.Desc.VdiDevice.Spice.IntelHDA.PCIAddr = pciAddr
  854. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.IntelHDA.PCIDevice, -1, nil)
  855. if err != nil {
  856. return errors.Wrap(err, "ensure vdi hda pci address")
  857. }
  858. case "vdagent-serial0":
  859. if s.Desc.VdiDevice.Spice == nil {
  860. s.Desc.Vdi = "spice"
  861. s.initSpiceDevices(pciRoot)
  862. }
  863. s.Desc.VdiDevice.Spice.VdagentSerial.PCIAddr = pciAddr
  864. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.VdagentSerial.PCIDevice, -1, nil)
  865. if err != nil {
  866. return errors.Wrap(err, "ensure vdagent serial pci address")
  867. }
  868. case "virtio-serial0":
  869. if s.Desc.VirtioSerial == nil {
  870. s.initVirtioSerial(pciRoot)
  871. }
  872. s.Desc.VirtioSerial.PCIAddr = pciAddr
  873. err = s.ensureDevicePciAddress(s.Desc.VirtioSerial.PCIDevice, -1, nil)
  874. if err != nil {
  875. return errors.Wrap(err, "ensure virtio serial address")
  876. }
  877. case "usbspice":
  878. if s.Desc.VdiDevice.Spice == nil {
  879. s.Desc.Vdi = "spice"
  880. s.initSpiceDevices(pciRoot)
  881. }
  882. s.Desc.VdiDevice.Spice.UsbRedirct.EHCI1.PCIAddr = pciAddr
  883. multiFunc := true
  884. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.EHCI1.PCIDevice, -1, &multiFunc)
  885. if err != nil {
  886. return errors.Wrap(err, "ensure vdi usb ehci1 pci address")
  887. }
  888. case "uhci1":
  889. if s.Desc.VdiDevice.Spice == nil {
  890. s.Desc.Vdi = "spice"
  891. s.initSpiceDevices(pciRoot)
  892. }
  893. multiFunc := true
  894. s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIAddr = pciAddr
  895. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI1.PCIDevice, -1, &multiFunc)
  896. if err != nil {
  897. return errors.Wrap(err, "ensure vdi usb uhci1 pci address")
  898. }
  899. case "uhci2":
  900. if s.Desc.VdiDevice.Spice == nil {
  901. s.Desc.Vdi = "spice"
  902. s.initSpiceDevices(pciRoot)
  903. }
  904. multiFunc := true
  905. s.Desc.VdiDevice.Spice.UsbRedirct.UHCI2.PCIAddr = pciAddr
  906. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI2.PCIDevice, -1, &multiFunc)
  907. if err != nil {
  908. return errors.Wrap(err, "ensure vdi usb uhci2 pci address")
  909. }
  910. case "uhci3":
  911. if s.Desc.VdiDevice.Spice == nil {
  912. s.Desc.Vdi = "spice"
  913. s.initSpiceDevices(pciRoot)
  914. }
  915. multiFunc := true
  916. s.Desc.VdiDevice.Spice.UsbRedirct.UHCI3.PCIAddr = pciAddr
  917. err = s.ensureDevicePciAddress(s.Desc.VdiDevice.Spice.UsbRedirct.UHCI3.PCIDevice, -1, &multiFunc)
  918. if err != nil {
  919. return errors.Wrap(err, "ensure vdi usb uhci3 pci address")
  920. }
  921. case "ahci0":
  922. if s.Desc.SataController == nil {
  923. s.Desc.SataController = &desc.SGuestAhciDevice{
  924. PCIDevice: desc.NewPCIDevice(pciRoot.CType, "ahci", "ahci0"),
  925. }
  926. }
  927. s.Desc.SataController.PCIAddr = pciAddr
  928. err = s.ensureDevicePciAddress(s.Desc.SataController.PCIDevice, -1, nil)
  929. if err != nil {
  930. return errors.Wrap(err, "ensure SataController pci address")
  931. }
  932. default:
  933. switch {
  934. case strings.HasPrefix(pciInfoList[0].Devices[i].QdevID, "drive_"):
  935. indexStr := strings.TrimPrefix(pciInfoList[0].Devices[i].QdevID, "drive_")
  936. index, err := strconv.Atoi(indexStr)
  937. if err != nil {
  938. log.Errorf("failed parse disk pci id %s", pciInfoList[0].Devices[i].QdevID)
  939. unknownDevices = append(unknownDevices, pciInfoList[0].Devices[i])
  940. continue
  941. }
  942. for i := 0; i < len(s.Desc.Disks); i++ {
  943. if s.Desc.Disks[i].Index == int8(index) {
  944. if s.Desc.Disks[i].Pci == nil {
  945. devType := qemu.GetDiskDeviceModel(DISK_DRIVER_VIRTIO)
  946. s.Desc.Disks[i].Pci = desc.NewPCIDevice(pciRoot.CType, devType, pciInfoList[0].Devices[i].QdevID)
  947. s.Desc.Disks[i].Scsi = nil
  948. s.Desc.Disks[i].Ide = nil
  949. s.Desc.Disks[i].Driver = DISK_DRIVER_VIRTIO
  950. }
  951. s.Desc.Disks[i].Pci.PCIAddr = pciAddr
  952. err = s.ensureDevicePciAddress(s.Desc.Disks[i].Pci, -1, nil)
  953. if err != nil {
  954. return errors.Wrapf(err, "ensure disk %d pci address", s.Desc.Disks[i].Index)
  955. }
  956. }
  957. }
  958. case strings.HasPrefix(pciInfoList[0].Devices[i].QdevID, "netdev-"):
  959. ifname := strings.TrimPrefix(pciInfoList[0].Devices[i].QdevID, "netdev-")
  960. for i := 0; i < len(s.Desc.Nics); i++ {
  961. if s.Desc.Nics[i].Ifname == ifname {
  962. s.Desc.Nics[i].Pci.PCIAddr = pciAddr
  963. err = s.ensureDevicePciAddress(s.Desc.Nics[i].Pci, -1, nil)
  964. if err != nil {
  965. return errors.Wrapf(err, "ensure nic %s pci address", s.Desc.Nics[i].Ifname)
  966. }
  967. }
  968. }
  969. default:
  970. class := pciInfoList[0].Devices[i].ClassInfo.Class
  971. vendor := pciInfoList[0].Devices[i].ID.Vendor
  972. device := pciInfoList[0].Devices[i].ID.Device
  973. switch { // qemu: docs/specs/pci-ids.txt
  974. case class == 3075 && vendor == 6966 && device == 13: // { 0x0c03, "USB controller", "usb"}, 1b36:000d PCI xhci usb host adapter
  975. if s.Desc.Usb == nil {
  976. s.initUsbController(pciRoot)
  977. }
  978. s.Desc.Usb.PCIAddr = pciAddr
  979. err = s.ensureDevicePciAddress(s.Desc.Usb.PCIDevice, -1, nil)
  980. if err != nil {
  981. return errors.Wrap(err, "ensure usb controller pci address")
  982. }
  983. case class == 255 && vendor == 6900 && device == 4101: // 0x00ff, 1af4:1005 entropy generator device (legacy)
  984. if s.Desc.Rng == nil {
  985. // in case rng device disable by host options
  986. s.initRandomDevice(pciRoot, true)
  987. }
  988. s.Desc.Rng.PCIAddr = pciAddr
  989. err = s.ensureDevicePciAddress(s.Desc.Rng.PCIDevice, -1, nil)
  990. if err != nil {
  991. return errors.Wrap(err, "ensure random device pci address")
  992. }
  993. case class == 1920 && vendor == 6900 && device == 4099: // 0x0780, 1af4:1003 console device (legacy)
  994. if s.Desc.VirtioSerial == nil {
  995. s.initVirtioSerial(pciRoot)
  996. }
  997. s.Desc.VirtioSerial.PCIAddr = pciAddr
  998. err = s.ensureDevicePciAddress(s.Desc.VirtioSerial.PCIDevice, -1, nil)
  999. if err != nil {
  1000. return errors.Wrap(err, "ensure virtio serial address")
  1001. }
  1002. case class == 768 && vendor == 4660 && device == 4369: // { 0x0300, "VGA controller", "display", 0x00ff}, PCI ID: 1234:1111
  1003. if s.Desc.VgaDevice == nil {
  1004. s.initGuestVga(pciRoot)
  1005. }
  1006. s.Desc.VgaDevice.PCIAddr = pciAddr
  1007. err = s.ensureDevicePciAddress(s.Desc.VgaDevice.PCIDevice, -1, nil)
  1008. if err != nil {
  1009. return errors.Wrap(err, "ensure vga pci address")
  1010. }
  1011. case class == 512 && vendor == 6900 && device == 4096: // { 0x0200, "Ethernet controller", "ethernet"}, 1af4:1000 network device (legacy)
  1012. // virtio nics has no ids
  1013. ifname := s.getNetdevOfThePciAddress(qtree, pciAddr)
  1014. index := 0
  1015. for ; index < len(s.Desc.Nics); index++ {
  1016. if s.Desc.Nics[index].Ifname == ifname {
  1017. s.Desc.Nics[index].Pci.PCIAddr = pciAddr
  1018. err = s.ensureDevicePciAddress(s.Desc.Nics[index].Pci, -1, nil)
  1019. if err != nil {
  1020. return errors.Wrapf(err, "ensure nic %s pci address", s.Desc.Nics[index].Ifname)
  1021. }
  1022. break
  1023. }
  1024. }
  1025. if index >= len(s.Desc.Nics) {
  1026. return errors.Errorf("failed find nics ifname")
  1027. }
  1028. default:
  1029. unknownDevices = append(unknownDevices, pciInfoList[0].Devices[i])
  1030. }
  1031. }
  1032. }
  1033. }
  1034. s.initGuestDisks(pciRoot, nil, true)
  1035. for i := 0; i < len(unknownDevices); i++ {
  1036. if unknownDevices[i].Bus == 0 && unknownDevices[i].Slot == 0 {
  1037. continue // host bridge
  1038. }
  1039. pciDev := desc.NewPCIDevice(pciRoot.CType, "", unknownDevices[i].QdevID)
  1040. pciDev.PCIAddr = &desc.PCIAddr{
  1041. Bus: uint(unknownDevices[i].Bus),
  1042. Slot: uint(unknownDevices[i].Slot),
  1043. Function: uint(unknownDevices[i].Function),
  1044. }
  1045. err = s.ensureDevicePciAddress(pciDev, -1, nil)
  1046. if err != nil {
  1047. return errors.Wrap(err, "ensure anonymous pci dev address")
  1048. }
  1049. if s.isMachineDefaultAddress(pciDev.PCIAddr) {
  1050. continue
  1051. }
  1052. if s.Desc.AnonymousPCIDevs == nil {
  1053. s.Desc.AnonymousPCIDevs = make([]*desc.PCIDevice, 0)
  1054. }
  1055. s.Desc.AnonymousPCIDevs = append(s.Desc.AnonymousPCIDevs, pciDev)
  1056. }
  1057. return nil
  1058. }