diff --git a/src/runtime/cli/config/configuration-fc.toml.in b/src/runtime/cli/config/configuration-fc.toml.in index c9850d974b..0f0dc63afa 100644 --- a/src/runtime/cli/config/configuration-fc.toml.in +++ b/src/runtime/cli/config/configuration-fc.toml.in @@ -129,6 +129,12 @@ block_device_driver = "@DEFBLOCKSTORAGEDRIVER_FC@" # result in memory pre allocation #enable_hugepages = true +# Enable vIOMMU, default false +# Enabling this will result in the VM having a vIOMMU device +# This will also add the following options to the kernel's +# command line: intel_iommu=on,iommu=pt +#enable_iommu = true + # Enable swap of vm memory. Default false. # The behaviour is undefined if mem_prealloc is also set to true #enable_swap = true diff --git a/src/runtime/cli/config/configuration-qemu-virtiofs.toml.in b/src/runtime/cli/config/configuration-qemu-virtiofs.toml.in index 46a5ff0cab..129dc9963d 100644 --- a/src/runtime/cli/config/configuration-qemu-virtiofs.toml.in +++ b/src/runtime/cli/config/configuration-qemu-virtiofs.toml.in @@ -183,6 +183,12 @@ enable_vhost_user_store = @DEFENABLEVHOSTUSERSTORE@ # simulated block device nodes for vhost-user devices to live. vhost_user_store_path = "@DEFVHOSTUSERSTOREPATH@" +# Enable vIOMMU, default false +# Enabling this will result in the VM having a vIOMMU device +# This will also add the following options to the kernel's +# command line: intel_iommu=on,iommu=pt +#enable_iommu = true + # Enable file based guest memory support. The default is an empty string which # will disable this feature. In the case of virtio-fs, this is enabled # automatically and '/dev/shm' is used as the backing folder. diff --git a/src/runtime/cli/config/configuration-qemu.toml.in b/src/runtime/cli/config/configuration-qemu.toml.in index 46ce7d9b53..289ddde1a8 100644 --- a/src/runtime/cli/config/configuration-qemu.toml.in +++ b/src/runtime/cli/config/configuration-qemu.toml.in @@ -190,6 +190,12 @@ enable_vhost_user_store = @DEFENABLEVHOSTUSERSTORE@ # simulated block device nodes for vhost-user devices to live. vhost_user_store_path = "@DEFVHOSTUSERSTOREPATH@" +# Enable vIOMMU, default false +# Enabling this will result in the VM having a vIOMMU device +# This will also add the following options to the kernel's +# command line: intel_iommu=on,iommu=pt +#enable_iommu = true + # Enable file based guest memory support. The default is an empty string which # will disable this feature. In the case of virtio-fs, this is enabled # automatically and '/dev/shm' is used as the backing folder. diff --git a/src/runtime/pkg/katautils/config-settings.go.in b/src/runtime/pkg/katautils/config-settings.go.in index aaf78cc3f9..968d50a18a 100644 --- a/src/runtime/pkg/katautils/config-settings.go.in +++ b/src/runtime/pkg/katautils/config-settings.go.in @@ -38,6 +38,7 @@ const defaultBlockDeviceCacheNoflush bool = false const defaultEnableIOThreads bool = false const defaultEnableMemPrealloc bool = false const defaultEnableHugePages bool = false +const defaultEnableIOMMU bool = false const defaultFileBackedMemRootDir string = "" const defaultEnableSwap bool = false const defaultEnableDebug bool = false diff --git a/src/runtime/pkg/katautils/config.go b/src/runtime/pkg/katautils/config.go index cd946dadc0..0136c3c186 100644 --- a/src/runtime/pkg/katautils/config.go +++ b/src/runtime/pkg/katautils/config.go @@ -118,6 +118,7 @@ type hypervisor struct { MemPrealloc bool `toml:"enable_mem_prealloc"` HugePages bool `toml:"enable_hugepages"` VirtioMem bool `toml:"enable_virtio_mem"` + IOMMU bool `toml:"enable_iommu"` FileBackedMemRootDir string `toml:"file_mem_backend"` Swap bool `toml:"enable_swap"` Debug bool `toml:"enable_debug"` @@ -645,6 +646,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { VirtioFSExtraArgs: h.VirtioFSExtraArgs, MemPrealloc: h.MemPrealloc, HugePages: h.HugePages, + IOMMU: h.IOMMU, FileBackedMemRootDir: h.FileBackedMemRootDir, Mlock: !h.Swap, Debug: h.Debug, @@ -1086,6 +1088,7 @@ func GetDefaultHypervisorConfig() vc.HypervisorConfig { DefaultBridges: defaultBridgesCount, MemPrealloc: defaultEnableMemPrealloc, HugePages: defaultEnableHugePages, + IOMMU: defaultEnableIOMMU, FileBackedMemRootDir: defaultFileBackedMemRootDir, Mlock: !defaultEnableSwap, Debug: defaultEnableDebug, diff --git a/src/runtime/virtcontainers/hypervisor.go b/src/runtime/virtcontainers/hypervisor.go index 7b7be5baa3..a5e7bd25c2 100644 --- a/src/runtime/virtcontainers/hypervisor.go +++ b/src/runtime/virtcontainers/hypervisor.go @@ -358,6 +358,9 @@ type HypervisorConfig struct { // VirtioMem is used to enable/disable virtio-mem VirtioMem bool + // IOMMU specifies if the VM should have a vIOMMU + IOMMU bool + // Realtime Used to enable/disable realtime Realtime bool diff --git a/src/runtime/virtcontainers/pkg/annotations/annotations.go b/src/runtime/virtcontainers/pkg/annotations/annotations.go index 10ce7833e2..4544153a6e 100644 --- a/src/runtime/virtcontainers/pkg/annotations/annotations.go +++ b/src/runtime/virtcontainers/pkg/annotations/annotations.go @@ -148,6 +148,9 @@ const ( // HugePages is a sandbox annotation to specify if the memory should be pre-allocated from huge pages HugePages = kataAnnotHypervisorPrefix + "enable_hugepages" + // Iommu is a sandbox annotation to specify if the VM should have a vIOMMU device + IOMMU = kataAnnotHypervisorPrefix + "enable_iommu" + // FileBackedMemRootDir is a sandbox annotation to soecify file based memory backend root directory FileBackedMemRootDir = kataAnnotHypervisorPrefix + "file_mem_backend" diff --git a/src/runtime/virtcontainers/pkg/oci/utils.go b/src/runtime/virtcontainers/pkg/oci/utils.go index 40fdb94467..476f0d6603 100644 --- a/src/runtime/virtcontainers/pkg/oci/utils.go +++ b/src/runtime/virtcontainers/pkg/oci/utils.go @@ -539,6 +539,15 @@ func addHypervisorMemoryOverrides(ocispec specs.Spec, sbConfig *vc.SandboxConfig sbConfig.HypervisorConfig.HugePages = hugePages } + + if value, ok := ocispec.Annotations[vcAnnotations.IOMMU]; ok { + iommu, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("Error parsing annotation for iommu: Please specify boolean value 'true|false'") + } + + sbConfig.HypervisorConfig.IOMMU = iommu + } return nil } diff --git a/src/runtime/virtcontainers/pkg/oci/utils_test.go b/src/runtime/virtcontainers/pkg/oci/utils_test.go index 662095d957..c78f9aa888 100644 --- a/src/runtime/virtcontainers/pkg/oci/utils_test.go +++ b/src/runtime/virtcontainers/pkg/oci/utils_test.go @@ -771,6 +771,7 @@ func TestAddHypervisorAnnotations(t *testing.T) { ocispec.Annotations[vcAnnotations.EnableSwap] = "true" ocispec.Annotations[vcAnnotations.FileBackedMemRootDir] = "/dev/shm" ocispec.Annotations[vcAnnotations.HugePages] = "true" + ocispec.Annotations[vcAnnotations.IOMMU] = "true" ocispec.Annotations[vcAnnotations.BlockDeviceDriver] = "virtio-scsi" ocispec.Annotations[vcAnnotations.DisableBlockDeviceUse] = "true" ocispec.Annotations[vcAnnotations.EnableIOThreads] = "true" @@ -802,6 +803,7 @@ func TestAddHypervisorAnnotations(t *testing.T) { assert.Equal(config.HypervisorConfig.Mlock, false) assert.Equal(config.HypervisorConfig.FileBackedMemRootDir, "/dev/shm") assert.Equal(config.HypervisorConfig.HugePages, true) + assert.Equal(config.HypervisorConfig.IOMMU, true) assert.Equal(config.HypervisorConfig.BlockDeviceDriver, "virtio-scsi") assert.Equal(config.HypervisorConfig.DisableBlockDeviceUse, true) assert.Equal(config.HypervisorConfig.EnableIOThreads, true) diff --git a/src/runtime/virtcontainers/qemu.go b/src/runtime/virtcontainers/qemu.go index 7bca50f6e6..b6edfe6bf7 100644 --- a/src/runtime/virtcontainers/qemu.go +++ b/src/runtime/virtcontainers/qemu.go @@ -409,6 +409,13 @@ func (q *qemu) buildDevices(initrdPath string) ([]govmmQemu.Device, *govmmQemu.I } } + if q.config.IOMMU { + devices, err = q.arch.appendIOMMU(devices) + if err != nil { + return nil, nil, err + } + } + var ioThread *govmmQemu.IOThread if q.config.BlockDeviceDriver == config.VirtioSCSI { return q.arch.appendSCSIController(devices, q.config.EnableIOThreads) diff --git a/src/runtime/virtcontainers/qemu_amd64.go b/src/runtime/virtcontainers/qemu_amd64.go index 274b5f3f0d..c566297837 100644 --- a/src/runtime/virtcontainers/qemu_amd64.go +++ b/src/runtime/virtcontainers/qemu_amd64.go @@ -48,7 +48,6 @@ var kernelParams = []Param{ {"reboot", "k"}, {"console", "hvc0"}, {"console", "hvc1"}, - {"iommu", "off"}, {"cryptomgr.notests", ""}, {"net.ifnames", "0"}, {"pci", "lastbus=0"}, @@ -89,12 +88,31 @@ func newQemuArch(config HypervisorConfig) qemuArch { factory = true } + var qemuMachines = supportedQemuMachines + if config.IOMMU { + var q35QemuIOMMUOptions = "accel=kvm,kernel_irqchip=split" + + kernelParams = append(kernelParams, + Param{"intel_iommu", "on"}) + kernelParams = append(kernelParams, + Param{"iommu", "pt"}) + + for _, m := range qemuMachines { + if m.Type == QemuQ35 { + m.Options = q35QemuIOMMUOptions + } + } + } else { + kernelParams = append(kernelParams, + Param{"iommu", "off"}) + } + q := &qemuAmd64{ qemuArchBase: qemuArchBase{ machineType: machineType, memoryOffset: config.MemOffset, qemuPaths: qemuPaths, - supportedQemuMachines: supportedQemuMachines, + supportedQemuMachines: qemuMachines, kernelParamsNonDebug: kernelParamsNonDebug, kernelParamsDebug: kernelParamsDebug, kernelParams: kernelParams,