github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/qemu_amd64_test.go (about) 1 // Copyright (c) 2018 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 package virtcontainers 7 8 import ( 9 "fmt" 10 "io/ioutil" 11 "os" 12 "testing" 13 14 govmmQemu "github.com/kata-containers/govmm/qemu" 15 "github.com/kata-containers/runtime/virtcontainers/types" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 func qemuConfig(machineType string) HypervisorConfig { 20 return HypervisorConfig{ 21 HypervisorMachineType: machineType, 22 } 23 } 24 25 func newTestQemu(machineType string) qemuArch { 26 config := qemuConfig(machineType) 27 return newQemuArch(config) 28 } 29 30 func TestQemuAmd64Capabilities(t *testing.T) { 31 assert := assert.New(t) 32 33 amd64 := newTestQemu(QemuPC) 34 caps := amd64.capabilities() 35 assert.True(caps.IsBlockDeviceHotplugSupported()) 36 37 amd64 = newTestQemu(QemuQ35) 38 caps = amd64.capabilities() 39 assert.True(caps.IsBlockDeviceHotplugSupported()) 40 41 amd64 = newTestQemu(QemuMicrovm) 42 caps = amd64.capabilities() 43 assert.False(caps.IsBlockDeviceHotplugSupported()) 44 } 45 46 func TestQemuAmd64Bridges(t *testing.T) { 47 assert := assert.New(t) 48 amd64 := newTestQemu(QemuPC) 49 len := 5 50 51 amd64.bridges(uint32(len)) 52 bridges := amd64.getBridges() 53 assert.Len(bridges, len) 54 55 for i, b := range bridges { 56 id := fmt.Sprintf("%s-bridge-%d", types.PCI, i) 57 assert.Equal(types.PCI, b.Type) 58 assert.Equal(id, b.ID) 59 assert.NotNil(b.Devices) 60 } 61 62 amd64 = newTestQemu(QemuQ35) 63 amd64.bridges(uint32(len)) 64 bridges = amd64.getBridges() 65 assert.Len(bridges, len) 66 67 for i, b := range bridges { 68 id := fmt.Sprintf("%s-bridge-%d", types.PCI, i) 69 assert.Equal(types.PCI, b.Type) 70 assert.Equal(id, b.ID) 71 assert.NotNil(b.Devices) 72 } 73 74 amd64 = newTestQemu(QemuMicrovm) 75 amd64.bridges(uint32(len)) 76 bridges = amd64.getBridges() 77 assert.Nil(bridges) 78 79 amd64 = newTestQemu(QemuQ35 + QemuPC) 80 amd64.bridges(uint32(len)) 81 bridges = amd64.getBridges() 82 assert.Nil(bridges) 83 } 84 85 func TestQemuAmd64CPUModel(t *testing.T) { 86 assert := assert.New(t) 87 amd64 := newTestQemu(QemuPC) 88 89 expectedOut := defaultCPUModel 90 model := amd64.cpuModel() 91 assert.Equal(expectedOut, model) 92 93 amd64.disableNestingChecks() 94 base, ok := amd64.(*qemuAmd64) 95 assert.True(ok) 96 base.vmFactory = true 97 expectedOut = defaultCPUModel + ",vmx=off" 98 model = amd64.cpuModel() 99 assert.Equal(expectedOut, model) 100 } 101 102 func TestQemuAmd64MemoryTopology(t *testing.T) { 103 assert := assert.New(t) 104 amd64 := newTestQemu(QemuPC) 105 memoryOffset := 1024 106 107 hostMem := uint64(100) 108 mem := uint64(120) 109 slots := uint8(10) 110 expectedMemory := govmmQemu.Memory{ 111 Size: fmt.Sprintf("%dM", mem), 112 Slots: slots, 113 MaxMem: fmt.Sprintf("%dM", hostMem+uint64(memoryOffset)), 114 } 115 116 m := amd64.memoryTopology(mem, hostMem, slots) 117 assert.Equal(expectedMemory, m) 118 } 119 120 func TestQemuAmd64AppendImage(t *testing.T) { 121 assert := assert.New(t) 122 123 f, err := ioutil.TempFile("", "img") 124 assert.NoError(err) 125 defer func() { _ = f.Close() }() 126 defer func() { _ = os.Remove(f.Name()) }() 127 128 imageStat, err := f.Stat() 129 assert.NoError(err) 130 131 // save default supportedQemuMachines options 132 machinesCopy := make([]govmmQemu.Machine, len(supportedQemuMachines)) 133 assert.Equal(len(supportedQemuMachines), copy(machinesCopy, supportedQemuMachines)) 134 135 cfg := qemuConfig(QemuPC) 136 cfg.ImagePath = f.Name() 137 cfg.DisableImageNvdimm = false 138 amd64 := newQemuArch(cfg) 139 for _, m := range amd64.(*qemuAmd64).supportedQemuMachines { 140 assert.Contains(m.Options, qemuNvdimmOption) 141 } 142 143 expectedOut := []govmmQemu.Device{ 144 govmmQemu.Object{ 145 Driver: govmmQemu.NVDIMM, 146 Type: govmmQemu.MemoryBackendFile, 147 DeviceID: "nv0", 148 ID: "mem0", 149 MemPath: f.Name(), 150 Size: (uint64)(imageStat.Size()), 151 }, 152 } 153 154 devices, err := amd64.appendImage(nil, f.Name()) 155 assert.NoError(err) 156 assert.Equal(expectedOut, devices) 157 158 // restore default supportedQemuMachines options 159 assert.Equal(len(supportedQemuMachines), copy(supportedQemuMachines, machinesCopy)) 160 161 cfg.DisableImageNvdimm = true 162 amd64 = newQemuArch(cfg) 163 for _, m := range amd64.(*qemuAmd64).supportedQemuMachines { 164 assert.NotContains(m.Options, qemuNvdimmOption) 165 } 166 167 found := false 168 devices, err = amd64.appendImage(nil, f.Name()) 169 assert.NoError(err) 170 for _, d := range devices { 171 if b, ok := d.(govmmQemu.BlockDevice); ok { 172 assert.Equal(b.Driver, govmmQemu.VirtioBlock) 173 assert.True(b.ShareRW) 174 found = true 175 } 176 } 177 assert.True(found) 178 179 // restore default supportedQemuMachines options 180 assert.Equal(len(supportedQemuMachines), copy(supportedQemuMachines, machinesCopy)) 181 } 182 183 func TestQemuAmd64AppendBridges(t *testing.T) { 184 var devices []govmmQemu.Device 185 assert := assert.New(t) 186 187 // check PC 188 amd64 := newTestQemu(QemuPC) 189 190 amd64.bridges(1) 191 bridges := amd64.getBridges() 192 assert.Len(bridges, 1) 193 194 devices = amd64.appendBridges(devices) 195 assert.Len(devices, 1) 196 197 expectedOut := []govmmQemu.Device{ 198 govmmQemu.BridgeDevice{ 199 Type: govmmQemu.PCIBridge, 200 Bus: defaultPCBridgeBus, 201 ID: bridges[0].ID, 202 Chassis: 1, 203 SHPC: true, 204 Addr: "2", 205 }, 206 } 207 208 assert.Equal(expectedOut, devices) 209 210 // Check Q35 211 amd64 = newTestQemu(QemuQ35) 212 213 amd64.bridges(1) 214 bridges = amd64.getBridges() 215 assert.Len(bridges, 1) 216 217 devices = []govmmQemu.Device{} 218 devices = amd64.appendBridges(devices) 219 assert.Len(devices, 1) 220 221 expectedOut = []govmmQemu.Device{ 222 govmmQemu.BridgeDevice{ 223 Type: govmmQemu.PCIBridge, 224 Bus: defaultBridgeBus, 225 ID: bridges[0].ID, 226 Chassis: 1, 227 SHPC: true, 228 Addr: "2", 229 }, 230 } 231 232 assert.Equal(expectedOut, devices) 233 } 234 235 func TestQemuAmd64WithInitrd(t *testing.T) { 236 assert := assert.New(t) 237 238 cfg := qemuConfig(QemuPC) 239 cfg.InitrdPath = "dummy-initrd" 240 amd64 := newQemuArch(cfg) 241 242 for _, m := range amd64.(*qemuAmd64).supportedQemuMachines { 243 assert.NotContains(m.Options, qemuNvdimmOption) 244 } 245 } 246 247 func TestQemuAmd64Microvm(t *testing.T) { 248 assert := assert.New(t) 249 250 cfg := qemuConfig(QemuMicrovm) 251 amd64 := newQemuArch(cfg) 252 assert.False(cfg.DisableImageNvdimm) 253 254 for _, m := range amd64.(*qemuAmd64).supportedQemuMachines { 255 assert.NotContains(m.Options, qemuNvdimmOption) 256 } 257 258 assert.False(amd64.supportGuestMemoryHotplug()) 259 } 260 261 func TestQemuAmd64Iommu(t *testing.T) { 262 assert := assert.New(t) 263 264 config := qemuConfig(QemuQ35) 265 config.IOMMU = true 266 qemu := newQemuArch(config) 267 268 p := qemu.kernelParameters(false) 269 assert.Contains(p, Param{"intel_iommu", "on"}) 270 271 m, err := qemu.machine() 272 273 assert.NoError(err) 274 assert.Contains(m.Options, "kernel_irqchip=split") 275 }