gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/qemu_s390x.go (about) 1 // Copyright (c) 2018 IBM 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 package virtcontainers 7 8 import ( 9 "fmt" 10 "time" 11 12 govmmQemu "github.com/intel/govmm/qemu" 13 "github.com/kata-containers/runtime/virtcontainers/device/config" 14 "github.com/kata-containers/runtime/virtcontainers/types" 15 ) 16 17 type qemuS390x struct { 18 // inherit from qemuArchBase, overwrite methods if needed 19 qemuArchBase 20 } 21 22 const defaultQemuPath = "/usr/bin/qemu-system-s390x" 23 24 const defaultQemuMachineType = QemuCCWVirtio 25 26 const defaultQemuMachineOptions = "accel=kvm" 27 28 const virtioSerialCCW = "virtio-serial-ccw" 29 30 const qmpMigrationWaitTimeout = 5 * time.Second 31 32 var qemuPaths = map[string]string{ 33 QemuCCWVirtio: defaultQemuPath, 34 } 35 36 // Verify needed parameters 37 var kernelParams = []Param{ 38 {"console", "ttysclp0"}, 39 } 40 41 var ccwbridge = types.NewBridge(types.CCW, "", make(map[uint32]string, types.CCWBridgeMaxCapacity), 0) 42 43 var supportedQemuMachines = []govmmQemu.Machine{ 44 { 45 Type: QemuCCWVirtio, 46 Options: defaultQemuMachineOptions, 47 }, 48 } 49 50 // MaxQemuVCPUs returns the maximum number of vCPUs supported 51 func MaxQemuVCPUs() uint32 { 52 // Max number of virtual Cpu defined in qemu. See 53 // https://github.com/qemu/qemu/blob/80422b00196a7af4c6efb628fae0ad8b644e98af/target/s390x/cpu.h#L55 54 // #define S390_MAX_CPUS 248 55 return uint32(248) 56 } 57 58 func newQemuArch(config HypervisorConfig) qemuArch { 59 machineType := config.HypervisorMachineType 60 if machineType == "" { 61 machineType = defaultQemuMachineType 62 } 63 64 q := &qemuS390x{ 65 qemuArchBase{ 66 machineType: machineType, 67 memoryOffset: config.MemOffset, 68 qemuPaths: qemuPaths, 69 supportedQemuMachines: supportedQemuMachines, 70 kernelParamsNonDebug: kernelParamsNonDebug, 71 kernelParamsDebug: kernelParamsDebug, 72 kernelParams: kernelParams, 73 }, 74 } 75 // Set first bridge type to CCW 76 q.Bridges = append(q.Bridges, ccwbridge) 77 78 if config.ImagePath != "" { 79 q.kernelParams = append(q.kernelParams, commonVirtioblkKernelRootParams...) 80 q.kernelParamsNonDebug = append(q.kernelParamsNonDebug, kernelParamsSystemdNonDebug...) 81 q.kernelParamsDebug = append(q.kernelParamsDebug, kernelParamsSystemdDebug...) 82 } 83 84 return q 85 } 86 87 func (q *qemuS390x) bridges(number uint32) { 88 q.Bridges = genericBridges(number, q.machineType) 89 } 90 91 // appendConsole appends a console to devices. 92 // The function has been overwriten to correctly set the driver to the CCW device 93 func (q *qemuS390x) appendConsole(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) { 94 id := "serial0" 95 addr, b, err := q.addDeviceToBridge(id, types.CCW) 96 if err != nil { 97 return devices, fmt.Errorf("Failed to append console %v", err) 98 } 99 100 var devno string 101 devno, err = b.AddressFormatCCW(addr) 102 if err != nil { 103 return devices, fmt.Errorf("Failed to append console %v", err) 104 } 105 106 serial := govmmQemu.SerialDevice{ 107 Driver: virtioSerialCCW, 108 ID: id, 109 DisableModern: q.nestedRun, 110 DevNo: devno, 111 } 112 113 devices = append(devices, serial) 114 115 console := govmmQemu.CharDevice{ 116 Driver: govmmQemu.Console, 117 Backend: govmmQemu.Socket, 118 DeviceID: "console0", 119 ID: "charconsole0", 120 Path: path, 121 } 122 123 devices = append(devices, console) 124 125 return devices, nil 126 } 127 128 func (q *qemuS390x) appendImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) { 129 drive, err := genericImage(path) 130 if err != nil { 131 return nil, err 132 } 133 return q.appendCCWBlockDevice(devices, drive) 134 } 135 136 func (q *qemuS390x) appendBlockDevice(devices []govmmQemu.Device, drive config.BlockDrive) ([]govmmQemu.Device, error) { 137 return q.appendCCWBlockDevice(devices, drive) 138 } 139 140 func (q *qemuS390x) appendCCWBlockDevice(devices []govmmQemu.Device, drive config.BlockDrive) ([]govmmQemu.Device, error) { 141 d, err := genericBlockDevice(drive, false) 142 if err != nil { 143 return devices, fmt.Errorf("Failed to append blk-dev %v", err) 144 } 145 addr, b, err := q.addDeviceToBridge(drive.ID, types.CCW) 146 if err != nil { 147 return devices, fmt.Errorf("Failed to append blk-dev %v", err) 148 } 149 d.DevNo, err = b.AddressFormatCCW(addr) 150 if err != nil { 151 return devices, fmt.Errorf("Failed to append blk-dev %v", err) 152 } 153 devices = append(devices, d) 154 return devices, nil 155 } 156 157 // appendVhostUserDevice throws an error if vhost devices are tried to be used. 158 // See issue https://github.com/kata-containers/runtime/issues/659 159 func (q *qemuS390x) appendVhostUserDevice(devices []govmmQemu.Device, attr config.VhostUserDeviceAttrs) ([]govmmQemu.Device, error) { 160 return nil, fmt.Errorf("No vhost-user devices supported on s390x") 161 } 162 163 // supportGuestMemoryHotplug return false for s390x architecture. The pc-dimm backend device for s390x 164 // is not support. PC-DIMM is not listed in the devices supported by qemu-system-s390x -device help 165 func (q *qemuS390x) supportGuestMemoryHotplug() bool { 166 return false 167 } 168 169 func (q *qemuS390x) appendNetwork(devices []govmmQemu.Device, endpoint Endpoint) ([]govmmQemu.Device, error) { 170 d, err := genericNetwork(endpoint, false, false, q.networkIndex) 171 if err != nil { 172 return devices, fmt.Errorf("Failed to append network %v", err) 173 } 174 q.networkIndex++ 175 addr, b, err := q.addDeviceToBridge(d.ID, types.CCW) 176 if err != nil { 177 return devices, fmt.Errorf("Failed to append network %v", err) 178 } 179 d.DevNo, err = b.AddressFormatCCW(addr) 180 if err != nil { 181 return devices, fmt.Errorf("Failed to append network %v", err) 182 } 183 184 devices = append(devices, d) 185 return devices, nil 186 } 187 188 func (q *qemuS390x) appendRNGDevice(devices []govmmQemu.Device, rngDev config.RNGDev) ([]govmmQemu.Device, error) { 189 addr, b, err := q.addDeviceToBridge(rngDev.ID, types.CCW) 190 if err != nil { 191 return devices, fmt.Errorf("Failed to append RNG-Device %v", err) 192 } 193 var devno string 194 devno, err = b.AddressFormatCCW(addr) 195 if err != nil { 196 return devices, fmt.Errorf("Failed to append RNG-Device %v", err) 197 } 198 199 devices = append(devices, 200 govmmQemu.RngDevice{ 201 ID: rngDev.ID, 202 Filename: rngDev.Filename, 203 DevNo: devno, 204 }, 205 ) 206 207 return devices, nil 208 } 209 210 func (q *qemuS390x) append9PVolume(devices []govmmQemu.Device, volume types.Volume) ([]govmmQemu.Device, error) { 211 if volume.MountTag == "" || volume.HostPath == "" { 212 return devices, nil 213 } 214 d := generic9PVolume(volume, false) 215 addr, b, err := q.addDeviceToBridge(d.ID, types.CCW) 216 if err != nil { 217 return devices, fmt.Errorf("Failed to append 9p-Volume %v", err) 218 } 219 d.DevNo, err = b.AddressFormatCCW(addr) 220 if err != nil { 221 return devices, fmt.Errorf("Failed to append 9p-Volume %v", err) 222 } 223 devices = append(devices, d) 224 return devices, nil 225 } 226 227 // appendBridges appends to devices the given bridges 228 func (q *qemuS390x) appendBridges(devices []govmmQemu.Device) []govmmQemu.Device { 229 return genericAppendBridges(devices, q.Bridges, q.machineType) 230 } 231 232 func (q *qemuS390x) appendSCSIController(devices []govmmQemu.Device, enableIOThreads bool) ([]govmmQemu.Device, *govmmQemu.IOThread, error) { 233 d, t := genericSCSIController(enableIOThreads, q.nestedRun) 234 addr, b, err := q.addDeviceToBridge(d.ID, types.CCW) 235 if err != nil { 236 return devices, nil, fmt.Errorf("Failed to append scsi-controller %v", err) 237 } 238 d.DevNo, err = b.AddressFormatCCW(addr) 239 if err != nil { 240 return devices, nil, fmt.Errorf("Failed to append scsi-controller %v", err) 241 } 242 243 devices = append(devices, d) 244 return devices, t, nil 245 } 246 247 func (q *qemuS390x) appendVSock(devices []govmmQemu.Device, vsock types.VSock) ([]govmmQemu.Device, error) { 248 var devno string 249 id := fmt.Sprintf("vsock-%d", vsock.ContextID) 250 addr, b, err := q.addDeviceToBridge(id, types.CCW) 251 if err != nil { 252 return devices, fmt.Errorf("Failed to append VSock: %v", err) 253 } 254 devno, err = b.AddressFormatCCW(addr) 255 if err != nil { 256 return devices, fmt.Errorf("Failed to append VSock: %v", err) 257 } 258 devices = append(devices, 259 govmmQemu.VSOCKDevice{ 260 ID: id, 261 ContextID: vsock.ContextID, 262 VHostFD: vsock.VhostFd, 263 DisableModern: false, 264 DevNo: devno, 265 }, 266 ) 267 268 return devices, nil 269 270 }