This series contains preliminary work to enable Secure Virtual Machines
(SVM) on powerpc. SVMs request to be migrated to secure memory very early in
the boot process (in prom_init()), so by default all of their memory is
inaccessible to the hypervisor. There is an ultravisor call that the VM can
use to request certain pages to be made accessible (aka shared).
The objective of these patches is to have the guest perform this request for
buffers that need to be shared with the hypervisor, such as the LPPACAs, the
SWIOTLB buffer and the Debug Trace Log. This work is incomplete: there are
surely other memory regions that need to be made accessible, but I'm posting
it early to get comments on whether the approach being taken is appropriate.
It should be applied on top of the generic virtio DMA API rework series
posted earlier, which adds a platform hook to override any arch based DMA
API operations for any virtio device:
https://lists.ozlabs.org/pipermail/linuxppc-dev/2018-July/175994.html
I'm aware that changes need to be made to the patch series above, but IIUC
it depends on upcoming virtio cleanup from Christoph Hellwig so for now the
patch series above will be used as a stepping stone for this series.
This code has been tested with virtio block, net and scsi devices with and
without VIRTIO_F_IOMMU_PLATFORM flag. Please let me know what you think.
For now I am testing on a regular guest with a couple of patches on top
forcing is_svm_platform() to always return true and adding debug messages to
confirm that mem_convert_shared() is being called in the expected places.
These are the commands I'm using to start up the guest:
Without VIRTIO_F_IOMMU_PLATFORM:
qemu-system-ppc64 \
-enable-kvm \
-kernel /home/bauermann/src/linux/arch/powerpc/boot/zImage \
-append "root=PARTUUID=e550ad6f-05 ro" \
-machine pseries-2.6 \
-m 8G \
-smp 2 \
-serial mon:stdio \
-nographic \
-nodefaults \
-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x4 \
-drive file=/home/bauermann/VMs/svm.qcow2,format=qcow2,if=none,id=drive-scsi0-0-0-0 \
-device scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 \
-drive file=/home/bauermann/VMs/svm-blk.qcow2,format=qcow2,if=none,id=drive-virtio-disk0 \
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0 \
-device virtio-net,netdev=hostnet0,id=net0,mac=52:54:00:96:70:1f \
-netdev user,id=hostnet0 \
-set netdev.hostnet0.hostfwd=tcp::42022-:22
With VIRTIO_F_IOMMU_PLATFORM. Same as above plus some -global options so
that the virtio devices use the modern interface rather than the
transitional one:
qemu-system-ppc64 \
-enable-kvm \
-kernel /home/bauermann/src/linux/arch/powerpc/boot/zImage \
-append "root=PARTUUID=e550ad6f-05 ro" \
-machine pseries-2.6 \
-m 8G \
-smp 2 \
-serial mon:stdio \
-nographic \
-nodefaults \
-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x4 \
-drive file=/home/bauermann/VMs/svm.qcow2,format=qcow2,if=none,id=drive-scsi0-0-0-0 \
-device scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 \
-drive file=/home/bauermann/VMs/svm-blk.qcow2,format=qcow2,if=none,id=drive-virtio-disk0 \
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0 \
-device virtio-net,netdev=hostnet0,id=net0,mac=52:54:00:96:70:1f \
-netdev user,id=hostnet0 \
-set netdev.hostnet0.hostfwd=tcp::42022-:22 \
-global virtio-blk-pci.iommu_platform=true \
-global virtio-blk-pci.disable-legacy=on \
-global virtio-blk-pci.disable-modern=off \
-global virtio-net-pci.iommu_platform=true \
-global virtio-net-pci.disable-legacy=on \
-global virtio-net-pci.disable-modern=off \
-global virtio-scsi-pci.iommu_platform=true \
-global virtio-scsi-pci.disable-legacy=on \
-global virtio-scsi-pci.disable-modern=off
The code was tested with a couple of other permutations where one virtio
device has the flag VIRTIO_F_IOMMU_PLATFORM and others don't. Please suggest
some other scenarios which need to be tested as well.
Anshuman Khandual (10):
powerpc/svm: Detect Secure Virtual Machine (SVM) platform
powerpc/svm: Select CONFIG_DMA_DIRECT_OPS and CONFIG_SWIOTLB
powerpc/svm: Add memory conversion (shared/secure) helper functions
powerpc/svm: Convert SWIOTLB buffers to shared memory
powerpc/svm: Don't release SWIOTLB buffers on secure guests
powerpc/svm: Use SWIOTLB DMA API for all virtio devices
powerpc/svm: Use shared memory for Debug Trace Log (DTL)
powerpc/svm: Use shared memory for LPPACA structures
powerpc/svm: Force the use of bounce buffers
powerpc/svm: Increase SWIOTLB buffer size
Thiago Jung Bauermann (1):
powerpc: Add and use LPPACA_SIZE constant
arch/powerpc/Kconfig | 22 ++++++++
arch/powerpc/include/asm/mem_encrypt.h | 19 +++++++
arch/powerpc/include/asm/reg.h | 3 ++
arch/powerpc/include/asm/svm.h | 26 +++++++++
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/paca.c | 41 ++++++++++++--
arch/powerpc/kernel/svm.c | 99 ++++++++++++++++++++++++++++++++++
arch/powerpc/platforms/pseries/iommu.c | 6 ++-
arch/powerpc/platforms/pseries/setup.c | 5 +-
kernel/dma/swiotlb.c | 5 ++
10 files changed, 221 insertions(+), 6 deletions(-)
create mode 100644 arch/powerpc/include/asm/mem_encrypt.h
create mode 100644 arch/powerpc/include/asm/svm.h
create mode 100644 arch/powerpc/kernel/svm.c
From: Anshuman Khandual <redacted>
A guest requests to be moved to secure memory early at the kernel
startup (in prom_init). Define a flag that can be easily checked by other
parts of the kernel so that they can set things up accordingly. This is
done by checking the MSR(S) bit, which is always set for secure VMs.
Also add a new config option CONFIG_PPC_SVM to wrap all these code to
prevent it from being executed from non subscribing platforms. This SVM
platform detection is applicable only to guest kernels that will run under
an Ultravisor as a secure guest.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Ram Pai <redacted>
Signed-off-by: Sukadev Bhattiprolu <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/Kconfig | 11 +++++++++++
arch/powerpc/include/asm/reg.h | 3 +++
arch/powerpc/include/asm/svm.h | 22 ++++++++++++++++++++++
3 files changed, 36 insertions(+)
@@ -440,6 +440,17 @@ config MATH_EMULATION_HW_UNIMPLEMENTEDendchoice+configPPC_SVM+bool"Secure virtual machine (SVM) support for POWERPC"+defaultn+depends onPPC_PSERIES+help+SupportsecureguestsonPOWERPC.TherearecertainPOWERplatforms+whichsupportsecureguestswiththehelpofanUltravisorexecuting+belowthehypervisorlayer.Thisenablesthesupportforthoseguests.++Ifunsure,say"N".+configPPC_TRANSACTIONAL_MEMbool"Transactional Memory support for POWERPC"depends onPPC_BOOK3S_64
From: Anshuman Khandual <redacted>
Ultravisor based secure guest platforms will use generic SWIOTLB DMA API
(i.e swiotlb_dma_ops structure) available under the CONFIG_DMA_DIRECT_OPS
config. Also base CONFIG_SWIOTLB needs to be explicitly selected as well.
Select both these config options on powerpc server platforms with secure
guest support.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/Kconfig | 2 ++
1 file changed, 2 insertions(+)
From: Anshuman Khandual <redacted>
Even though SWIOTLB slab gets allocated and initialized on each powerpc
platform with swiotlb_init(), it gets released away again on all server
platforms because ppc_swiotlb_enable variable never gets set. Secure
guests would require SWIOTLB DMA API support for virtio bounce buffering
purpose. Hence retain the allocated buffer by setting ppc_swiotlb_enable
variable for secure guests on Ultravisor platforms.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/kernel/svm.c | 1 +
1 file changed, 1 insertion(+)
From: Anshuman Khandual <redacted>
Secure guest memory (GPA range) is isolated and inaccessible from the host.
But virtio ring transactions require the back end drivers to process
incoming scatter gather buffers which require their access in host. Hence a
portion of guest memory can be converted to shared memory and all buffers
need to be bounced into the pool before being passed on to the host.
SWIOTLB buffers can be pre-allocated and converted as shared memory during
early boot. Generic SWIOTLB DMA API (swiotlb_dma_ops) callbacks can be used
to bounce each incoming scatter gather I/O buffer addresses into this pool
of shared memory before being passed on to the host. All virtio devices on
secure guest platform need to use generic SWIOTLB DMA API. Utilize the new
virtio core platform hook platform_override_dma_ops() to achieve this.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/platforms/pseries/iommu.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
From: Anshuman Khandual <redacted>
On Ultravisor platform kmem_cache for DTL buffers must use a constructor
function which converts the underlying buddy allocated SLUB cache pages
into shared memory so that they are accessible to the hypervisor.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/include/asm/svm.h | 1 +
arch/powerpc/kernel/svm.c | 30 ++++++++++++++++++++++++++++++
arch/powerpc/platforms/pseries/setup.c | 5 ++++-
3 files changed, 35 insertions(+), 1 deletion(-)
@@ -66,3 +66,33 @@ int set_memory_decrypted(unsigned long addr, int numpages)return0;}++/* There's one dispatch log per CPU. */+#define NR_DTL_PAGE (DISPATCH_LOG_BYTES * CONFIG_NR_CPUS / PAGE_SIZE)++staticstructpage*dtl_page_store[NR_DTL_PAGE];+staticlongdtl_nr_pages;++staticboolis_dtl_page_shared(structpage*page)+{+longi;++for(i=0;i<dtl_nr_pages;i++)+if(dtl_page_store[i]==page)+returntrue;++returnfalse;+}++voiddtl_cache_ctor(void*addr)+{+unsignedlongpfn=PHYS_PFN(__pa(addr));+structpage*page=pfn_to_page(pfn);++if(!is_dtl_page_shared(page)){+dtl_page_store[dtl_nr_pages]=page;+dtl_nr_pages++;+WARN_ON(dtl_nr_pages>=NR_DTL_PAGE);+mem_convert_shared(pfn,PAGE_SIZE);+}+}
@@ -288,8 +289,10 @@ static inline int alloc_dispatch_logs(void)staticintalloc_dispatch_log_kmem_cache(void){+void(*ctor)(void*)=is_svm_platform()?dtl_cache_ctor:NULL;+dtl_cache=kmem_cache_create("dtl",DISPATCH_LOG_BYTES,-DISPATCH_LOG_BYTES,0,NULL);+DISPATCH_LOG_BYTES,0,ctor);if(!dtl_cache){pr_warn("Failed to create dispatch trace log buffer cache\n");pr_warn("Stolen time statistics will be unreliable\n");
From: Anshuman Khandual <redacted>
LPPACA structures need to be shared with the host. Hence they need to be on
shared memory. Instead of allocating individual chunks of memory for given
structure from memblock, a contiguous chunk of memory is allocated and then
converted into shared memory. Subsequent allocation requests will come from
the contiguous chunk which will be always shared memory for all structures.
While we were able to use a kmem_cache constructor for the Debug Trace Log,
LPPACAs are allocated very early in the boot process (before SLUB is
available) so we need to use a simpler scheme here.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/kernel/paca.c | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
From: Anshuman Khandual <redacted>
SWIOTLB checks range of incoming CPU addresses to be bounced and see if the
device can access it through it's DMA window without requiring bouncing. In
such cases it just chooses to skip bouncing. But for cases like secure
guests on powerpc platform all addresses need to be bounced into the shared
pool of memory because the host cannot access it otherwise. Hence the need
to do the bouncing is not related to device's DMA window. Hence force the
use of bouncing by setting the swiotlb_force variable on secure guests.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/kernel/svm.c | 1 +
1 file changed, 1 insertion(+)
From: Christoph Hellwig <hch@lst.de> Date: 2018-08-24 05:59:00
On Thu, Aug 23, 2018 at 11:59:32PM -0300, Thiago Jung Bauermann wrote:
quoted hunk
From: Anshuman Khandual <redacted>
SWIOTLB checks range of incoming CPU addresses to be bounced and see if the
device can access it through it's DMA window without requiring bouncing. In
such cases it just chooses to skip bouncing. But for cases like secure
guests on powerpc platform all addresses need to be bounced into the shared
pool of memory because the host cannot access it otherwise. Hence the need
to do the bouncing is not related to device's DMA window. Hence force the
use of bouncing by setting the swiotlb_force variable on secure guests.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/kernel/svm.c | 1 +
1 file changed, 1 insertion(+)
Hello Christoph,
Thanks for your quick review.
Christoph Hellwig [off-list ref] writes:
On Thu, Aug 23, 2018 at 11:59:32PM -0300, Thiago Jung Bauermann wrote:
quoted
From: Anshuman Khandual <redacted>
SWIOTLB checks range of incoming CPU addresses to be bounced and see if the
device can access it through it's DMA window without requiring bouncing. In
such cases it just chooses to skip bouncing. But for cases like secure
guests on powerpc platform all addresses need to be bounced into the shared
pool of memory because the host cannot access it otherwise. Hence the need
to do the bouncing is not related to device's DMA window. Hence force the
use of bouncing by setting the swiotlb_force variable on secure guests.
Signed-off-by: Anshuman Khandual <redacted>
Signed-off-by: Thiago Jung Bauermann <redacted>
---
arch/powerpc/kernel/svm.c | 1 +
1 file changed, 1 insertion(+)
@@ -17,6 +17,7 @@ static int __init init_svm(void)return0;ppc_swiotlb_enable=1;+swiotlb_force=SWIOTLB_FORCE;swiotlb_update_mem_attributes();
This needs a comment.
Good point. Will add one.
If in the new scheme of things (with bus_dma_mask?) dma_capable() on a
virtio device running in a secure guest returns false, then this patch
becomes unnecessary and can be dropped.
--
Thiago Jung Bauermann
IBM Linux Technology Center
@@ -457,6 +457,11 @@ config PPC_SVMIfunsure,say"N".+configSWIOTLB_DEFAULT_SIZE+int"Size of Software I/O TLB buffer (in MiB)"+default"1024"+depends onPPC_SVM+configPPC_TRANSACTIONAL_MEMbool"Transactional Memory support for POWERPC"depends onPPC_BOOK3S_64