diff --git a/virtcontainers/qemu.go b/virtcontainers/qemu.go index 479d2517d3..1eac467d42 100644 --- a/virtcontainers/qemu.go +++ b/virtcontainers/qemu.go @@ -1764,6 +1764,9 @@ func genericAppendBridges(devices []govmmQemu.Device, bridges []types.Bridge, ma if b.Type == types.PCIE { t = govmmQemu.PCIEBridge } + if b.Type == types.CCW { + continue + } bridges[idx].Addr = bridgePCIStartAddr + idx @@ -1783,7 +1786,6 @@ func genericAppendBridges(devices []govmmQemu.Device, bridges []types.Bridge, ma return devices } -// nolint: unused, deadcode func genericBridges(number uint32, machineType string) []types.Bridge { var bridges []types.Bridge var bt types.Type @@ -1800,7 +1802,7 @@ func genericBridges(number uint32, machineType string) []types.Bridge { case QemuPseries: bt = types.PCI case QemuCCWVirtio: - bt = types.PCI + bt = types.CCW default: return nil } diff --git a/virtcontainers/qemu_arch_base.go b/virtcontainers/qemu_arch_base.go index 004006e96e..f2ccc04b1c 100644 --- a/virtcontainers/qemu_arch_base.go +++ b/virtcontainers/qemu_arch_base.go @@ -362,6 +362,9 @@ func (q *qemuArchBase) appendSCSIController(devices []govmmQemu.Device, enableIO // appendBridges appends to devices the given bridges func (q *qemuArchBase) appendBridges(devices []govmmQemu.Device) []govmmQemu.Device { for idx, b := range q.Bridges { + if b.Type == types.CCW { + continue + } t := govmmQemu.PCIBridge if b.Type == types.PCIE { t = govmmQemu.PCIEBridge @@ -618,6 +621,8 @@ func (q *qemuArchBase) addDeviceToBridge(ID string, t types.Type) (string, types addr, err = b.AddDevice(ID) if err == nil { switch t { + case types.CCW: + return fmt.Sprintf("%04x", addr), b, nil case types.PCI, types.PCIE: return fmt.Sprintf("%02x", addr), b, nil } diff --git a/virtcontainers/qemu_s390x.go b/virtcontainers/qemu_s390x.go index 498e83f6b6..4a2840150b 100644 --- a/virtcontainers/qemu_s390x.go +++ b/virtcontainers/qemu_s390x.go @@ -11,6 +11,7 @@ import ( govmmQemu "github.com/intel/govmm/qemu" "github.com/kata-containers/runtime/virtcontainers/device/config" + "github.com/kata-containers/runtime/virtcontainers/types" ) type qemuS390x struct { @@ -39,6 +40,8 @@ var kernelParams = []Param{ var kernelRootParams = commonVirtioblkKernelRootParams +var ccwbridge = types.NewBridge(types.CCW, "", make(map[uint32]string, types.CCWBridgeMaxCapacity), 0) + var supportedQemuMachines = []govmmQemu.Machine{ { Type: QemuCCWVirtio, @@ -71,6 +74,8 @@ func newQemuArch(config HypervisorConfig) qemuArch { kernelParams: kernelParams, }, } + // Set first bridge type to CCW + q.Bridges = append(q.Bridges, ccwbridge) if config.ImagePath != "" { q.kernelParams = append(q.kernelParams, kernelRootParams...) diff --git a/virtcontainers/types/bridges.go b/virtcontainers/types/bridges.go index 6b0e0cbb98..cb15a88f0e 100644 --- a/virtcontainers/types/bridges.go +++ b/virtcontainers/types/bridges.go @@ -10,7 +10,7 @@ import "fmt" // Type represents a type of bus and bridge. type Type string -const pciBridgeMaxCapacity = 30 +const PCIBridgeMaxCapacity = 30 const ( // PCI represents a PCI bus and bridge @@ -20,6 +20,12 @@ const ( PCIE Type = "pcie" ) +const CCWBridgeMaxCapacity = 0xffff + +const ( + CCW Type = "ccw" +) + type Bridge struct { // Devices contains information about devices plugged and its address in the bridge Devices map[uint32]string @@ -43,7 +49,9 @@ func NewBridge(bt Type, id string, devices map[uint32]string, addr int) Bridge { case PCI: fallthrough case PCIE: - maxCapacity = pciBridgeMaxCapacity + maxCapacity = PCIBridgeMaxCapacity + case CCW: + maxCapacity = CCWBridgeMaxCapacity default: maxCapacity = 0 } @@ -88,3 +96,20 @@ func (b *Bridge) RemoveDevice(ID string) error { return fmt.Errorf("Unable to hot unplug device %s: not present on bridge", ID) } + +// AddressFormatCCW returns the address format for the device number. The channel subsystem-ID 0xfe is reserved to the virtual channel and the address format is in the form fe.n.dddd, where n is subchannel set ID and ddd the device number. More details at https://www.ibm.com/support/knowledgecenter/en/linuxonibm/com.ibm.linux.z.ldva/ldva_t_configuringSCSIdevices.html +func (b *Bridge) AddressFormatCCW(addr string) (string, error) { + if b.Type != CCW { + return "", fmt.Errorf("Expected bridge type %T, got %T (%+v)", CCW, b.Type, b) + } + + return fmt.Sprintf("fe.%x.%s", b.Addr, addr), nil +} + +// AddressFormatCCWForVirtServer returns the address format for the virtual server. The address format is in the form of 0.n.dddd +func (b *Bridge) AddressFormatCCWForVirtServer(addr string) (string, error) { + if b.Type != CCW { + return "", fmt.Errorf("Wrong bridge type") + } + return fmt.Sprintf("0.%x.%s", b.Addr, addr), nil +} diff --git a/virtcontainers/types/bridges_test.go b/virtcontainers/types/bridges_test.go index d2837b85cb..d8102eaa1d 100644 --- a/virtcontainers/types/bridges_test.go +++ b/virtcontainers/types/bridges_test.go @@ -46,7 +46,15 @@ func testAddRemoveDevice(t *testing.T, b *Bridge) { func TestAddRemoveDevicePCI(t *testing.T) { // create a pci bridge - bridges := []*Bridge{{make(map[uint32]string), "rgb123", 5, PCI, pciBridgeMaxCapacity}} + bridges := []*Bridge{{make(map[uint32]string), "rgb123", 5, PCI, PCIBridgeMaxCapacity}} + + testAddRemoveDevice(t, bridges[0]) +} + +func TestAddRemoveDeviceCCW(t *testing.T) { + + // create a CCW bridge + bridges := []*Bridge{{make(map[uint32]string), "rgb123", 5, CCW, CCWBridgeMaxCapacity}} testAddRemoveDevice(t, bridges[0]) }