@@ -136,6 +136,7 @@ type bootIso struct {
136
136
// QemuInstance holds an instantiated VM through its lifecycle.
137
137
type QemuInstance struct {
138
138
qemu exec.Cmd
139
+ architecture string
139
140
tempdir string
140
141
swtpm exec.Cmd
141
142
nbdServers []exec.Cmd
@@ -295,7 +296,10 @@ func (inst *QemuInstance) Destroy() {
295
296
// is used to boot from the network device (boot once is not supported). For s390x, the boot ordering was not a problem as it
296
297
// would always read from disk first. For aarch64, the bootindex needs to be switched to boot from disk before a reboot
297
298
func (inst * QemuInstance ) SwitchBootOrder () (err2 error ) {
298
- if coreosarch .CurrentRpmArch () != "s390x" && coreosarch .CurrentRpmArch () != "aarch64" {
299
+ switch inst .architecture {
300
+ case "s390x" , "aarch64" :
301
+ break
302
+ default :
299
303
//Not applicable for other arches
300
304
return nil
301
305
}
@@ -401,6 +405,8 @@ type QemuBuilder struct {
401
405
// File to which to redirect the serial console
402
406
ConsoleFile string
403
407
408
+ // If set, use QEMU full emulation for the target architecture
409
+ architecture string
404
410
// Memory defaults to 1024 on most architectures, others it may be 2048
405
411
Memory int
406
412
// Processors < 0 means to use host count, unset means 1, values > 1 are directly used
@@ -454,10 +460,11 @@ type QemuBuilder struct {
454
460
// NewQemuBuilder creates a new build for QEMU with default settings.
455
461
func NewQemuBuilder () * QemuBuilder {
456
462
ret := QemuBuilder {
457
- Firmware : "bios" ,
458
- Swtpm : true ,
459
- Pdeathsig : true ,
460
- Argv : []string {},
463
+ Firmware : "bios" ,
464
+ Swtpm : true ,
465
+ Pdeathsig : true ,
466
+ Argv : []string {},
467
+ architecture : coreosarch .CurrentRpmArch (),
461
468
}
462
469
return & ret
463
470
}
@@ -526,15 +533,15 @@ func (builder *QemuBuilder) AddFd(fd *os.File) string {
526
533
}
527
534
528
535
// virtio returns a virtio device argument for qemu, which is architecture dependent
529
- func virtio (device , args string ) string {
536
+ func virtio (arch , device , args string ) string {
530
537
var suffix string
531
- switch coreosarch . CurrentRpmArch () {
538
+ switch arch {
532
539
case "x86_64" , "ppc64le" , "aarch64" :
533
540
suffix = "pci"
534
541
case "s390x" :
535
542
suffix = "ccw"
536
543
default :
537
- panic (fmt .Sprintf ("RpmArch %s unhandled in virtio()" , coreosarch . CurrentRpmArch () ))
544
+ panic (fmt .Sprintf ("RpmArch %s unhandled in virtio()" , arch ))
538
545
}
539
546
return fmt .Sprintf ("virtio-%s-%s,%s" , device , suffix , args )
540
547
}
@@ -574,7 +581,7 @@ func (builder *QemuBuilder) setupNetworking() error {
574
581
netdev += ",restrict=on"
575
582
}
576
583
577
- builder .Append ("-netdev" , netdev , "-device" , virtio ("net" , "netdev=eth0" ))
584
+ builder .Append ("-netdev" , netdev , "-device" , virtio (builder . architecture , "net" , "netdev=eth0" ))
578
585
return nil
579
586
}
580
587
@@ -587,14 +594,24 @@ func (builder *QemuBuilder) setupAdditionalNetworking() error {
587
594
macSuffix := fmt .Sprintf ("%02x" , macCounter )
588
595
589
596
netdev := fmt .Sprintf ("user,id=eth%s,dhcpstart=10.0.2.%s" , idSuffix , netSuffix )
590
- device := virtio ("net" , fmt .Sprintf ("netdev=eth%s,mac=52:55:00:d1:56:%s" , idSuffix , macSuffix ))
597
+ device := virtio (builder . architecture , "net" , fmt .Sprintf ("netdev=eth%s,mac=52:55:00:d1:56:%s" , idSuffix , macSuffix ))
591
598
builder .Append ("-netdev" , netdev , "-device" , device )
592
599
macCounter ++
593
600
}
594
601
595
602
return nil
596
603
}
597
604
605
+ // SetArchitecture enables qemu full emulation for the target architecture.
606
+ func (builder * QemuBuilder ) SetArchitecture (arch string ) error {
607
+ switch arch {
608
+ case "x86_64" , "aarch64" , "s390x" , "ppc64le" :
609
+ builder .architecture = arch
610
+ return nil
611
+ }
612
+ return fmt .Errorf ("architecture %s not supported by coreos-assembler qemu" , arch )
613
+ }
614
+
598
615
// Mount9p sets up a mount point from the host to guest. To be replaced
599
616
// with https://virtio-fs.gitlab.io/ once it lands everywhere.
600
617
func (builder * QemuBuilder ) Mount9p (source , destHint string , readonly bool ) {
@@ -604,13 +621,13 @@ func (builder *QemuBuilder) Mount9p(source, destHint string, readonly bool) {
604
621
readonlyStr = ",readonly=on"
605
622
}
606
623
builder .Append ("--fsdev" , fmt .Sprintf ("local,id=fs%d,path=%s,security_model=mapped%s" , builder .fs9pID , source , readonlyStr ))
607
- builder .Append ("-device" , virtio ("9p" , fmt .Sprintf ("fsdev=fs%d,mount_tag=%s" , builder .fs9pID , destHint )))
624
+ builder .Append ("-device" , virtio (builder . architecture , "9p" , fmt .Sprintf ("fsdev=fs%d,mount_tag=%s" , builder .fs9pID , destHint )))
608
625
}
609
626
610
627
// supportsFwCfg if the target system supports injecting
611
628
// Ignition via the qemu -fw_cfg option.
612
629
func (builder * QemuBuilder ) supportsFwCfg () bool {
613
- switch coreosarch . CurrentRpmArch () {
630
+ switch builder . architecture {
614
631
case "s390x" , "ppc64le" :
615
632
return false
616
633
}
@@ -619,7 +636,7 @@ func (builder *QemuBuilder) supportsFwCfg() bool {
619
636
620
637
// supportsSwtpm if the target system supports a virtual TPM device
621
638
func (builder * QemuBuilder ) supportsSwtpm () bool {
622
- switch coreosarch . CurrentRpmArch () {
639
+ switch builder . architecture {
623
640
case "s390x" :
624
641
// s390x does not support a backend for TPM
625
642
return false
@@ -655,7 +672,7 @@ type coreosGuestfish struct {
655
672
remote string
656
673
}
657
674
658
- func newGuestfish (diskImagePath string , diskSectorSize int ) (* coreosGuestfish , error ) {
675
+ func newGuestfish (arch , diskImagePath string , diskSectorSize int ) (* coreosGuestfish , error ) {
659
676
// Set guestfish backend to direct in order to avoid libvirt as backend.
660
677
// Using libvirt can lead to permission denied issues if it does not have access
661
678
// rights to the qcow image
@@ -668,7 +685,7 @@ func newGuestfish(diskImagePath string, diskSectorSize int) (*coreosGuestfish, e
668
685
cmd .Env = append (os .Environ (), "LIBGUESTFS_BACKEND=direct" )
669
686
670
687
// Hack to run with a wrapper on older P8 hardware running RHEL7
671
- switch coreosarch . CurrentRpmArch () {
688
+ switch arch {
672
689
case "ppc64le" :
673
690
u := unix.Utsname {}
674
691
if err := unix .Uname (& u ); err != nil {
@@ -736,8 +753,8 @@ func (gf *coreosGuestfish) destroy() {
736
753
}
737
754
738
755
// setupPreboot performs changes necessary before the disk is booted
739
- func setupPreboot (confPath , firstbootkargs , kargs string , diskImagePath string , diskSectorSize int ) error {
740
- gf , err := newGuestfish (diskImagePath , diskSectorSize )
756
+ func setupPreboot (arch , confPath , firstbootkargs , kargs string , diskImagePath string , diskSectorSize int ) error {
757
+ gf , err := newGuestfish (arch , diskImagePath , diskSectorSize )
741
758
if err != nil {
742
759
return err
743
760
}
@@ -898,7 +915,7 @@ func (builder *QemuBuilder) addDiskImpl(disk *Disk, primary bool) error {
898
915
}
899
916
requiresInjection := builder .ConfigFile != "" && builder .ForceConfigInjection
900
917
if requiresInjection || builder .AppendFirstbootKernelArgs != "" || builder .AppendKernelArgs != "" {
901
- if err := setupPreboot (builder .ConfigFile , builder .AppendFirstbootKernelArgs , builder .AppendKernelArgs ,
918
+ if err := setupPreboot (builder .architecture , builder . ConfigFile , builder .AppendFirstbootKernelArgs , builder .AppendKernelArgs ,
902
919
disk .dstFileName , disk .SectorSize ); err != nil {
903
920
return errors .Wrapf (err , "ignition injection with guestfs failed" )
904
921
}
@@ -952,13 +969,13 @@ func (builder *QemuBuilder) addDiskImpl(disk *Disk, primary bool) error {
952
969
wwn := rand .Uint64 ()
953
970
954
971
var bus string
955
- switch coreosarch . CurrentRpmArch () {
972
+ switch builder . architecture {
956
973
case "x86_64" , "ppc64le" , "aarch64" :
957
974
bus = "pci"
958
975
case "s390x" :
959
976
bus = "ccw"
960
977
default :
961
- panic (fmt .Sprintf ("Mantle doesn't know which bus type to use on %s" , coreosarch . CurrentRpmArch () ))
978
+ panic (fmt .Sprintf ("Mantle doesn't know which bus type to use on %s" , builder . architecture ))
962
979
}
963
980
964
981
for i := 0 ; i < 2 ; i ++ {
@@ -984,7 +1001,7 @@ func (builder *QemuBuilder) addDiskImpl(disk *Disk, primary bool) error {
984
1001
disk .dstFileName = ""
985
1002
switch channel {
986
1003
case "virtio" :
987
- builder .Append ("-device" , virtio ("blk" , fmt .Sprintf ("drive=%s%s" , id , opts )))
1004
+ builder .Append ("-device" , virtio (builder . architecture , "blk" , fmt .Sprintf ("drive=%s%s" , id , opts )))
988
1005
case "nvme" :
989
1006
builder .Append ("-device" , fmt .Sprintf ("nvme,drive=%s%s" , id , opts ))
990
1007
default :
@@ -1067,7 +1084,7 @@ func (builder *QemuBuilder) finalize() {
1067
1084
1068
1085
// Then later, other non-x86_64 seemed to just copy that.
1069
1086
memory := 1024
1070
- switch coreosarch . CurrentRpmArch () {
1087
+ switch builder . architecture {
1071
1088
case "aarch64" , "s390x" , "ppc64le" :
1072
1089
memory = 2048
1073
1090
}
@@ -1083,15 +1100,16 @@ func (builder *QemuBuilder) Append(args ...string) {
1083
1100
1084
1101
// baseQemuArgs takes a board and returns the basic qemu
1085
1102
// arguments needed for the current architecture.
1086
- func baseQemuArgs () []string {
1103
+ func baseQemuArgs (arch string ) ( []string , error ) {
1087
1104
accel := "accel=kvm"
1088
1105
kvm := true
1089
- if _ , ok := os .LookupEnv ("COSA_NO_KVM" ); ok {
1106
+ hostArch := coreosarch .CurrentRpmArch ()
1107
+ if _ , ok := os .LookupEnv ("COSA_NO_KVM" ); ok || hostArch != arch {
1090
1108
accel = "accel=tcg"
1091
1109
kvm = false
1092
1110
}
1093
1111
var ret []string
1094
- switch coreosarch . CurrentRpmArch () {
1112
+ switch arch {
1095
1113
case "x86_64" :
1096
1114
ret = []string {
1097
1115
"qemu-system-x86_64" ,
@@ -1113,19 +1131,19 @@ func baseQemuArgs() []string {
1113
1131
"-machine" , "pseries,kvm-type=HV,vsmt=8,cap-fwnmi=off," + accel ,
1114
1132
}
1115
1133
default :
1116
- panic ( fmt .Sprintf ( "RpmArch %s combo not supported for qemu " , coreosarch . CurrentRpmArch ()) )
1134
+ return nil , fmt .Errorf ( "architecture %s not supported for qemu" , arch )
1117
1135
}
1118
1136
if kvm {
1119
1137
ret = append (ret , "-cpu" , "host" )
1120
1138
} else {
1121
- if coreosarch . CurrentRpmArch () == "x86_64" {
1139
+ if arch == "x86_64" {
1122
1140
// the default qemu64 CPU model does not support x86_64_v2
1123
1141
// causing crashes on EL9+ kernels
1124
1142
// see https://bugzilla.redhat.com/show_bug.cgi?id=2060839
1125
1143
ret = append (ret , "-cpu" , "Nehalem" )
1126
1144
}
1127
1145
}
1128
- return ret
1146
+ return ret , nil
1129
1147
}
1130
1148
1131
1149
func (builder * QemuBuilder ) setupUefi (secureBoot bool ) error {
@@ -1289,7 +1307,7 @@ func (builder *QemuBuilder) setupIso() error {
1289
1307
}
1290
1308
builder .Append ("-drive" , "file=" + builder .iso .path + ",format=raw,if=none,readonly=on,id=installiso" )
1291
1309
if builder .isoAsDisk {
1292
- builder .Append ("-device" , virtio ("blk" , "drive=installiso" + bootindexStr ))
1310
+ builder .Append ("-device" , virtio (builder . architecture , "blk" , "drive=installiso" + bootindexStr ))
1293
1311
} else {
1294
1312
builder .Append ("-device" , "ide-cd,drive=installiso" + bootindexStr )
1295
1313
}
@@ -1378,7 +1396,10 @@ func (builder *QemuBuilder) Exec() (*QemuInstance, error) {
1378
1396
}
1379
1397
}()
1380
1398
1381
- argv := baseQemuArgs ()
1399
+ argv , err := baseQemuArgs (builder .architecture )
1400
+ if err != nil {
1401
+ return nil , err
1402
+ }
1382
1403
argv = append (argv , "-m" , fmt .Sprintf ("%d" , builder .Memory ))
1383
1404
1384
1405
if builder .Processors < 0 {
@@ -1416,7 +1437,7 @@ func (builder *QemuBuilder) Exec() (*QemuInstance, error) {
1416
1437
1417
1438
// We always provide a random source
1418
1439
argv = append (argv , "-object" , "rng-random,filename=/dev/urandom,id=rng0" ,
1419
- "-device" , virtio ("rng" , "rng=rng0" ))
1440
+ "-device" , virtio (builder . architecture , "rng" , "rng=rng0" ))
1420
1441
if builder .UUID != "" {
1421
1442
argv = append (argv , "-uuid" , builder .UUID )
1422
1443
}
@@ -1518,7 +1539,7 @@ func (builder *QemuBuilder) Exec() (*QemuInstance, error) {
1518
1539
}
1519
1540
argv = append (argv , "-chardev" , fmt .Sprintf ("socket,id=chrtpm,path=%s" , swtpmSock ), "-tpmdev" , "emulator,id=tpm0,chardev=chrtpm" )
1520
1541
// There are different device backends on each architecture
1521
- switch coreosarch . CurrentRpmArch () {
1542
+ switch builder . architecture {
1522
1543
case "x86_64" :
1523
1544
argv = append (argv , "-device" , "tpm-tis,tpmdev=tpm0" )
1524
1545
case "aarch64" :
@@ -1560,6 +1581,7 @@ func (builder *QemuBuilder) Exec() (*QemuInstance, error) {
1560
1581
argv = append (argv , builder .Argv ... )
1561
1582
1562
1583
inst .qemu = exec .Command (argv [0 ], argv [1 :]... )
1584
+ inst .architecture = builder .architecture
1563
1585
1564
1586
cmd := inst .qemu .(* exec.ExecCmd )
1565
1587
cmd .Stderr = os .Stderr
0 commit comments