github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/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/kata-containers/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  	qemuMachines := make([]govmmQemu.Machine, len(supportedQemuMachines))
    65  	copy(qemuMachines, supportedQemuMachines)
    66  
    67  	q := &qemuS390x{
    68  		qemuArchBase{
    69  			machineType:           machineType,
    70  			memoryOffset:          config.MemOffset,
    71  			qemuPaths:             qemuPaths,
    72  			supportedQemuMachines: qemuMachines,
    73  			kernelParamsNonDebug:  kernelParamsNonDebug,
    74  			kernelParamsDebug:     kernelParamsDebug,
    75  			kernelParams:          kernelParams,
    76  		},
    77  	}
    78  	// Set first bridge type to CCW
    79  	q.Bridges = append(q.Bridges, ccwbridge)
    80  
    81  	if config.ImagePath != "" {
    82  		q.kernelParams = append(q.kernelParams, commonVirtioblkKernelRootParams...)
    83  		q.kernelParamsNonDebug = append(q.kernelParamsNonDebug, kernelParamsSystemdNonDebug...)
    84  		q.kernelParamsDebug = append(q.kernelParamsDebug, kernelParamsSystemdDebug...)
    85  	}
    86  
    87  	return q
    88  }
    89  
    90  func (q *qemuS390x) bridges(number uint32) {
    91  	q.Bridges = genericBridges(number, q.machineType)
    92  }
    93  
    94  // appendConsole appends a console to devices.
    95  // The function has been overwriten to correctly set the driver to the CCW device
    96  func (q *qemuS390x) appendConsole(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
    97  	id := "serial0"
    98  	addr, b, err := q.addDeviceToBridge(id, types.CCW)
    99  	if err != nil {
   100  		return devices, fmt.Errorf("Failed to append console %v", err)
   101  	}
   102  
   103  	var devno string
   104  	devno, err = b.AddressFormatCCW(addr)
   105  	if err != nil {
   106  		return devices, fmt.Errorf("Failed to append console %v", err)
   107  	}
   108  
   109  	serial := govmmQemu.SerialDevice{
   110  		Driver:        virtioSerialCCW,
   111  		ID:            id,
   112  		DisableModern: q.nestedRun,
   113  		DevNo:         devno,
   114  	}
   115  
   116  	devices = append(devices, serial)
   117  
   118  	console := govmmQemu.CharDevice{
   119  		Driver:   govmmQemu.Console,
   120  		Backend:  govmmQemu.Socket,
   121  		DeviceID: "console0",
   122  		ID:       "charconsole0",
   123  		Path:     path,
   124  	}
   125  
   126  	devices = append(devices, console)
   127  
   128  	return devices, nil
   129  }
   130  
   131  func (q *qemuS390x) appendImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
   132  	drive, err := genericImage(path)
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  	return q.appendCCWBlockDevice(devices, drive)
   137  }
   138  
   139  func (q *qemuS390x) appendBlockDevice(devices []govmmQemu.Device, drive config.BlockDrive) ([]govmmQemu.Device, error) {
   140  	return q.appendCCWBlockDevice(devices, drive)
   141  }
   142  
   143  func (q *qemuS390x) appendCCWBlockDevice(devices []govmmQemu.Device, drive config.BlockDrive) ([]govmmQemu.Device, error) {
   144  	d, err := genericBlockDevice(drive, false)
   145  	if err != nil {
   146  		return devices, fmt.Errorf("Failed to append blk-dev %v", err)
   147  	}
   148  	addr, b, err := q.addDeviceToBridge(drive.ID, types.CCW)
   149  	if err != nil {
   150  		return devices, fmt.Errorf("Failed to append blk-dev %v", err)
   151  	}
   152  	d.DevNo, err = b.AddressFormatCCW(addr)
   153  	if err != nil {
   154  		return devices, fmt.Errorf("Failed to append blk-dev %v", err)
   155  	}
   156  	devices = append(devices, d)
   157  	return devices, nil
   158  }
   159  
   160  // appendVhostUserDevice throws an error if vhost devices are tried to be used.
   161  // See issue https://github.com/kata-containers/runtime/issues/659
   162  func (q *qemuS390x) appendVhostUserDevice(devices []govmmQemu.Device, attr config.VhostUserDeviceAttrs) ([]govmmQemu.Device, error) {
   163  	return nil, fmt.Errorf("No vhost-user devices supported on s390x")
   164  }
   165  
   166  // supportGuestMemoryHotplug return false for s390x architecture. The pc-dimm backend device for s390x
   167  // is not support. PC-DIMM is not listed in the devices supported by qemu-system-s390x -device help
   168  func (q *qemuS390x) supportGuestMemoryHotplug() bool {
   169  	return false
   170  }
   171  
   172  func (q *qemuS390x) appendNetwork(devices []govmmQemu.Device, endpoint Endpoint) ([]govmmQemu.Device, error) {
   173  	d, err := genericNetwork(endpoint, false, false, q.networkIndex)
   174  	if err != nil {
   175  		return devices, fmt.Errorf("Failed to append network %v", err)
   176  	}
   177  	q.networkIndex++
   178  	addr, b, err := q.addDeviceToBridge(d.ID, types.CCW)
   179  	if err != nil {
   180  		return devices, fmt.Errorf("Failed to append network %v", err)
   181  	}
   182  	d.DevNo, err = b.AddressFormatCCW(addr)
   183  	if err != nil {
   184  		return devices, fmt.Errorf("Failed to append network %v", err)
   185  	}
   186  
   187  	devices = append(devices, d)
   188  	return devices, nil
   189  }
   190  
   191  func (q *qemuS390x) appendRNGDevice(devices []govmmQemu.Device, rngDev config.RNGDev) ([]govmmQemu.Device, error) {
   192  	addr, b, err := q.addDeviceToBridge(rngDev.ID, types.CCW)
   193  	if err != nil {
   194  		return devices, fmt.Errorf("Failed to append RNG-Device %v", err)
   195  	}
   196  	var devno string
   197  	devno, err = b.AddressFormatCCW(addr)
   198  	if err != nil {
   199  		return devices, fmt.Errorf("Failed to append RNG-Device %v", err)
   200  	}
   201  
   202  	devices = append(devices,
   203  		govmmQemu.RngDevice{
   204  			ID:       rngDev.ID,
   205  			Filename: rngDev.Filename,
   206  			DevNo:    devno,
   207  		},
   208  	)
   209  
   210  	return devices, nil
   211  }
   212  
   213  func (q *qemuS390x) append9PVolume(devices []govmmQemu.Device, volume types.Volume) ([]govmmQemu.Device, error) {
   214  	if volume.MountTag == "" || volume.HostPath == "" {
   215  		return devices, nil
   216  	}
   217  	d := generic9PVolume(volume, false)
   218  	addr, b, err := q.addDeviceToBridge(d.ID, types.CCW)
   219  	if err != nil {
   220  		return devices, fmt.Errorf("Failed to append 9p-Volume %v", err)
   221  	}
   222  	d.DevNo, err = b.AddressFormatCCW(addr)
   223  	if err != nil {
   224  		return devices, fmt.Errorf("Failed to append 9p-Volume %v", err)
   225  	}
   226  	devices = append(devices, d)
   227  	return devices, nil
   228  }
   229  
   230  // appendBridges appends to devices the given bridges
   231  func (q *qemuS390x) appendBridges(devices []govmmQemu.Device) []govmmQemu.Device {
   232  	return genericAppendBridges(devices, q.Bridges, q.machineType)
   233  }
   234  
   235  func (q *qemuS390x) appendSCSIController(devices []govmmQemu.Device, enableIOThreads bool) ([]govmmQemu.Device, *govmmQemu.IOThread, error) {
   236  	d, t := genericSCSIController(enableIOThreads, q.nestedRun)
   237  	addr, b, err := q.addDeviceToBridge(d.ID, types.CCW)
   238  	if err != nil {
   239  		return devices, nil, fmt.Errorf("Failed to append scsi-controller %v", err)
   240  	}
   241  	d.DevNo, err = b.AddressFormatCCW(addr)
   242  	if err != nil {
   243  		return devices, nil, fmt.Errorf("Failed to append scsi-controller %v", err)
   244  	}
   245  
   246  	devices = append(devices, d)
   247  	return devices, t, nil
   248  }
   249  
   250  func (q *qemuS390x) appendVSock(devices []govmmQemu.Device, vsock types.VSock) ([]govmmQemu.Device, error) {
   251  	var devno string
   252  	id := fmt.Sprintf("vsock-%d", vsock.ContextID)
   253  	addr, b, err := q.addDeviceToBridge(id, types.CCW)
   254  	if err != nil {
   255  		return devices, fmt.Errorf("Failed to append VSock: %v", err)
   256  	}
   257  	devno, err = b.AddressFormatCCW(addr)
   258  	if err != nil {
   259  		return devices, fmt.Errorf("Failed to append VSock: %v", err)
   260  	}
   261  	devices = append(devices,
   262  		govmmQemu.VSOCKDevice{
   263  			ID:            id,
   264  			ContextID:     vsock.ContextID,
   265  			VHostFD:       vsock.VhostFd,
   266  			DisableModern: false,
   267  			DevNo:         devno,
   268  		},
   269  	)
   270  
   271  	return devices, nil
   272  
   273  }
   274  
   275  func (q *qemuS390x) appendIOMMU(devices []govmmQemu.Device) ([]govmmQemu.Device, error) {
   276  	return devices, fmt.Errorf("S390x does not support appending a vIOMMU")
   277  }