[lxc-devel] [lxd/master] Add ppc64le support
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Jan 30 04:20:17 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200129/c25450cd/attachment.bin>
-------------- next part --------------
From ed4e666d3c439551f3e890b7000c10865305ea34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 29 Jan 2020 22:59:11 -0500
Subject: [PATCH 1/3] lxd/vm: Record architecture name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/instance/drivers/driver_qemu.go | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index 556b1bc32a..82e541270f 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -103,6 +103,12 @@ func qemuInstantiate(s *state.State, args db.InstanceArgs, expandedDevices devic
expiryDate: args.ExpiryDate,
}
+ // Get the architecture name.
+ archName, err := osarch.ArchitectureName(vm.architecture)
+ if err == nil {
+ vm.architectureName = archName
+ }
+
// Cleanup the zero values.
if vm.expiryDate.IsZero() {
vm.expiryDate = time.Time{}
@@ -147,6 +153,12 @@ func qemuCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error)
expiryDate: args.ExpiryDate,
}
+ // Get the architecture name.
+ archName, err := osarch.ArchitectureName(vm.architecture)
+ if err == nil {
+ vm.architectureName = archName
+ }
+
// Cleanup the zero values.
if vm.expiryDate.IsZero() {
vm.expiryDate = time.Time{}
@@ -178,7 +190,7 @@ func qemuCreate(s *state.State, args db.InstanceArgs) (instance.Instance, error)
}()
// Load the config.
- err := vm.init()
+ err = vm.init()
if err != nil {
logger.Error("Failed creating instance", ctxMap)
return nil, err
@@ -288,8 +300,9 @@ type qemu struct {
// Cached handles.
// Do not use these variables directly, instead use their associated get functions so they
// will be initialised on demand.
- agentClient *http.Client
- storagePool storagePools.Pool
+ agentClient *http.Client
+ storagePool storagePools.Pool
+ architectureName string
}
// getAgentClient returns the current agent client handle. To avoid TLS setup each time this
@@ -2953,9 +2966,6 @@ func (vm *qemu) Exec(req api.InstanceExecPost, stdin *os.File, stdout *os.File,
// Render returns info about the instance.
func (vm *qemu) Render() (interface{}, interface{}, error) {
- // Ignore err as the arch string on error is correct (unknown)
- architectureName, _ := osarch.ArchitectureName(vm.architecture)
-
if vm.IsSnapshot() {
// Prepare the ETag
etag := []interface{}{vm.expiryDate}
@@ -2968,7 +2978,7 @@ func (vm *qemu) Render() (interface{}, interface{}, error) {
Name: strings.SplitN(vm.name, "/", 2)[1],
Stateful: vm.stateful,
}
- vmSnap.Architecture = architectureName
+ vmSnap.Architecture = vm.architectureName
vmSnap.Config = vm.localConfig
vmSnap.Devices = vm.localDevices.CloneNative()
vmSnap.Ephemeral = vm.ephemeral
@@ -2992,7 +3002,7 @@ func (vm *qemu) Render() (interface{}, interface{}, error) {
}
vmState.Description = vm.description
- vmState.Architecture = architectureName
+ vmState.Architecture = vm.architectureName
vmState.Config = vm.localConfig
vmState.CreatedAt = vm.creationDate
vmState.Devices = vm.localDevices.CloneNative()
From 4795633df6d1c5cb241c163373065de8c77fbcf0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 29 Jan 2020 22:59:37 -0500
Subject: [PATCH 2/3] lxd/vm: Cleanup qemu config
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/instance/drivers/driver_qemu_templates.go | 3 ---
1 file changed, 3 deletions(-)
diff --git a/lxd/instance/drivers/driver_qemu_templates.go b/lxd/instance/drivers/driver_qemu_templates.go
index a557dc127a..13c2ac6033 100644
--- a/lxd/instance/drivers/driver_qemu_templates.go
+++ b/lxd/instance/drivers/driver_qemu_templates.go
@@ -107,9 +107,6 @@ var qemuCPU = template.Must(template.New("qemuCPU").Parse(`
# CPU
[smp-opts]
cpus = "{{.cpuCount}}"
-#sockets = "1"
-#cores = "1"
-#threads = "1"
`))
var qemuControlSocket = template.Must(template.New("qemuControlSocket").Parse(`
From 89252be528a0a30925b512fe4a716f33118fa494 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 29 Jan 2020 23:02:01 -0500
Subject: [PATCH 3/3] lxd/vm: Add ppc64el support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/instance/drivers/driver_qemu.go | 72 ++++++++++---------
lxd/instance/drivers/driver_qemu_templates.go | 60 +++++++++++++++-
2 files changed, 97 insertions(+), 35 deletions(-)
diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index 82e541270f..e956abf108 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -680,8 +680,8 @@ func (vm *qemu) Start(stateful bool) error {
devConfs = append(devConfs, runConf)
}
- // Get qemu configuration
- qemuBinary, qemuType, qemuConfig, err := vm.qemuArchConfig()
+ // Get qemu configuration.
+ qemuBinary, err := vm.qemuArchConfig()
if err != nil {
op.Done(err)
return err
@@ -690,7 +690,7 @@ func (vm *qemu) Start(stateful bool) error {
// Define a set of files to open and pass their file descriptors to qemu command.
fdFiles := make([]string, 0)
- confFile, err := vm.generateQemuConfigFile(qemuType, qemuConfig, devConfs, &fdFiles)
+ confFile, err := vm.generateQemuConfigFile(devConfs, &fdFiles)
if err != nil {
op.Done(err)
return err
@@ -863,6 +863,11 @@ func (vm *qemu) Start(stateful bool) error {
}
func (vm *qemu) setupNvram() error {
+ // No UEFI nvram for ppc64le.
+ if vm.architecture == osarch.ARCH_64BIT_POWERPC_LITTLE_ENDIAN {
+ return nil
+ }
+
// Mount the instance's config volume.
ourMount, err := vm.mount()
if err != nil {
@@ -891,25 +896,16 @@ func (vm *qemu) setupNvram() error {
return nil
}
-func (vm *qemu) qemuArchConfig() (string, string, string, error) {
+func (vm *qemu) qemuArchConfig() (string, error) {
if vm.architecture == osarch.ARCH_64BIT_INTEL_X86 {
- conf := `
-[global]
-driver = "ICH9-LPC"
-property = "disable_s3"
-value = "1"
-
-[global]
-driver = "ICH9-LPC"
-property = "disable_s4"
-value = "1"
-`
- return "qemu-system-x86_64", "q35", conf, nil
+ return "qemu-system-x86_64", nil
} else if vm.architecture == osarch.ARCH_64BIT_ARMV8_LITTLE_ENDIAN {
- return "qemu-system-aarch64", "virt", "", nil
+ return "qemu-system-aarch64", nil
+ } else if vm.architecture == osarch.ARCH_64BIT_POWERPC_LITTLE_ENDIAN {
+ return "qemu-system-ppc64", nil
}
- return "", "", "", fmt.Errorf("Architecture isn't supported for virtual machines")
+ return "", fmt.Errorf("Architecture isn't supported for virtual machines")
}
// deviceVolatileGetFunc returns a function that retrieves a named device's volatile config and
@@ -1279,12 +1275,11 @@ func (vm *qemu) deviceBootPriorities() (map[string]int, error) {
// generateQemuConfigFile writes the qemu config file and returns its location.
// It writes the config file inside the VM's log path.
-func (vm *qemu) generateQemuConfigFile(qemuType string, qemuConf string, devConfs []*deviceConfig.RunConfig, fdFiles *[]string) (string, error) {
+func (vm *qemu) generateQemuConfigFile(devConfs []*deviceConfig.RunConfig, fdFiles *[]string) (string, error) {
var sb *strings.Builder = &strings.Builder{}
err := qemuBase.Execute(sb, map[string]interface{}{
- "qemuType": qemuType,
- "qemuConf": qemuConf,
+ "architecture": vm.architectureName,
"ringbufSizeBytes": qmp.RingbufSize,
})
if err != nil {
@@ -1372,6 +1367,7 @@ func (vm *qemu) addMemoryConfig(sb *strings.Builder) error {
}
return qemuMemory.Execute(sb, map[string]interface{}{
+ "architecture": vm.architectureName,
"memSizeBytes": memSizeBytes,
})
}
@@ -1379,7 +1375,8 @@ func (vm *qemu) addMemoryConfig(sb *strings.Builder) error {
// addVsockConfig adds the qemu config required for setting up the host->VM vsock socket.
func (vm *qemu) addVsockConfig(sb *strings.Builder) error {
return qemuVsock.Execute(sb, map[string]interface{}{
- "vsockID": vm.vsockID(),
+ "architecture": vm.architectureName,
+ "vsockID": vm.vsockID(),
})
}
@@ -1397,29 +1394,38 @@ func (vm *qemu) addCPUConfig(sb *strings.Builder) error {
}
return qemuCPU.Execute(sb, map[string]interface{}{
- "cpuCount": cpuCount,
+ "architecture": vm.architectureName,
+ "cpuCount": cpuCount,
})
}
// addMonitorConfig adds the qemu config required for setting up the host side VM monitor device.
func (vm *qemu) addMonitorConfig(sb *strings.Builder) error {
return qemuControlSocket.Execute(sb, map[string]interface{}{
- "path": vm.getMonitorPath(),
+ "architecture": vm.architectureName,
+ "path": vm.getMonitorPath(),
})
}
// addFirmwareConfig adds the qemu config required for adding a secure boot compatible EFI firmware.
func (vm *qemu) addFirmwareConfig(sb *strings.Builder) error {
+ // No UEFI nvram for ppc64le.
+ if vm.architecture == osarch.ARCH_64BIT_POWERPC_LITTLE_ENDIAN {
+ return nil
+ }
+
return qemuDriveFirmware.Execute(sb, map[string]interface{}{
- "roPath": filepath.Join(vm.ovmfPath(), "OVMF_CODE.fd"),
- "nvramPath": vm.getNvramPath(),
+ "architecture": vm.architectureName,
+ "roPath": filepath.Join(vm.ovmfPath(), "OVMF_CODE.fd"),
+ "nvramPath": vm.getNvramPath(),
})
}
// addConfDriveConfig adds the qemu config required for adding the config drive.
func (vm *qemu) addConfDriveConfig(sb *strings.Builder) error {
return qemuDriveConfig.Execute(sb, map[string]interface{}{
- "path": filepath.Join(vm.Path(), "config"),
+ "architecture": vm.architectureName,
+ "path": filepath.Join(vm.Path(), "config"),
})
}
@@ -1483,11 +1489,12 @@ func (vm *qemu) addDriveConfig(sb *strings.Builder, bootIndexes map[string]int,
}
return qemuDrive.Execute(sb, map[string]interface{}{
- "devName": driveConf.DevName,
- "devPath": driveConf.DevPath,
- "bootIndex": bootIndexes[driveConf.DevName],
- "cacheMode": cacheMode,
- "aioMode": aioMode,
+ "architecture": vm.architectureName,
+ "devName": driveConf.DevName,
+ "devPath": driveConf.DevPath,
+ "bootIndex": bootIndexes[driveConf.DevName],
+ "cacheMode": cacheMode,
+ "aioMode": aioMode,
})
}
@@ -1508,6 +1515,7 @@ func (vm *qemu) addNetDevConfig(sb *strings.Builder, nicIndex int, bootIndexes m
var tpl *template.Template
tplFields := map[string]interface{}{
+ "architecture": vm.architectureName,
"devName": devName,
"devHwaddr": devHwaddr,
"bootIndex": bootIndexes[devName],
diff --git a/lxd/instance/drivers/driver_qemu_templates.go b/lxd/instance/drivers/driver_qemu_templates.go
index 13c2ac6033..030432c35c 100644
--- a/lxd/instance/drivers/driver_qemu_templates.go
+++ b/lxd/instance/drivers/driver_qemu_templates.go
@@ -9,11 +9,30 @@ var qemuBase = template.Must(template.New("qemuBase").Parse(`
# Machine
[machine]
graphics = "off"
-type = "{{.qemuType}}"
+{{if eq .architecture "x86_64" -}}
+type = "q35"
+{{end -}}
+{{if eq .architecture "aarch64" -}}
+type = "virt"
+{{end -}}
+{{if eq .architecture "ppc64le" -}}
+type = "pseries"
+{{end -}}
accel = "kvm"
usb = "off"
graphics = "off"
-{{ .qemuConf -}}
+
+{{if eq .architecture "x86_64" -}}
+[global]
+driver = "ICH9-LPC"
+property = "disable_s3"
+value = "1"
+
+[global]
+driver = "ICH9-LPC"
+property = "disable_s4"
+value = "1"
+{{end -}}
[boot-opts]
strict = "on"
@@ -31,7 +50,8 @@ chardev = "vserial"
backend = "ringbuf"
size = "{{.ringbufSizeBytes}}B"
-# PCIe root
+# SCSI controller
+{{if ne .architecture "ppc64le" -}}
[device "qemu_pcie1"]
driver = "pcie-root-port"
port = "0x10"
@@ -39,42 +59,62 @@ chassis = "1"
bus = "pcie.0"
multifunction = "on"
addr = "0x2"
+{{- end }}
[device "qemu_scsi"]
driver = "virtio-scsi-pci"
+{{if eq .architecture "ppc64le" -}}
+bus = pci.0
+addr = "0x2"
+{{else -}}
bus = "qemu_pcie1"
addr = "0x0"
+{{end -}}
# Balloon driver
+{{if ne .architecture "ppc64le" -}}
[device "qemu_pcie2"]
driver = "pcie-root-port"
port = "0x11"
chassis = "2"
bus = "pcie.0"
addr = "0x2.0x1"
+{{- end }}
[device "qemu_ballon"]
driver = "virtio-balloon-pci"
+{{if eq .architecture "ppc64le" -}}
+bus = pci.0
+addr = "0x2.0x1"
+{{else -}}
bus = "qemu_pcie2"
addr = "0x0"
+{{end -}}
# Random number generator
[object "qemu_rng"]
qom-type = "rng-random"
filename = "/dev/urandom"
+{{if ne .architecture "ppc64le" -}}
[device "qemu_pcie3"]
driver = "pcie-root-port"
port = "0x12"
chassis = "3"
bus = "pcie.0"
addr = "0x2.0x2"
+{{- end }}
[device "dev-qemu_rng"]
driver = "virtio-rng-pci"
rng = "qemu_rng"
+{{if eq .architecture "ppc64le" -}}
+bus = "pci.0"
+addr = "0x2.0x2"
+{{else -}}
bus = "qemu_pcie3"
addr = "0x0"
+{{end -}}
# Console
[chardev "console"]
@@ -89,18 +129,25 @@ size = "{{.memSizeBytes}}B"
var qemuVsock = template.Must(template.New("qemuVsock").Parse(`
# Vsock
+{{if ne .architecture "ppc64le" -}}
[device "qemu_pcie4"]
driver = "pcie-root-port"
port = "0x13"
chassis = "4"
bus = "pcie.0"
addr = "0x2.0x3"
+{{- end }}
[device]
driver = "vhost-vsock-pci"
guest-cid = "{{.vsockID}}"
+{{if eq .architecture "ppc64le" -}}
+bus = "pci.0"
+addr = "0x2.0x3"
+{{else -}}
bus = "qemu_pcie4"
addr = "0x0"
+{{end -}}
`))
var qemuCPU = template.Must(template.New("qemuCPU").Parse(`
@@ -176,19 +223,26 @@ bootindex = "{{.bootIndex}}"
// qemuDevTapCommon is common PCI device template for tap based netdevs.
var qemuDevTapCommon = template.Must(template.New("qemuDevTapCommon").Parse(`
+{{if ne .architecture "ppc64le" -}}
[device "qemu_pcie{{.chassisIndex}}"]
driver = "pcie-root-port"
port = "0x{{.portIndex}}"
chassis = "{{.chassisIndex}}"
bus = "pcie.0"
addr = "0x2.0x{{.pcieAddr}}"
+{{- end }}
[device "dev-lxd_{{.devName}}"]
driver = "virtio-net-pci"
netdev = "lxd_{{.devName}}"
mac = "{{.devHwaddr}}"
+{{if eq .architecture "ppc64le" -}}
+bus = "pci.0"
+addr = "0x2.0x{{.pcieAddr}}"
+{{else -}}
bus = "qemu_pcie{{.chassisIndex}}"
addr = "0x0"
+{{end -}}
bootindex = "{{.bootIndex}}"
`))
More information about the lxc-devel
mailing list