CHROMIUM: pkvm: x86: Use shadow IOMMU page tables for legacy IOMMU
Unlike scalable IOMMU, legacy IOMMU provides just one level of address
translation. So in the cases when the host itself uses address
translation for the given device (i.e. uses legacy IOMMU in
non-passthrough mode), pKVM needs to shadow the host's vIOMMU page
tables to ensure memory protection. This patch enables using shadow
IOMMU page tables in legacy mode, replacing our temporary hack using
vIOMMU page tables directly.
TODO: this patch still does not ensure memory protection, since it
does not implement syncing of shadow IOMMU page tables after a page is
donated. Memory protection _usually_ takes effect some time later, when
the (non-malicious) host itself triggers IOMMU sync. But since we do not
trust the host, memory protection is not guaranteed at all.
Performance considerations: as the host frequently flushes IOTLB when
mapping/unmapping its DMA buffers, the shadow tables sync in pKVM during
IOTLB flush emulation has high impact on performance. Fortunately the
host typically uses page-selective IOTLB flushes. This patch implements
two basic optimizations eliminating the biggest bottlenecks:
1. Obvious one: for a page-selective flush, walk shadow page table
entries for the needed pages only.
2. For a page-selective or a domain-selective flush, walk root & context
table entries for the needed BDFs only (i.e. for the ptdevs with the
matching DID registered earlier), not the entire BDF space.
Signed-off-by: Dmytro Maluka <dmy@semihalf.com>
(cherry-picked from commit b4a85afa3a6d25cf2d9bb021ff81106782da96ed ->
https://github.com/intel-staging/pKVM-IA)
BUG=b:255568785
TEST=1. Check if wifi works in ChromeOS with good performance. (Wifi is
an untrusted device so ChromeOS uses IOMMU address translation for it.)
2. Start a protected VM and verify its DMA protection from a ChromeOS's
untrusted device (e.g. using CL:4043523 + CL:4123732 + CL:4123733).
3. Pass-thru iwlwifi to a protected VM, check if wifi works in the VM.
4. Stop this protected VM and start it again.
5. Stop this protected VM, bind iwlwifi back to ChromeOS driver and
check if wifi works in ChromeOS.
6. Start this protected VM with iwlwifi + a few more trusted and/or
untrusted devices passed-thru, check if wifi still works in the VM and
other devices show up in the VM's lspci.
7. Start this protected VM with iwlwifi + a few more protected and/or
unprotected VMs with passed-thru devices in parallel.
Change-Id: Ibfd38d7da2c545204be573eca566d356027e0fdf
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/4329719
Reviewed-by: Tomasz Nowicki <tnowicki@google.com>
Commit-Queue: Dmytro Maluka <dmaluka@google.com>
Tested-by: Dmytro Maluka <dmaluka@google.com>
6 files changed