KVM: s390: Add support for protected VMs
Subsystems (5)
Janosch Frank
maintainercover KVM: s390: Add support for protected VMs
Protected VMs (PVM) are KVM VMs, where KVM can't access the VM's state like guest memory and guest registers anymore. Instead the PVMs are mostly managed by a new entity called Ultravisor (UV), which provides an API, so KVM and the PV can request management actions.
PVMs are encrypted at rest and protected from hypervisor access while running. They switch from a normal operation into protected mode, so we can still use the standard boot process to load a encrypted blob and then move it into protected mode.
Rebooting is only possible by passing through the unprotected/normal mode and switching to protected again.
All patches are in the protvirt branch of the korg s390 kvm git.
Claudio will present the technology at his presentation at KVM Forum 2019.
Christian Borntraeger (1):
KVM: s390: protvirt: Add SCLP handling
Claudio Imbrenda (2):
KVM: s390: add missing include in gmap.h
KVM: s390: protvirt: Implement on-demand pinning
Janosch Frank (27):
DOCUMENTATION: protvirt: Protected virtual machine introduction
KVM: s390: protvirt: Add initial lifecycle handling
s390: KVM: Export PV handle to gmap
s390: UV: Add import and export to UV library
KVM: s390: protvirt: Secure memory is not mergeable
DOCUMENTATION: protvirt: Interrupt injection
KVM: s390: protvirt: Handle SE notification interceptions
DOCUMENTATION: protvirt: Instruction emulation
KVM: s390: protvirt: Handle spec exception loops
KVM: s390: protvirt: Add new gprs location handling
KVM: S390: protvirt: Introduce instruction data area bounce buffer
KVM: S390: protvirt: Instruction emulation
KVM: s390: protvirt: Make sure prefix is always protected
KVM: s390: protvirt: Write sthyi data to instruction data area
KVM: s390: protvirt: STSI handling
KVM: s390: protvirt: Only sync fmt4 registers
KVM: s390: protvirt: SIGP handling
KVM: s390: protvirt: Add program exception injection
KVM: s390: protvirt: Sync pv state
DOCUMENTATION: protvirt: Diag 308 IPL
KVM: s390: protvirt: Add diag 308 subcode 8 - 10 handling
KVM: s390: protvirt: UV calls diag308 0, 1
KVM: s390: Introduce VCPU reset IOCTL
KVM: s390: protvirt: Report CPU state to Ultravisor
KVM: s390: Fix cpu reset local IRQ clearing
KVM: s390: protvirt: Support cmd 5 operation state
KVM: s390: protvirt: Add UV debug trace
Michael Mueller (4):
KVM: s390: protvirt: Add interruption injection controls
KVM: s390: protvirt: Implement interruption injection
KVM: s390: protvirt: Add machine-check interruption injection controls
KVM: s390: protvirt: Implement machine-check interruption injection
Vasily Gorbik (3):
s390/protvirt: introduce host side setup s390/protvirt: add ultravisor initialization
s390: add (non)secure page access exceptions handlers
.../admin-guide/kernel-parameters.txt | 5 + Documentation/virtual/kvm/s390-pv-boot.txt | 62 +++ Documentation/virtual/kvm/s390-pv.txt | 97 ++++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +- arch/s390/include/asm/gmap.h | 4 + arch/s390/include/asm/kvm_host.h | 103 +++- arch/s390/include/asm/uv.h | 255 +++++++++- arch/s390/include/uapi/asm/kvm.h | 5 +- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/pgm_check.S | 4 +- arch/s390/kernel/setup.c | 7 +- arch/s390/kernel/uv.c | 121 +++++ arch/s390/kvm/Kconfig | 9 + arch/s390/kvm/Makefile | 2 +- arch/s390/kvm/diag.c | 7 + arch/s390/kvm/intercept.c | 91 +++- arch/s390/kvm/interrupt.c | 208 ++++++-- arch/s390/kvm/kvm-s390.c | 476 +++++++++++++++--- arch/s390/kvm/kvm-s390.h | 58 +++ arch/s390/kvm/priv.c | 9 +- arch/s390/kvm/pv.c | 317 ++++++++++++ arch/s390/mm/fault.c | 64 +++ arch/s390/mm/gmap.c | 28 +- include/uapi/linux/kvm.h | 42 ++ 25 files changed, 1848 insertions(+), 149 deletions(-) create mode 100644 Documentation/virtual/kvm/s390-pv-boot.txt create mode 100644 Documentation/virtual/kvm/s390-pv.txt create mode 100644 arch/s390/kernel/uv.c create mode 100644 arch/s390/kvm/pv.c
Signature · 1 line
2.20.1
Janosch Frank
maintainerRFC 1/37 DOCUMENTATION: protvirt: Protected virtual machine introduction
Introduction to Protected VMs.
--- Documentation/virtual/kvm/s390-pv.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Documentation/virtual/kvm/s390-pv.txt
Documentation/virtual/kvm/s390-pv.txt new file +23 -0
@@ -0,0 +1,23 @@ +Ultravisor and Protected VMs +=========================== + +Summary: + +Protected VMs (PVM) are KVM VMs, where KVM can't access the VM's state +like guest memory and guest registers anymore. Instead the PVMs are +mostly managed by a new entity called Ultravisor (UV), which provides +an API, so KVM and the PVM can request management actions. + +Each guest starts in the non-protected mode and then transitions into +protected mode. On transition KVM registers the guest and its VCPUs +with the Ultravisor and prepares everything for running it. + +The Ultravisor will secure and decrypt the guest's boot memory +(i.e. kernel/initrd). It will safeguard state changes like VCPU +starts/stops and injected interrupts while the guest is running. + +As access to the guest's state, like the SIE state description is +normally needed to be able to run a VM, some changes have been made in +SIE behavior and fields have different meaning for a PVM. SIE exits +are minimized as much as possible to improve speed and reduce exposed +guest state.
Signature · 1 line
2.20.1
Re: [RFC 01/37] DOCUMENTATION: protvirt: Protected virtual machine introduction
Quoted 23 lines · Janosch Frank
Introduction to Protected VMs.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Documentation/virtual/kvm/s390-pv.txtDocumentation/virtual/kvm/s390-pv.txt new file +9
-0@@ -0,0 +1,23 @@ +Ultravisor and Protected VMs +=========================== + +Summary: + +Protected VMs (PVM) are KVM VMs, where KVM can't access the VM's state +like guest memory and guest registers anymore. Instead the PVMs are +mostly managed by a new entity called Ultravisor (UV), which provides +an API, so KVM and the PVM can request management actions.
Documentation/virtual/kvm/s390-pv.txt line 19
Quoted 10 lines
Documentation/virtual/kvm/s390-pv.txt new file +10
-0+ +Each guest starts in the non-protected mode and then transitions into +protected mode. On transition KVM registers the guest and its VCPUs +with the Ultravisor and prepares everything for running it. + +The Ultravisor will secure and decrypt the guest's boot memory +(i.e. kernel/initrd). It will safeguard state changes like VCPU +starts/stops and injected interrupts while the guest is running. + +As access to the guest's state, like the SIE state description is
not a native speaker, but do we need a , /here\ ?
Documentation/virtual/kvm/s390-pv.txt line 23
Quoted 6 lines
Documentation/virtual/kvm/s390-pv.txt new file +4
-0+normally needed to be able to run a VM, some changes have been made in +SIE behavior and fields have different meaning for a PVM. SIE exits +are minimized as much as possible to improve speed and reduce exposed +guest state.
After review we could merge all documentation patches into one, if we want.
Re: [RFC 01/37] DOCUMENTATION: protvirt: Protected virtual machine introduction
In reply to Janosch FrankDocumentation/virtual/kvm/s390-pv.txt
Quoted 13 lines · On Thu, 24 Oct 2019 07:40:23 -0400 Janosch Frank <[email protected]> wrote:
Introduction to Protected VMs.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Documentation/virtual/kvm/s390-pv.txtDocumentation/virtual/kvm/s390-pv.txt new file +0
-0
This should be under /virt/, I think. Also, maybe start out with RST already for new files?
Documentation/virtual/kvm/s390-pv.txt line 7
Quoted 8 lines
Documentation/virtual/kvm/s390-pv.txt new file +7
-0@@ -0,0 +1,23 @@ +Ultravisor and Protected VMs +=========================== + +Summary: + +Protected VMs (PVM) are KVM VMs, where KVM can't access the VM's state +like guest memory and guest registers anymore. Instead the PVMs are
s/Instead/Instead,/
Documentation/virtual/kvm/s390-pv.txt line 9
Quoted 2 lines
Documentation/virtual/kvm/s390-pv.txt new file +2
-0+mostly managed by a new entity called Ultravisor (UV), which provides +an API, so KVM and the PVM can request management actions.
Hm...
"The UV provides an API (both for guests and hypervisors), where PVMs and KVM can request management actions." ?
Documentation/virtual/kvm/s390-pv.txt line 11
Quoted 2 lines
Documentation/virtual/kvm/s390-pv.txt new file +2
-0+ +Each guest starts in the non-protected mode and then transitions into
"and then may make a request to transition into protected mode" ?
Documentation/virtual/kvm/s390-pv.txt line 19
Quoted 8 lines
Documentation/virtual/kvm/s390-pv.txt new file +8
-0+protected mode. On transition KVM registers the guest and its VCPUs +with the Ultravisor and prepares everything for running it. + +The Ultravisor will secure and decrypt the guest's boot memory +(i.e. kernel/initrd). It will safeguard state changes like VCPU +starts/stops and injected interrupts while the guest is running. + +As access to the guest's state, like the SIE state description is
"such as the SIE state description," ?
Quoted 4 lines
Documentation/virtual/kvm/s390-pv.txt new file +4
-0+normally needed to be able to run a VM, some changes have been made in +SIE behavior and fields have different meaning for a PVM. SIE exits +are minimized as much as possible to improve speed and reduce exposed +guest state.
Janosch Frank
maintainerRe: [RFC 01/37] DOCUMENTATION: protvirt: Protected virtual machine introduction
Quoted 20 lines · Cornelia Huck
Documentation/virtual/kvm/s390-pv.txt
Quoted 13 lines · On Thu, 24 Oct 2019 07:40:23 -0400 Janosch Frank <[email protected]> wrote:
Introduction to Protected VMs.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Documentation/virtual/kvm/s390-pv.txtDocumentation/virtual/kvm/s390-pv.txt new file +0
-0This should be under /virt/, I think. Also, maybe start out with RST already for new files?
Quoted 10 lines
Documentation/virtual/kvm/s390-pv.txt line 7
Quoted 8 lines
Documentation/virtual/kvm/s390-pv.txt new file +7
-0@@ -0,0 +1,23 @@ +Ultravisor and Protected VMs +=========================== + +Summary: + +Protected VMs (PVM) are KVM VMs, where KVM can't access the VM's state +like guest memory and guest registers anymore. Instead the PVMs ares/Instead/Instead,/
Fixed
Quoted 8 lines
Documentation/virtual/kvm/s390-pv.txt line 9
Quoted 3 lines
Documentation/virtual/kvm/s390-pv.txt new file +2
-0+mostly managed by a new entity called Ultravisor (UV), which provides +an API, so KVM and the PVM can request management actions.Hm...
"The UV provides an API (both for guests and hypervisors), where PVMs and KVM can request management actions." ?
I applied your proposal, but removed the part in the brace, as it is obvious from the words that follow.
Quoted 5 lines
Documentation/virtual/kvm/s390-pv.txt line 11
Quoted 3 lines
Documentation/virtual/kvm/s390-pv.txt new file +2
-0+ +Each guest starts in the non-protected mode and then transitions into"and then may make a request to transition into protected mode" ?
Sure
Quoted 17 lines
Documentation/virtual/kvm/s390-pv.txt line 19
Quoted 9 lines
Documentation/virtual/kvm/s390-pv.txt new file +8
-0+protected mode. On transition KVM registers the guest and its VCPUs +with the Ultravisor and prepares everything for running it. + +The Ultravisor will secure and decrypt the guest's boot memory +(i.e. kernel/initrd). It will safeguard state changes like VCPU +starts/stops and injected interrupts while the guest is running. + +As access to the guest's state, like the SIE state description is"such as the SIE state description," ?
Quoted 4 lines
Documentation/virtual/kvm/s390-pv.txt new file +4
-0+normally needed to be able to run a VM, some changes have been made in +SIE behavior and fields have different meaning for a PVM. SIE exits +are minimized as much as possible to improve speed and reduce exposed +guest state.
Janosch Frank
maintainerRFC 2/37 s390/protvirt: introduce host side setup
In reply to Janosch FrankFrom: Vasily Gorbik <[email protected]>
Introduce KVM_S390_PROTECTED_VIRTUALIZATION_HOST kbuild option for protected virtual machines hosting support code.
Add "prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.
Extend ultravisor info definitions and expose it via uv_info struct filled in during startup.
--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 arch/s390/kernel/uv.c
Documentation/admin-guide/kernel-parameters.txt +5 -0
@@ -3693,6 +3693,11 @@ before loading. See Documentation/admin-guide/blockdev/ramdisk.rst. + prot_virt= [S390] enable hosting protected virtual machines + isolated from the hypervisor (if hardware supports + that). + Format: <bool> + psi= [KNL] Enable or disable pressure stall information tracking. Format: <bool>
arch/s390/boot/Makefile +1 -1
@@ -37,7 +37,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char obj-y := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o obj-y += version.o pgm_check_info.o ctype.o text_dma.o -obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) += uv.o +obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST)) += uv.o obj-$(CONFIG_RELOCATABLE) += machine_kexec_reloc.o obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o targets := bzImage startup.a section_cmp.boot.data section_cmp.boot.preserved.data $(obj-y)
arch/s390/boot/uv.c +19 -1
@@ -3,7 +3,12 @@#include <asm/facility.h> #include <asm/sections.h> +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST int __bootdata_preserved (prot_virt_guest ); +#endif +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +struct uv_info __bootdata_preserved (uv_info ); +#endif void uv_query_info (void ) {
@@ -18,7 +23,20 @@ void uv_query_info(void)if (uv_call (0 , (uint64_t )&uvcb))return ; -if (test_bit_inv (BIT_UVC_CMD_SET_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list) && +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST )) { +memcpy (uv_info.inst_calls_list, uvcb.inst_calls_list,sizeof (uv_info.inst_calls_list)); + uv_info.uv_base_stor_len = uvcb.uv_base_stor_len; + uv_info.guest_base_stor_len = uvcb.conf_base_phys_stor_len; + uv_info.guest_virt_base_stor_len = uvcb.conf_base_virt_stor_len; + uv_info.guest_virt_var_stor_len = uvcb.conf_virt_var_stor_len; + uv_info.guest_cpu_stor_len = uvcb.cpu_stor_len; + uv_info.max_sec_stor_addr =ALIGN (uvcb.max_guest_stor_addr,PAGE_SIZE ); + uv_info.max_num_sec_conf = uvcb.max_num_sec_conf; + uv_info.max_guest_cpus = uvcb.max_guest_cpus; + } + +if (IS_ENABLED (CONFIG_PROTECTED_VIRTUALIZATION_GUEST ) && +test_bit_inv (BIT_UVC_CMD_SET_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list) &&test_bit_inv (BIT_UVC_CMD_REMOVE_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list)) prot_virt_guest =1 ; }
arch/s390/include/asm/uv.h +43 -3
70 lines not on this page · raw message
arch/s390/kernel/Makefile +1 -0
@@ -78,6 +78,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_diag.o obj-$(CONFIG_TRACEPOINTS) += trace.o +obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST)) += uv.o # vdso obj-y += vdso64/
arch/s390/kernel/setup.c +0 -4
@@ -92,10 +92,6 @@ char elf_platform[ELF_PLATFORM_SIZE];unsigned long int_hwcap =0 ; -#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST -int __bootdata_preserved (prot_virt_guest ); -#endif -int __bootdata (noexec_disabled );int __bootdata (memory_end_set );unsigned long __bootdata (memory_end );
arch/s390/kernel/uv.c new file +48 -0
48 lines not on this page · raw message
arch/s390/kvm/Kconfig +9 -0
@@ -55,6 +55,15 @@ config KVM_S390_UCONTROL If unsure, say N. +config KVM_S390_PROTECTED_VIRTUALIZATION_HOST + bool "Protected guests execution support" + depends on KVM + ---help--- + Support hosting protected virtual machines isolated from the + hypervisor. + + If unsure, say Y. + # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. source "drivers/vhost/Kconfig"
Signature · 1 line
2.20.1
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 29 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-)create mode 100644
arch/s390/kernel/uv.cDocumentation/admin-guide/kernel-parameters.txt +0
-0
Documentation/admin-guide/kernel-parameters.txt line 3699
Quoted 7 lines
Documentation/admin-guide/kernel-parameters.txt +4
-0@@ -3693,6 +3693,11 @@ before loading. See Documentation/admin-guide/blockdev/ramdisk.rst. + prot_virt= [S390] enable hosting protected virtual machines + isolated from the hypervisor (if hardware supports + that). + Format: <bool>
Isn't that a virt driver detail that should come in via KVM module parameters? I don't see quite yet why this has to be a kernel parameter (that can be changed at runtime).
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 33 lines · David Hildenbrand
Quoted 32 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-)create mode 100644
arch/s390/kernel/uv.cDocumentation/admin-guide/kernel-parameters.txt +0
-0@@ -3693,6 +3693,11 @@ before loading. See Documentation/admin-guide/blockdev/ramdisk.rst.
Quoted 9 lines
Documentation/admin-guide/kernel-parameters.txt line 3699
Quoted 4 lines
Documentation/admin-guide/kernel-parameters.txt +4
-0+ prot_virt= [S390] enable hosting protected virtual machines + isolated from the hypervisor (if hardware supports + that). + Format: <bool>Isn't that a virt driver detail that should come in via KVM module parameters? I don't see quite yet why this has to be a kernel parameter (that can be changed at runtime).
I was confused by "runtime" in "which controls if the kernel protected VMs support is enabled at runtime"
So this can't be changed at runtime. Can you clarify why kvm can't initialize that when loaded and why we need a kernel parameter?
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 43 lines · David Hildenbrand
Quoted 25 lines · David Hildenbrand
Quoted 24 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>---
.../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++8 files changed, 126 insertions(+), 9 deletions(-)create mode 100644
arch/s390/kernel/uv.cQuoted 16 lines
Quoted 11 lines
Documentation/admin-guide/kernel-parameters.txt +0
-0@@ -3693,6 +3693,11 @@before loading.
SeeDocumentation/admin-guide/blockdev/ramdisk.rst. + prot_virt= [S390] enable hosting protected virtual machines + isolated from the hypervisor (if hardware supports + that).
+ Format: <bool>Isn't that a virt driver detail that should come in via KVM module parameters? I don't see quite yet why this has to be a kernel parameter (that can be changed at runtime).
Quoted 3 lines
I was confused by "runtime" in "which controls if the kernel protected VMs support is enabled at runtime"
So this can't be changed at runtime. Can you clarify why kvm can't initialize that when loaded and why we need a kernel parameter?
We have to do the opt-in very early for several reasons:
- we have to donate a potentially largish contiguous (in real) range of memory to the ultravisor
- The opt-in will also disable some features in the host that could affect guest integrity (e.g. time sync via STP to avoid the host messing with the guest time stepping). Linux is not happy when you remove features at a later point in time
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 46 lines · Christian Borntraeger
Quoted 43 lines · David Hildenbrand
Quoted 41 lines · David Hildenbrand
Quoted 29 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-)create mode 100644
arch/s390/kernel/uv.cDocumentation/admin-guide/kernel-parameters.txt +0
-0Documentation/admin-guide/kernel-parameters.txt line 3698
Quoted 6 lines
Documentation/admin-guide/kernel-parameters.txt +3
-0@@ -3693,6 +3693,11 @@ before loading. See Documentation/admin-guide/blockdev/ramdisk.rst. + prot_virt= [S390] enable hosting protected virtual machines + isolated from the hypervisor (if hardware supports + that). + Format: <bool>Isn't that a virt driver detail that should come in via KVM module parameters? I don't see quite yet why this has to be a kernel parameter (that can be changed at runtime).
Quoted 6 lines
Quoted 3 lines
I was confused by "runtime" in "which controls if the kernel protected VMs support is enabled at runtime"
So this can't be changed at runtime. Can you clarify why kvm can't initialize that when loaded and why we need a kernel parameter?
We have to do the opt-in very early for several reasons:
- we have to donate a potentially largish contiguous (in real) range of memory to the ultravisor
If you'd be using CMA (or alloc_contig_pages() with less guarantees) you could be making good use of the memory until you actually start an encrypted guest.
I can see that using the memblock allocator early is easier. But you waste "largish ... range of memory" even if you never run VMs.
Maybe something to work on in the future.
Quoted 3 lines
- The opt-in will also disable some features in the host that could affect guest integrity (e.g. time sync via STP to avoid the host messing with the guest time stepping). Linux is not happy when you remove features at a later point in time
At least disabling STP shouldn't be a real issue if I'm not wrong (maybe I am). But there seem to be more features.
(when I saw "prot_virt" it felt like somebody is using a big hammer for small nails (e.g., compared to "stp=off").)
Can you guys add these details to the patch description?
Signature · 3 lines
Thanks, David / dhildenb
Claudio Imbrenda
maintainerRe: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 56 lines · On Thu, 24 Oct 2019 17:52:31 +0200 David Hildenbrand <[email protected]> wrote:
Quoted 55 lines · Christian Borntraeger
Quoted 51 lines · David Hildenbrand
Quoted 35 lines · David Hildenbrand
Quoted 34 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48+++++++++++++++++++
arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644arch/s390/kernel/uv.c(quoted diff) +0
-0
b/Documentation/admin-guide/kernel-parameters.txtindexc7ac2f3ac99f..aa22e36b3105100644 ---a/Documentation/admin-guide/kernel-parameters.txt+++b/Documentation/admin-guide/kernel-parameters.txt@@ -3693,6 +3693,11 @@ before loading.
SeeDocumentation/admin-guide/blockdev/ramdisk.rst.
+ prot_virt= [S390] enable hosting protected virtualQuoted 9 lines
Quoted 4 lines
machines
+ isolated from the hypervisor (if hardware supports + that).
+ Format: <bool>Isn't that a virt driver detail that should come in via KVM module parameters? I don't see quite yet why this has to be a kernel parameter (that can be changed at runtime).
I was confused by "runtime" in "which controls if the kernel protected VMs support is enabled at runtime"
So this can't be changed at runtime. Can you clarify why kvm can't initialize that when loaded and why we need a kernel parameter?
Quoted 7 lines
Quoted 3 lines
We have to do the opt-in very early for several reasons:
- we have to donate a potentially largish contiguous (in real) range of memory to the ultravisorIf you'd be using CMA (or
alloc_contig_pages()with less guarantees) you could be making good use of the memory until you actually start an encrypted guest.
no, the memory needs to be allocated before any other interaction with the ultravisor is attempted, and the size depends on the size of the _host_ memory. it can be a very substantial amount of memory, and thus it's very likely to fail unless it's done very early at boot time.
Quoted 3 lines
I can see that using the memblock allocator early is easier. But you waste "largish ... range of memory" even if you never run VMs.
this is inevitable
Quoted 2 lines
Maybe something to work on in the future.
honestly unlikely. which is why protected virtualization needs to be enabled explicitly
Quoted 6 lines
Quoted 5 lines
- The opt-in will also disable some features in the host that could affect guest integrity (e.g. time sync via STP to avoid the host messing with the guest time stepping). Linux is not happy when you remove features at a later point in time
Quoted 7 lines
At least disabling STP shouldn't be a real issue if I'm not wrong (maybe I am). But there seem to be more features.
(when I saw "
prot_virt" it felt like somebody is using a big hammer for small nails (e.g., compared to "stp=off").)Can you guys add these details to the patch description?
yeah, probably a good idea
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 63 lines · Claudio Imbrenda
Quoted 60 lines · On Thu, 24 Oct 2019 17:52:31 +0200 David Hildenbrand <[email protected]> wrote:
Quoted 58 lines · Christian Borntraeger
Quoted 46 lines · David Hildenbrand
Quoted 35 lines · David Hildenbrand
Quoted 34 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48+++++++++++++++++++
arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644arch/s390/kernel/uv.c(quoted diff) +0
-0
b/Documentation/admin-guide/kernel-parameters.txtindexc7ac2f3ac99f..aa22e36b3105100644 ---a/Documentation/admin-guide/kernel-parameters.txt+++b/Documentation/admin-guide/kernel-parameters.txt@@ -3693,6 +3693,11 @@ before loading.
SeeDocumentation/admin-guide/blockdev/ramdisk.rst.
+ prot_virt= [S390] enable hosting protected virtualQuoted 9 lines
Quoted 4 lines
machines
+ isolated from the hypervisor (if hardware supports + that).
+ Format: <bool>Isn't that a virt driver detail that should come in via KVM module parameters? I don't see quite yet why this has to be a kernel parameter (that can be changed at runtime).
Quoted 5 lines
I was confused by "runtime" in "which controls if the kernel protected VMs support is enabled at runtime"
So this can't be changed at runtime. Can you clarify why kvm can't initialize that when loaded and why we need a kernel parameter?
We have to do the opt-in very early for several reasons:
- we have to donate a potentially largish contiguous (in real) range of memory to the ultravisor
Quoted 6 lines
Quoted 3 lines
If you'd be using CMA (or
alloc_contig_pages()with less guarantees) you could be making good use of the memory until you actually start an encrypted guest.no, the memory needs to be allocated before any other interaction with the ultravisor is attempted, and the size depends on the size of the
I fail to see why you need interaction with the UV before you actually start/create an encrypted guest (IOW why you can't defer uv_init()) - but I am not past "[RFC 07/37] KVM: s390: protvirt: Secure memory is not mergeable" yet and ...
Quoted 2 lines
_host_ memory. it can be a very substantial amount of memory, and thus it's very likely to fail unless it's done very early at boot time.
... I guess you could still do that via CMA ... but it doesn't really matter right now :) I understood the rational.
Quoted 10 lines
Quoted 10 lines
Quoted 6 lines
- The opt-in will also disable some features in the host that could affect guest integrity (e.g. time sync via STP to avoid the host messing with the guest time stepping). Linux is not happy when you remove features at a later point in time
At least disabling STP shouldn't be a real issue if I'm not wrong (maybe I am). But there seem to be more features.
Quoted 7 lines
Quoted 4 lines
(when I saw "
prot_virt" it felt like somebody is using a big hammer for small nails (e.g., compared to "stp=off").)Can you guys add these details to the patch description?
yeah, probably a good idea
If a patch explains why it does something and not only what it does usually makes me ask less stupid questions :)
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 02/37] s390/protvirt: introduce host side setup
In reply to Janosch FrankQuoted 23 lines · On Thu, 24 Oct 2019 07:40:24 -0400 Janosch Frank <[email protected]> wrote:
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 arch/s390/kernel/uv.c
(...)
Quoted 5 lines
arch/s390/kvm/Kconfig +0
-0
arch/s390/kvm/Kconfig config KVM_S390_UCONTROL · line 63
Quoted 9 lines
arch/s390/kvm/Kconfig +6
-0@@ -55,6 +55,15 @@ config KVM_S390_UCONTROL If unsure, say N. +config KVM_S390_PROTECTED_VIRTUALIZATION_HOST + bool "Protected guests execution support" + depends on KVM + ---help--- + Support hosting protected virtual machines isolated from the + hypervisor.
I'm currently in the process of glancing across this patch set (won't be able to get around to properly looking at it until next week the earliest), so just a very high level comment:
I think there's not enough information in here to allow someone configuring the kernel to decide what this is and if it would be useful to them. This should probably be at least point to some document giving some more details. Also, can you add a sentence where this feature is actually expected to be available?
arch/s390/kvm/Kconfig config KVM_S390_UCONTROL · line 65
Quoted 2 lines
arch/s390/kvm/Kconfig +2
-0+ + If unsure, say Y.
Is 'Y' really the safe choice here? AFAICS, this is introducing new code and not only trying to call new interfaces, if available. Is there any drawback to enabling this on a kernel that won't run on a platform supporting this feature? Is this supposed to be a common setup?
Quoted 4 lines
arch/s390/kvm/Kconfig +1
-0+ # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. source "drivers/vhost/Kconfig"
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 6 lines · Cornelia Huck
I think there's not enough information in here to allow someone configuring the kernel to decide what this is and if it would be useful to them. This should probably be at least point to some document giving some more details. Also, can you add a sentence where this feature is actually expected to be available?
Quoted 7 lines
arch/s390/kvm/Kconfig config KVM_S390_UCONTROL · line 65
Quoted 2 lines
arch/s390/kvm/Kconfig +2
-0+ + If unsure, say Y.Is 'Y' really the safe choice here? AFAICS, this is introducing new code and not only trying to call new interfaces, if available. Is there any drawback to enabling this on a kernel that won't run on a platform supporting this feature? Is this supposed to be a common setup?
I would expect that this is enabled on distributions in the future. So I think we should actually get rid of this Kconfig and always enable that code. We just must pay attention to fence of all the new code if the user does not opt in. (e.g. prot_virt=0). We need to do that anyway and not hanving a Kconfig forces us to be extra careful.
Re: [RFC 02/37] s390/protvirt: introduce host side setup
In reply to Janosch FrankQuoted 261 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 arch/s390/kernel/uv.cDocumentation/admin-guide/kernel-parameters.txt +5
-0@@ -3693,6 +3693,11 @@ before loading. See Documentation/admin-guide/blockdev/ramdisk.rst. + prot_virt= [S390] enable hosting protected virtual machines + isolated from the hypervisor (if hardware supports + that). + Format: <bool> + psi= [KNL] Enable or disable pressure stall information tracking. Format: <bool>arch/s390/boot/Makefile +1
-1@@ -37,7 +37,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char obj-y := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o obj-y += version.o pgm_check_info.o ctype.o text_dma.o -obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) += uv.o +obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST)) += uv.o obj-$(CONFIG_RELOCATABLE) += machine_kexec_reloc.o obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o targets := bzImage startup.a section_cmp.boot.data section_cmp.boot.preserved.data $(obj-y)arch/s390/boot/uv.c +19
-1@@ -3,7 +3,12 @@#include <asm/facility.h> #include <asm/sections.h> +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST int __bootdata_preserved (prot_virt_guest ); +#endif +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +struct uv_info __bootdata_preserved (uv_info ); +#endif void uv_query_info (void ) {@@ -18,7 +23,20 @@ void uv_query_info(void)if (uv_call (0 , (uint64_t )&uvcb))return ; -if (test_bit_inv (BIT_UVC_CMD_SET_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list) && +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST )) { +memcpy (uv_info.inst_calls_list, uvcb.inst_calls_list,sizeof (uv_info.inst_calls_list)); + uv_info.uv_base_stor_len = uvcb.uv_base_stor_len; + uv_info.guest_base_stor_len = uvcb.conf_base_phys_stor_len; + uv_info.guest_virt_base_stor_len = uvcb.conf_base_virt_stor_len; + uv_info.guest_virt_var_stor_len = uvcb.conf_virt_var_stor_len; + uv_info.guest_cpu_stor_len = uvcb.cpu_stor_len; + uv_info.max_sec_stor_addr =ALIGN (uvcb.max_guest_stor_addr,PAGE_SIZE ); + uv_info.max_num_sec_conf = uvcb.max_num_sec_conf; + uv_info.max_guest_cpus = uvcb.max_guest_cpus; + } + +if (IS_ENABLED (CONFIG_PROTECTED_VIRTUALIZATION_GUEST ) && +test_bit_inv (BIT_UVC_CMD_SET_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list) &&test_bit_inv (BIT_UVC_CMD_REMOVE_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list)) prot_virt_guest =1 ; }arch/s390/include/asm/uv.h +43
-3@@ -44,7 +44,19 @@ struct uv_cb_qui {struct uv_cb_header header;u64 reserved08;u64 inst_calls_list[4 ]; -u64 reserved30[15 ]; +u64 reserved30[2 ]; +u64 uv_base_stor_len; +u64 reserved48; +u64 conf_base_phys_stor_len; +u64 conf_base_virt_stor_len; +u64 conf_virt_var_stor_len; +u64 cpu_stor_len; +u32 reserved68[3 ]; +u32 max_num_sec_conf; +u64 max_guest_stor_addr; +u8 reserved80[150 -128 ]; +u16 max_guest_cpus; +u64 reserved98; } __packed__aligned(8) ;struct uv_cb_share {@@ -69,9 +81,21 @@ static inline int uv_call(unsigned long r1, unsigned long r2)return cc; } -#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST +struct uv_info { +unsigned long inst_calls_list[4 ]; +unsigned long uv_base_stor_len; +unsigned long guest_base_stor_len; +unsigned long guest_virt_base_stor_len; +unsigned long guest_virt_var_stor_len; +unsigned long guest_cpu_stor_len; +unsigned long max_sec_stor_addr; +unsigned int max_num_sec_conf; +unsigned short max_guest_cpus; +}; +extern struct uv_info uv_info;extern int prot_virt_guest; +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST static inline int is_prot_virt_guest (void ) {return prot_virt_guest;@@ -121,11 +145,27 @@ static inline int uv_remove_shared(unsigned long addr) return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); } -void uv_query_info (void );#else #define is_prot_virt_guest () 0static inline int uv_set_shared (unsigned long addr) {return 0 ; }static inline int uv_remove_shared (unsigned long addr) {return 0 ; } +#endif + +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +extern int prot_virt_host; + +static inline int is_prot_virt_host (void ) +{ +return prot_virt_host; +} +#else +#define is_prot_virt_host () 0 +#endif + +#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST ) || \ + defined(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) +void uv_query_info (void ); +#else static inline void uv_query_info (void ) {}#endif arch/s390/kernel/Makefile +1
-0@@ -78,6 +78,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_diag.o obj-$(CONFIG_TRACEPOINTS) += trace.o +obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST)) += uv.o # vdso obj-y += vdso64/arch/s390/kernel/setup.c +0
-4@@ -92,10 +92,6 @@ char elf_platform[ELF_PLATFORM_SIZE];unsigned long int_hwcap =0 ; -#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST -int __bootdata_preserved (prot_virt_guest ); -#endif -int __bootdata (noexec_disabled );int __bootdata (memory_end_set );unsigned long __bootdata (memory_end );arch/s390/kernel/uv.c new file +48
-0@@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Common Ultravisor functions and initialization +* +* Copyright IBM Corp. 2019 +*/ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/sizes.h> +#include <linux/bitmap.h> +#include <linux/memblock.h> +#include <asm/facility.h> +#include <asm/sections.h> +#include <asm/uv.h> + +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST +int __bootdata_preserved (prot_virt_guest ); +#endif + +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +int prot_virt_host; +EXPORT_SYMBOL (prot_virt_host); +struct uv_info __bootdata_preserved (uv_info ); +EXPORT_SYMBOL (uv_info); + +static int __init prot_virt_setup (char *val) +{ +bool enabled; +int rc; + + rc =kstrtobool (val, &enabled); +if (!rc && enabled) + prot_virt_host =1 ; + +if (is_prot_virt_guest () && prot_virt_host) { + prot_virt_host =0 ; +pr_info ("Running as protected virtualization guest." ); + } + +if (prot_virt_host && !test_facility (158 )) { + prot_virt_host =0 ; +pr_info ("The ultravisor call facility is not available." ); + } + +return rc; +} +early_param ("prot_virt" , prot_virt_setup); +#endif arch/s390/kvm/Kconfig +2
-0@@ -55,6 +55,15 @@ config KVM_S390_UCONTROL If unsure, say N. +config KVM_S390_PROTECTED_VIRTUALIZATION_HOST + bool "Protected guests execution support"
arch/s390/kvm/Kconfig config KVM_S390_UCONTROL · line 69
Quoted 10 lines
arch/s390/kvm/Kconfig +7
-0+ depends on KVM + ---help--- + Support hosting protected virtual machines isolated from the + hypervisor. + + If unsure, say Y. + # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. source "drivers/vhost/Kconfig"
As we have the prot_virt kernel paramter there is a way to fence this during runtime Not sure if we really need a build time fence. We could get rid of CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST and just use CONFIG_KVM instead, assuming that in the long run all distros will enable that anyway.
If other reviewers prefer to keep that extra option what about the following to the help section:
----
Support hosting protected virtual machines in KVM. The state of these machines like memory content or register content is protected from the host or host administrators.
Enabling this option will enable extra code that talks to a new firmware instance called ultravisor that will take care of protecting the guest while also enabling KVM to run this guest.
This feature must be enable by the kernel command line option prot_virt.
If unsure, say Y.
----
Either way, the remaining part is
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 24 lines · On Fri, 1 Nov 2019 09:53:12 +0100 Christian Borntraeger…
Quoted 23 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 arch/s390/kernel/uv.c
(...)
Quoted 18 lines
Quoted 18 lines
arch/s390/kvm/Kconfig +9
-0@@ -55,6 +55,15 @@ config KVM_S390_UCONTROL If unsure, say N. +config KVM_S390_PROTECTED_VIRTUALIZATION_HOST + bool "Protected guests execution support" + depends on KVM + ---help--- + Support hosting protected virtual machines isolated from the + hypervisor. + + If unsure, say Y. + # OK, it's a little counter-intuitive to do this, but it puts it neatly under
Quoted 8 lines
arch/s390/kvm/Kconfig config KVM_S390_UCONTROL · line 69
Quoted 3 lines
arch/s390/kvm/Kconfig +0
-0# the virtualization menu. source "drivers/vhost/Kconfig"As we have the
prot_virtkernel paramter there is a way to fence this during runtime Not sure if we really need a build time fence. We could get rid ofCONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOSTand just useCONFIG_KVMinstead, assuming that in the long run all distros will enable that anyway.
I still need to read through the rest of this patch set to have an informed opinion on that, which will probably take some more time.
Quoted 8 lines
If other reviewers prefer to keep that extra option what about the following to the help section:
----
Support hosting protected virtual machines in KVM. The state of these machines like memory content or register content is protected from the host or host administrators.Enabling this option will enable extra code that talks to a new firmware instance
"...that allows the host kernel to talk..." ?
Quoted 4 lines
called ultravisor that will take care of protecting the guest while also enabling KVM to run this guest.
This feature must be enable by the kernel command line option
prot_virt.
s/enable by/enabled via/
Quoted 2 lines
If unsure, say Y.
Looks better. I'm continuing to read the rest of this series before I say more, though :)
Janosch Frank
maintainerRe: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 63 lines · Cornelia Huck
Quoted 24 lines · On Fri, 1 Nov 2019 09:53:12 +0100 Christian Borntraeger…
Quoted 23 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 arch/s390/kernel/uv.c(...)
Quoted 18 lines
Quoted 18 lines
arch/s390/kvm/Kconfig +9
-0@@ -55,6 +55,15 @@ config KVM_S390_UCONTROL If unsure, say N. +config KVM_S390_PROTECTED_VIRTUALIZATION_HOST + bool "Protected guests execution support" + depends on KVM + ---help--- + Support hosting protected virtual machines isolated from the + hypervisor. + + If unsure, say Y. + # OK, it's a little counter-intuitive to do this, but it puts it neatly underQuoted 8 lines
arch/s390/kvm/Kconfig config KVM_S390_UCONTROL · line 69
Quoted 3 lines
arch/s390/kvm/Kconfig +0
-0# the virtualization menu. source "drivers/vhost/Kconfig"As we have the
prot_virtkernel paramter there is a way to fence this during runtime Not sure if we really need a build time fence. We could get rid ofCONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOSTand just useCONFIG_KVMinstead, assuming that in the long run all distros will enable that anyway.I still need to read through the rest of this patch set to have an informed opinion on that, which will probably take some more time.
Quoted 3 lines
If other reviewers prefer to keep that extra option what about the following to the help section:
Quoted 7 lines
Quoted 5 lines
----
Support hosting protected virtual machines in KVM. The state of these machines like memory content or register content is protected from the host or host administrators.Enabling this option will enable extra code that talks to a new firmware instance
"...that allows the host kernel to talk..." ?
"allows a Linux hypervisor to talk..." ?
Quoted 14 lines
Quoted 5 lines
called ultravisor that will take care of protecting the guest while also enabling KVM to run this guest.
This feature must be enable by the kernel command line option
prot_virt.s/enable by/enabled via/
Quoted 2 lines
If unsure, say Y.
Looks better. I'm continuing to read the rest of this series before I say more, though :)
Re: [RFC 02/37] s390/protvirt: introduce host side setup
In reply to Janosch FrankQuoted 23 lines · On Thu, 24 Oct 2019 07:40:24 -0400 Janosch Frank <[email protected]> wrote:
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 arch/s390/kernel/uv.c
(...)
Quoted 5 lines
arch/s390/boot/uv.c +0
-0
arch/s390/boot/uv.c line 11
Quoted 9 lines
arch/s390/boot/uv.c +5
-0@@ -3,7 +3,12 @@#include <asm/facility.h> #include <asm/sections.h> +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST int __bootdata_preserved (prot_virt_guest ); +#endif +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +struct uv_info __bootdata_preserved (uv_info ); +#endif
Two functions with the same name, but different signatures look really ugly.
Also, what happens if I want to build just a single kernel image for both guest and host?
arch/s390/boot/uv.c void uv_query_info(void) · line 26
Quoted 9 lines
arch/s390/boot/uv.c +1
-1void uv_query_info (void ) {@@ -18,7 +23,20 @@ void uv_query_info(void)if (uv_call (0 , (uint64_t )&uvcb))return ; - if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) && +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST )) {
Do we always have everything needed for a host if uv_call() is successful?
Quoted 4 lines
arch/s390/boot/uv.c +4
-0+memcpy (uv_info.inst_calls_list, uvcb.inst_calls_list,sizeof (uv_info.inst_calls_list)); + uv_info.uv_base_stor_len = uvcb.uv_base_stor_len; + uv_info.guest_base_stor_len = uvcb.conf_base_phys_stor_len; + uv_info.guest_virt_base_stor_len = uvcb.conf_base_virt_stor_len;
arch/s390/boot/uv.c void uv_query_info(void) · line 40
Quoted 10 lines
arch/s390/boot/uv.c +9
-0+ uv_info.guest_virt_var_stor_len = uvcb.conf_virt_var_stor_len; + uv_info.guest_cpu_stor_len = uvcb.cpu_stor_len; + uv_info.max_sec_stor_addr =ALIGN (uvcb.max_guest_stor_addr,PAGE_SIZE ); + uv_info.max_num_sec_conf = uvcb.max_num_sec_conf; + uv_info.max_guest_cpus = uvcb.max_guest_cpus; + } + +if (IS_ENABLED (CONFIG_PROTECTED_VIRTUALIZATION_GUEST ) && +test_bit_inv (BIT_UVC_CMD_SET_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list) &&test_bit_inv (BIT_UVC_CMD_REMOVE_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list))
Especially as it looks like we need to test for those two commands to determine whether we have support for a guest.
Quoted 33 lines
arch/s390/boot/uv.c +0
-0prot_virt_guest =1 ; }arch/s390/include/asm/uv.h +14
-2@@ -44,7 +44,19 @@ struct uv_cb_qui {struct uv_cb_header header;u64 reserved08;u64 inst_calls_list[4 ]; -u64 reserved30[15 ]; +u64 reserved30[2 ]; +u64 uv_base_stor_len; +u64 reserved48; +u64 conf_base_phys_stor_len; +u64 conf_base_virt_stor_len; +u64 conf_virt_var_stor_len; +u64 cpu_stor_len; +u32 reserved68[3 ]; +u32 max_num_sec_conf; +u64 max_guest_stor_addr; +u8 reserved80[150 -128 ]; +u16 max_guest_cpus; +u64 reserved98; } __packed__aligned(8) ;struct uv_cb_share {@@ -69,9 +81,21 @@ static inline int uv_call(unsigned long r1, unsigned long r2)return cc; } -#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST +struct uv_info {
arch/s390/include/asm/uv.h static inline int uv_call(unsigned long r1, unsigned long r2) · line 94
Quoted 10 lines
arch/s390/include/asm/uv.h +10
-0+unsigned long inst_calls_list[4 ]; +unsigned long uv_base_stor_len; +unsigned long guest_base_stor_len; +unsigned long guest_virt_base_stor_len; +unsigned long guest_virt_var_stor_len; +unsigned long guest_cpu_stor_len; +unsigned long max_sec_stor_addr; +unsigned int max_num_sec_conf; +unsigned short max_guest_cpus; +};
What is the main difference between uv_info and uv_cb_qui? The alignment of max_sec_stor_addr?
Quoted 35 lines
arch/s390/include/asm/uv.h +19
-1+extern struct uv_info uv_info;extern int prot_virt_guest; +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST static inline int is_prot_virt_guest (void ) {return prot_virt_guest;@@ -121,11 +145,27 @@ static inline int uv_remove_shared(unsigned long addr) return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); } -void uv_query_info (void );#else #define is_prot_virt_guest () 0static inline int uv_set_shared (unsigned long addr) {return 0 ; }static inline int uv_remove_shared (unsigned long addr) {return 0 ; } +#endif + +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +extern int prot_virt_host; + +static inline int is_prot_virt_host (void ) +{ +return prot_virt_host; +} +#else +#define is_prot_virt_host () 0 +#endif + +#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST ) || \ + defined(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) +void uv_query_info (void ); +#else static inline void uv_query_info (void ) {}#endif
(...)
Quoted 36 lines
arch/s390/kernel/uv.c new file +30
-0@@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Common Ultravisor functions and initialization +* +* Copyright IBM Corp. 2019 +*/ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/sizes.h> +#include <linux/bitmap.h> +#include <linux/memblock.h> +#include <asm/facility.h> +#include <asm/sections.h> +#include <asm/uv.h> + +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST +int __bootdata_preserved (prot_virt_guest ); +#endif + +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +int prot_virt_host; +EXPORT_SYMBOL (prot_virt_host); +struct uv_info __bootdata_preserved (uv_info ); +EXPORT_SYMBOL (uv_info); + +static int __init prot_virt_setup (char *val) +{ +bool enabled; +int rc; +
arch/s390/kernel/uv.c line 40
Quoted 10 lines
arch/s390/kernel/uv.c new file +10
-0+ rc =kstrtobool (val, &enabled); +if (!rc && enabled) + prot_virt_host =1 ; + +if (is_prot_virt_guest () && prot_virt_host) { + prot_virt_host =0 ; +pr_info ("Running as protected virtualization guest." ); + } + +if (prot_virt_host && !test_facility (158 )) {
Why not check for that facility earlier? If it is not present, we cannot run as a prot virt guest, either.
arch/s390/kernel/uv.c line 47
Quoted 7 lines
arch/s390/kernel/uv.c new file +7
-0+ prot_virt_host =0 ; +pr_info ("The ultravisor call facility is not available." ); + } + +return rc; +} +early_param ("prot_virt" , prot_virt_setup);
Maybe rename this to prot_virt_host?
Quoted 1 line
arch/s390/kernel/uv.c new file +1
-0+#endif
(...)
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 47 lines · Cornelia Huck
Quoted 23 lines · On Thu, 24 Oct 2019 07:40:24 -0400 Janosch Frank <[email protected]> wrote:
From: Vasily Gorbik <[email protected]>
Introduce
KVM_S390_PROTECTED_VIRTUALIZATION_HOSTkbuild option for protected virtual machines hosting support code.Add "
prot_virt" command line option which controls if the kernel protected VMs support is enabled at runtime.Extend ultravisor info definitions and expose it via
uv_infostruct filled in during startup.Signed-off-by Vasily Gorbik <[email protected]>--- .../admin-guide/kernel-parameters.txt | 5 ++ arch/s390/boot/Makefile | 2 +- arch/s390/boot/uv.c | 20 +++++++- arch/s390/include/asm/uv.h | 46 ++++++++++++++++-- arch/s390/kernel/Makefile | 1 + arch/s390/kernel/setup.c | 4 -- arch/s390/kernel/uv.c | 48 +++++++++++++++++++ arch/s390/kvm/Kconfig | 9 ++++ 8 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 arch/s390/kernel/uv.c(...)
Quoted 5 lines
arch/s390/boot/uv.c +0
-0arch/s390/boot/uv.c line 11
Quoted 9 lines
arch/s390/boot/uv.c +5
-0@@ -3,7 +3,12 @@#include <asm/facility.h> #include <asm/sections.h> +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST int __bootdata_preserved (prot_virt_guest ); +#endif +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +struct uv_info __bootdata_preserved (uv_info ); +#endif Two functions with the same name, but different signatures look really ugly.
Quoted 2 lines
Also, what happens if I want to build just a single kernel image for both guest and host?
This is not two functions with the same name. It is 2 variable declarations with the __bootdata_preserved helper. We expect to have all distro kernels to enable both.
Quoted 8 lines
Quoted 8 lines
arch/s390/boot/uv.c +0
-0void uv_query_info (void ) {@@ -18,7 +23,20 @@ void uv_query_info(void)if (uv_call (0 , (uint64_t )&uvcb))return ;
Quoted 5 lines
arch/s390/boot/uv.c void uv_query_info(void) · line 26
Quoted 2 lines
arch/s390/boot/uv.c +1
-1- if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) && +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST )) {Do we always have everything needed for a host if
uv_call()is successful?
The uv_call is the query call. It will provide the list of features. We check that later on.
Quoted 50 lines
Quoted 5 lines
arch/s390/boot/uv.c +4
-0+memcpy (uv_info.inst_calls_list, uvcb.inst_calls_list,sizeof (uv_info.inst_calls_list)); + uv_info.uv_base_stor_len = uvcb.uv_base_stor_len; + uv_info.guest_base_stor_len = uvcb.conf_base_phys_stor_len; + uv_info.guest_virt_base_stor_len = uvcb.conf_base_virt_stor_len;arch/s390/boot/uv.c void uv_query_info(void) · line 40
Quoted 10 lines
arch/s390/boot/uv.c +9
-0+ uv_info.guest_virt_var_stor_len = uvcb.conf_virt_var_stor_len; + uv_info.guest_cpu_stor_len = uvcb.cpu_stor_len; + uv_info.max_sec_stor_addr =ALIGN (uvcb.max_guest_stor_addr,PAGE_SIZE ); + uv_info.max_num_sec_conf = uvcb.max_num_sec_conf; + uv_info.max_guest_cpus = uvcb.max_guest_cpus; + } + +if (IS_ENABLED (CONFIG_PROTECTED_VIRTUALIZATION_GUEST ) && +test_bit_inv (BIT_UVC_CMD_SET_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list) &&test_bit_inv (BIT_UVC_CMD_REMOVE_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list))Especially as it looks like we need to test for those two commands to determine whether we have support for a guest.
Quoted 31 lines
arch/s390/boot/uv.c +0
-0prot_virt_guest =1 ; }arch/s390/include/asm/uv.h +13
-1@@ -44,7 +44,19 @@ struct uv_cb_qui {struct uv_cb_header header;u64 reserved08;u64 inst_calls_list[4 ]; -u64 reserved30[15 ]; +u64 reserved30[2 ]; +u64 uv_base_stor_len; +u64 reserved48; +u64 conf_base_phys_stor_len; +u64 conf_base_virt_stor_len; +u64 conf_virt_var_stor_len; +u64 cpu_stor_len; +u32 reserved68[3 ]; +u32 max_num_sec_conf; +u64 max_guest_stor_addr; +u8 reserved80[150 -128 ]; +u16 max_guest_cpus; +u64 reserved98; } __packed__aligned(8) ;struct uv_cb_share {@@ -69,9 +81,21 @@ static inline int uv_call(unsigned long r1, unsigned long r2)return cc; }
Quoted 15 lines
arch/s390/include/asm/uv.h static inline int uv_call(unsigned long r1, unsigned long r2) · line 94
Quoted 12 lines
arch/s390/include/asm/uv.h +11
-1-#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST +struct uv_info { +unsigned long inst_calls_list[4 ]; +unsigned long uv_base_stor_len; +unsigned long guest_base_stor_len; +unsigned long guest_virt_base_stor_len; +unsigned long guest_virt_var_stor_len; +unsigned long guest_cpu_stor_len; +unsigned long max_sec_stor_addr; +unsigned int max_num_sec_conf; +unsigned short max_guest_cpus; +};What is the main difference between
uv_infoanduv_cb_qui? The alignment ofmax_sec_stor_addr?
One is the hardware data structure for query, the other one is the Linux internal state.
Quoted 39 lines
Quoted 36 lines
arch/s390/include/asm/uv.h +19
-1+extern struct uv_info uv_info;extern int prot_virt_guest; +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST static inline int is_prot_virt_guest (void ) {return prot_virt_guest;@@ -121,11 +145,27 @@ static inline int uv_remove_shared(unsigned long addr) return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); } -void uv_query_info (void );#else #define is_prot_virt_guest () 0static inline int uv_set_shared (unsigned long addr) {return 0 ; }static inline int uv_remove_shared (unsigned long addr) {return 0 ; } +#endif + +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +extern int prot_virt_host; + +static inline int is_prot_virt_host (void ) +{ +return prot_virt_host; +} +#else +#define is_prot_virt_host () 0 +#endif + +#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST ) || \ + defined(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) +void uv_query_info (void ); +#else static inline void uv_query_info (void ) {}#endif (...)
[...]
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 22 lines · On Mon, 4 Nov 2019 18:50:12 +0100 Christian Borntraeger…
Quoted 21 lines · Cornelia Huck
Quoted 5 lines · On Thu, 24 Oct 2019 07:40:24 -0400 Janosch Frank <[email protected]> wrote:
arch/s390/boot/uv.c +0
-0arch/s390/boot/uv.c line 11
Quoted 9 lines
arch/s390/boot/uv.c +5
-0@@ -3,7 +3,12 @@#include <asm/facility.h> #include <asm/sections.h> +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST int __bootdata_preserved (prot_virt_guest ); +#endif +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +struct uv_info __bootdata_preserved (uv_info ); +#endif Two functions with the same name, but different signatures look really ugly.
Quoted 6 lines
Quoted 2 lines
Also, what happens if I want to build just a single kernel image for both guest and host?
This is not two functions with the same name. It is 2 variable declarations with the
__bootdata_preservedhelper. We expect to have all distro kernels to enable both.
Ah ok, I misread that. (I'm blaming lack of sleep :/)
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
arch/s390/boot/uv.c +0
-0void uv_query_info (void ) {@@ -18,7 +23,20 @@ void uv_query_info(void)if (uv_call (0 , (uint64_t )&uvcb))return ;
Quoted 8 lines
Quoted 5 lines
arch/s390/boot/uv.c void uv_query_info(void) · line 26
Quoted 2 lines
arch/s390/boot/uv.c +1
-1- if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) && +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST )) {Do we always have everything needed for a host if
uv_call()is successful?The
uv_callis the query call. It will provide the list of features. We check that later on.
Hm yes. I'm just seeing the guest side check for features, while the host code just seems to go ahead and copies things. (later on == later patches?)
Quoted 67 lines
Quoted 51 lines
Quoted 6 lines
arch/s390/boot/uv.c +4
-0+memcpy (uv_info.inst_calls_list, uvcb.inst_calls_list,sizeof (uv_info.inst_calls_list)); + uv_info.uv_base_stor_len = uvcb.uv_base_stor_len; + uv_info.guest_base_stor_len = uvcb.conf_base_phys_stor_len; + uv_info.guest_virt_base_stor_len = uvcb.conf_base_virt_stor_len;arch/s390/boot/uv.c void uv_query_info(void) · line 40
Quoted 10 lines
arch/s390/boot/uv.c +9
-0+ uv_info.guest_virt_var_stor_len = uvcb.conf_virt_var_stor_len; + uv_info.guest_cpu_stor_len = uvcb.cpu_stor_len; + uv_info.max_sec_stor_addr =ALIGN (uvcb.max_guest_stor_addr,PAGE_SIZE ); + uv_info.max_num_sec_conf = uvcb.max_num_sec_conf; + uv_info.max_guest_cpus = uvcb.max_guest_cpus; + } + +if (IS_ENABLED (CONFIG_PROTECTED_VIRTUALIZATION_GUEST ) && +test_bit_inv (BIT_UVC_CMD_SET_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list) &&test_bit_inv (BIT_UVC_CMD_REMOVE_SHARED_ACCESS , (unsigned long *)uvcb.inst_calls_list))Especially as it looks like we need to test for those two commands to determine whether we have support for a guest.
Quoted 31 lines
arch/s390/boot/uv.c +0
-0prot_virt_guest =1 ; }arch/s390/include/asm/uv.h +13
-1@@ -44,7 +44,19 @@ struct uv_cb_qui {struct uv_cb_header header;u64 reserved08;u64 inst_calls_list[4 ]; -u64 reserved30[15 ]; +u64 reserved30[2 ]; +u64 uv_base_stor_len; +u64 reserved48; +u64 conf_base_phys_stor_len; +u64 conf_base_virt_stor_len; +u64 conf_virt_var_stor_len; +u64 cpu_stor_len; +u32 reserved68[3 ]; +u32 max_num_sec_conf; +u64 max_guest_stor_addr; +u8 reserved80[150 -128 ]; +u16 max_guest_cpus; +u64 reserved98; } __packed__aligned(8) ;struct uv_cb_share {@@ -69,9 +81,21 @@ static inline int uv_call(unsigned long r1, unsigned long r2)return cc; }Quoted 15 lines
arch/s390/include/asm/uv.h static inline int uv_call(unsigned long r1, unsigned long r2) · line 94
Quoted 12 lines
arch/s390/include/asm/uv.h +11
-1-#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST +struct uv_info { +unsigned long inst_calls_list[4 ]; +unsigned long uv_base_stor_len; +unsigned long guest_base_stor_len; +unsigned long guest_virt_base_stor_len; +unsigned long guest_virt_var_stor_len; +unsigned long guest_cpu_stor_len; +unsigned long max_sec_stor_addr; +unsigned int max_num_sec_conf; +unsigned short max_guest_cpus; +};What is the main difference between
uv_infoanduv_cb_qui? The alignment ofmax_sec_stor_addr?
Quoted 2 lines
One is the hardware data structure for query, the other one is the Linux internal state.
That's clear; I'm mainly wondering about what is simply copied vs. what needs to be calculated.
Re: [RFC 02/37] s390/protvirt: introduce host side setup
Quoted 25 lines · Cornelia Huck
Quoted 22 lines · On Mon, 4 Nov 2019 18:50:12 +0100 Christian Borntraeger…
Quoted 21 lines · Cornelia Huck
Quoted 5 lines · On Thu, 24 Oct 2019 07:40:24 -0400 Janosch Frank <[email protected]> wrote:
arch/s390/boot/uv.c +0
-0arch/s390/boot/uv.c line 11
Quoted 9 lines
arch/s390/boot/uv.c +5
-0@@ -3,7 +3,12 @@#include <asm/facility.h> #include <asm/sections.h> +#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST int __bootdata_preserved (prot_virt_guest ); +#endif +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +struct uv_info __bootdata_preserved (uv_info ); +#endif Two functions with the same name, but different signatures look really ugly.
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines
Also, what happens if I want to build just a single kernel image for both guest and host?
This is not two functions with the same name. It is 2 variable declarations with the
__bootdata_preservedhelper. We expect to have all distro kernels to enable both.Ah ok, I misread that. (I'm blaming lack of sleep :/)
Honestly, I have to admit that I mis-read this in the same way as Cornelia at the first glance. Why is that macro not using capital letters? ... then it would be way more obvious that it's not about a function prototype...
Thomas
Janosch Frank
maintainerRFC 3/37 s390/protvirt: add ultravisor initialization
In reply to Janosch FrankFrom: Vasily Gorbik <[email protected]>
Before being able to host protected virtual machines, donate some of the memory to the ultravisor. Besides that the ultravisor might impose addressing limitations for memory used to back protected VM storage. Treat that limit as protected virtualization host's virtual memory limit.
--- arch/s390/include/asm/uv.h | 16 ++++++++++++ arch/s390/kernel/setup.c | 3 +++ arch/s390/kernel/uv.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)
arch/s390/include/asm/uv.h +16 -0
@@ -23,12 +23,14 @@#define UVC_RC_NO_RESUME 0x0007#define UVC_CMD_QUI 0x0001 +#define UVC_CMD_INIT_UV 0x000f#define UVC_CMD_SET_SHARED_ACCESS 0x1000#define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001/* Bits in installed uv calls */ enum uv_cmds_inst {BIT_UVC_CMD_QUI =0 , +BIT_UVC_CMD_INIT_UV =1 ,BIT_UVC_CMD_SET_SHARED_ACCESS =8 ,BIT_UVC_CMD_REMOVE_SHARED_ACCESS =9 , };
@@ -59,6 +61,15 @@ struct uv_cb_qui {u64 reserved98; } __packed__aligned(8) ; +struct uv_cb_init { +struct uv_cb_header header; +u64 reserved08[2 ]; +u64 stor_origin; +u64 stor_len; +u64 reserved28[4 ]; + +} __packed__aligned(8) ; +struct uv_cb_share {struct uv_cb_header header;u64 reserved08[3 ];
@@ -158,8 +169,13 @@ static inline int is_prot_virt_host(void) {return prot_virt_host; } + +void setup_uv (void ); +void adjust_to_uv_max (unsigned long *vmax);#else #define is_prot_virt_host () 0 +static inline void setup_uv (void ) {} +static inline void adjust_to_uv_max (unsigned long *vmax) {}#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
arch/s390/kernel/setup.c +3 -0
@@ -567,6 +567,8 @@ static void __init setup_memory_end(void) vmax = _REGION1_SIZE;/* 4-level kernel page table */ } +adjust_to_uv_max (&vmax); +/* module area is at the end of the kernel address space. */ MODULES_END = vmax;MODULES_VADDR =MODULES_END -MODULES_LEN ;
@@ -1147,6 +1149,7 @@ void __init setup_arch(char **cmdline_p)*/ memblock_trim_memory (1UL << (MAX_ORDER -1 +PAGE_SHIFT )); +setup_uv ();setup_memory_end ();setup_memory ();dma_contiguous_reserve (memory_end);
arch/s390/kernel/uv.c +53 -0
57 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [RFC 03/37] s390/protvirt: add ultravisor initialization
Quoted 68 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Before being able to host protected virtual machines, donate some of the memory to the ultravisor. Besides that the ultravisor might impose addressing limitations for memory used to back protected VM storage. Treat that limit as protected virtualization host's virtual memory limit.
Signed-off-by Vasily Gorbik <[email protected]>--- arch/s390/include/asm/uv.h | 16 ++++++++++++ arch/s390/kernel/setup.c | 3 +++ arch/s390/kernel/uv.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)arch/s390/include/asm/uv.h +16
-0@@ -23,12 +23,14 @@#define UVC_RC_NO_RESUME 0x0007#define UVC_CMD_QUI 0x0001 +#define UVC_CMD_INIT_UV 0x000f#define UVC_CMD_SET_SHARED_ACCESS 0x1000#define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001/* Bits in installed uv calls */ enum uv_cmds_inst {BIT_UVC_CMD_QUI =0 , +BIT_UVC_CMD_INIT_UV =1 ,BIT_UVC_CMD_SET_SHARED_ACCESS =8 ,BIT_UVC_CMD_REMOVE_SHARED_ACCESS =9 , };@@ -59,6 +61,15 @@ struct uv_cb_qui {u64 reserved98; } __packed__aligned(8) ; +struct uv_cb_init { +struct uv_cb_header header; +u64 reserved08[2 ]; +u64 stor_origin; +u64 stor_len; +u64 reserved28[4 ]; + +} __packed__aligned(8) ; +struct uv_cb_share {struct uv_cb_header header;u64 reserved08[3 ];@@ -158,8 +169,13 @@ static inline int is_prot_virt_host(void) {return prot_virt_host; } + +void setup_uv (void ); +void adjust_to_uv_max (unsigned long *vmax);#else #define is_prot_virt_host () 0 +static inline void setup_uv (void ) {} +static inline void adjust_to_uv_max (unsigned long *vmax) {}#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \arch/s390/kernel/setup.c +0
-0
arch/s390/kernel/setup.c static void __init setup_memory_end(void) · line 570
Quoted 4 lines
arch/s390/kernel/setup.c +1
-0@@ -567,6 +567,8 @@ static void __init setup_memory_end(void) vmax = _REGION1_SIZE;/* 4-level kernel page table */ } +adjust_to_uv_max (&vmax);
I do wonder what would happen if vmax < max_physmem_end. Not sure if that is relevant at all.
Quoted 45 lines
arch/s390/kernel/setup.c +2
-0+/* module area is at the end of the kernel address space. */ MODULES_END = vmax;MODULES_VADDR =MODULES_END -MODULES_LEN ;@@ -1147,6 +1149,7 @@ void __init setup_arch(char **cmdline_p)*/ memblock_trim_memory (1UL << (MAX_ORDER -1 +PAGE_SHIFT )); +setup_uv ();setup_memory_end ();setup_memory ();dma_contiguous_reserve (memory_end);arch/s390/kernel/uv.c +25
-0@@ -45,4 +45,57 @@ static int __init prot_virt_setup(char *val)return rc; }early_param ("prot_virt" , prot_virt_setup); + +static int __init uv_init (unsigned long stor_base,unsigned long stor_len) +{ +struct uv_cb_init uvcb = { + .header.cmd =UVC_CMD_INIT_UV , + .header.len =sizeof (uvcb), + .stor_origin = stor_base, + .stor_len = stor_len, + }; +int cc; + + cc =uv_call (0 , (uint64_t )&uvcb); +if (cc || uvcb.header.rc !=UVC_RC_EXECUTED ) { +pr_err ("Ultravisor init failed with cc: %d rc: 0x%hx\n" , cc, + uvcb.header.rc); +return -1 ; + } +return 0 ; +} + +void __init setup_uv (void ) +{ +unsigned long uv_stor_base; + +if (!prot_virt_host)
arch/s390/kernel/uv.c static int __init prot_virt_setup(char *val) · line 82
Quoted 10 lines
arch/s390/kernel/uv.c +10
-0+return ; + + uv_stor_base = (unsigned long )memblock_alloc_try_nid ( + uv_info.uv_base_stor_len,SZ_1M ,SZ_2G , +MEMBLOCK_ALLOC_ACCESSIBLE ,NUMA_NO_NODE ); +if (!uv_stor_base) { +pr_info ("Failed to reserve %lu bytes for ultravisor base storage\n" , + uv_info.uv_base_stor_len); + goto fail; + }
If I'm not wrong, we could setup/reserve a CMA area here and defer the actual allocation. Then, any MOVABLE data can end up on this CMA area until needed.
But I am neither an expert on CMA nor on UV, so most probably what I say is wrong ;)
Quoted 10 lines
arch/s390/kernel/uv.c +9
-0+ +if (uv_init (uv_stor_base, uv_info.uv_base_stor_len)) { +memblock_free (uv_stor_base, uv_info.uv_base_stor_len); + goto fail; + } + +pr_info ("Reserving %luMB as ultravisor base storage\n" , + uv_info.uv_base_stor_len >>20 ); +return ;
arch/s390/kernel/uv.c static int __init prot_virt_setup(char *val) · line 101
Quoted 10 lines
arch/s390/kernel/uv.c +9
-0+fail: + prot_virt_host = 0; +} + +void adjust_to_uv_max (unsigned long *vmax) +{ +if (prot_virt_host && *vmax > uv_info.max_sec_stor_addr) + *vmax = uv_info.max_sec_stor_addr; +}#endif
Looks good to me from what I can tell.
Signature · 3 lines
Thanks, David / dhildenb
Vasily Gorbik
maintainerRe: [RFC 03/37] s390/protvirt: add ultravisor initialization
Quoted 15 lines · David Hildenbrand
Quoted 14 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Before being able to host protected virtual machines, donate some of the memory to the ultravisor. Besides that the ultravisor might impose addressing limitations for memory used to back protected VM storage. Treat that limit as protected virtualization host's virtual memory limit.
Signed-off-by Vasily Gorbik <[email protected]>--- arch/s390/include/asm/uv.h | 16 ++++++++++++ arch/s390/kernel/setup.c | 3 +++ arch/s390/kernel/uv.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)
Quoted 9 lines
arch/s390/kernel/setup.c static void __init setup_memory_end(void) · line 569
Quoted 6 lines
arch/s390/kernel/setup.c +1
-0@@ -567,6 +567,8 @@ static void __init setup_memory_end(void) vmax = _REGION1_SIZE;/* 4-level kernel page table */ } +adjust_to_uv_max (&vmax);I do wonder what would happen if vmax <
max_physmem_end. Not sure if that is relevant at all.
Then identity mapping would be shorter then actual physical memory available and everything above would be lost. But in reality "max_sec_stor_addr" is big enough to not worry about it in the foreseeable future at all.
Quoted 20 lines
Quoted 5 lines
arch/s390/kernel/setup.c +5
-0+void __init setup_uv (void ) +{ +unsigned long uv_stor_base; + +if (!prot_virt_host)arch/s390/kernel/setup.c static void __init setup_memory_end(void)
Quoted 10 lines
arch/s390/kernel/setup.c +10
-0+return ; + + uv_stor_base = (unsigned long )memblock_alloc_try_nid ( + uv_info.uv_base_stor_len,SZ_1M ,SZ_2G , +MEMBLOCK_ALLOC_ACCESSIBLE ,NUMA_NO_NODE ); +if (!uv_stor_base) { +pr_info ("Failed to reserve %lu bytes for ultravisor base storage\n" , + uv_info.uv_base_stor_len); + goto fail; + }If I'm not wrong, we could setup/reserve a CMA area here and defer the actual allocation. Then, any MOVABLE data can end up on this CMA area until needed.
Quoted 2 lines
But I am neither an expert on CMA nor on UV, so most probably what I say is wrong ;)
From pure memory management this sounds like a good idea. And I tried it and cma_declare_contiguous fulfills our needs, just had to export cma_alloc/cma_release symbols. Nevertheless, delaying ultravisor init means we would be potentially left with vmax == max_sec_stor_addr even if we wouldn't be able to run protected VMs after all (currently setup_uv() is called before kernel address space layout setup). Another much more fundamental reason is that ultravisor init has to be called with a single cpu running, which means it's easy to do before bringing other cpus up and we currently don't have api to stop cpus at a later point (stop_machine won't cut it).
Quoted 29 lines
Quoted 10 lines
arch/s390/kernel/setup.c +9
-0+ +if (uv_init (uv_stor_base, uv_info.uv_base_stor_len)) { +memblock_free (uv_stor_base, uv_info.uv_base_stor_len); + goto fail; + } + +pr_info ("Reserving %luMB as ultravisor base storage\n" , + uv_info.uv_base_stor_len >>20 ); +return ;arch/s390/kernel/setup.c
Quoted 10 lines
arch/s390/kernel/setup.c +9
-0+fail: + prot_virt_host = 0; +} + +void adjust_to_uv_max (unsigned long *vmax) +{ +if (prot_virt_host && *vmax > uv_info.max_sec_stor_addr) + *vmax = uv_info.max_sec_stor_addr; +}#endif Looks good to me from what I can tell.
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 03/37] s390/protvirt: add ultravisor initialization
Quoted 53 lines · Vasily Gorbik
Quoted 15 lines · David Hildenbrand
Quoted 14 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Before being able to host protected virtual machines, donate some of the memory to the ultravisor. Besides that the ultravisor might impose addressing limitations for memory used to back protected VM storage. Treat that limit as protected virtualization host's virtual memory limit.
Signed-off-by Vasily Gorbik <[email protected]>--- arch/s390/include/asm/uv.h | 16 ++++++++++++ arch/s390/kernel/setup.c | 3 +++ arch/s390/kernel/uv.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)Quoted 9 lines
arch/s390/kernel/setup.c static void __init setup_memory_end(void) · line 569
Quoted 6 lines
arch/s390/kernel/setup.c +1
-0@@ -567,6 +567,8 @@ static void __init setup_memory_end(void) vmax = _REGION1_SIZE;/* 4-level kernel page table */ } +adjust_to_uv_max (&vmax);I do wonder what would happen if vmax <
max_physmem_end. Not sure if that is relevant at all.Then identity mapping would be shorter then actual physical memory available and everything above would be lost. But in reality "
max_sec_stor_addr" is big enough to not worry about it in the foreseeable future at all.Quoted 20 lines
Quoted 5 lines
arch/s390/kernel/setup.c +5
-0+void __init setup_uv (void ) +{ +unsigned long uv_stor_base; + +if (!prot_virt_host)arch/s390/kernel/setup.c static void __init setup_memory_end(void)
Quoted 10 lines
arch/s390/kernel/setup.c +10
-0+return ; + + uv_stor_base = (unsigned long )memblock_alloc_try_nid ( + uv_info.uv_base_stor_len,SZ_1M ,SZ_2G , +MEMBLOCK_ALLOC_ACCESSIBLE ,NUMA_NO_NODE ); +if (!uv_stor_base) { +pr_info ("Failed to reserve %lu bytes for ultravisor base storage\n" , + uv_info.uv_base_stor_len); + goto fail; + }If I'm not wrong, we could setup/reserve a CMA area here and defer the actual allocation. Then, any MOVABLE data can end up on this CMA area until needed.
Quoted 2 lines
But I am neither an expert on CMA nor on UV, so most probably what I say is wrong ;)
Quoted 9 lines
From pure memory management this sounds like a good idea. And I tried
it andcma_declare_contiguousfulfills our needs, just had to export cma_alloc/cma_release symbols. Nevertheless, delaying ultravisor init means we would be potentially left with vmax ==max_sec_stor_addreven if we wouldn't be able to run protected VMs after all (currentlysetup_uv()is called before kernel address space layout setup). Another much more fundamental reason is that ultravisor init has to be called with a single cpu running, which means it's easy to do before bringing other cpus up and we currently don't have api to stop cpus at a later point (stop_machinewon't cut it).
Interesting point, I guess. One could hack around that. Emphasis on *hack* :) In stop_machine() you caught all CPUs. You could just temporarily SIGP STOP all running ones, issue the UV init call, and SIGP START them again. Not sure how that works with SMP, though ...
But yeah, this is stuff for the future, just an idea from my side :)
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 03/37] s390/protvirt: add ultravisor initialization
In reply to Janosch FrankQuoted 8 lines · Janosch Frank
From: Vasily Gorbik <[email protected]>
Before being able to host protected virtual machines, donate some of the memory to the ultravisor. Besides that the ultravisor might impose addressing limitations for memory used to back protected VM storage. Treat that limit as protected virtualization host's virtual memory limit.
Signed-off-by Vasily Gorbik <[email protected]>
Quoted 139 lines
--- arch/s390/include/asm/uv.h | 16 ++++++++++++ arch/s390/kernel/setup.c | 3 +++ arch/s390/kernel/uv.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)arch/s390/include/asm/uv.h +16
-0@@ -23,12 +23,14 @@#define UVC_RC_NO_RESUME 0x0007#define UVC_CMD_QUI 0x0001 +#define UVC_CMD_INIT_UV 0x000f#define UVC_CMD_SET_SHARED_ACCESS 0x1000#define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001/* Bits in installed uv calls */ enum uv_cmds_inst {BIT_UVC_CMD_QUI =0 , +BIT_UVC_CMD_INIT_UV =1 ,BIT_UVC_CMD_SET_SHARED_ACCESS =8 ,BIT_UVC_CMD_REMOVE_SHARED_ACCESS =9 , };@@ -59,6 +61,15 @@ struct uv_cb_qui {u64 reserved98; } __packed__aligned(8) ; +struct uv_cb_init { +struct uv_cb_header header; +u64 reserved08[2 ]; +u64 stor_origin; +u64 stor_len; +u64 reserved28[4 ]; + +} __packed__aligned(8) ; +struct uv_cb_share {struct uv_cb_header header;u64 reserved08[3 ];@@ -158,8 +169,13 @@ static inline int is_prot_virt_host(void) {return prot_virt_host; } + +void setup_uv (void ); +void adjust_to_uv_max (unsigned long *vmax);#else #define is_prot_virt_host () 0 +static inline void setup_uv (void ) {} +static inline void adjust_to_uv_max (unsigned long *vmax) {}#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \arch/s390/kernel/setup.c +3
-0@@ -567,6 +567,8 @@ static void __init setup_memory_end(void) vmax = _REGION1_SIZE;/* 4-level kernel page table */ } +adjust_to_uv_max (&vmax); +/* module area is at the end of the kernel address space. */ MODULES_END = vmax;MODULES_VADDR =MODULES_END -MODULES_LEN ;@@ -1147,6 +1149,7 @@ void __init setup_arch(char **cmdline_p)*/ memblock_trim_memory (1UL << (MAX_ORDER -1 +PAGE_SHIFT )); +setup_uv ();setup_memory_end ();setup_memory ();dma_contiguous_reserve (memory_end);arch/s390/kernel/uv.c +53
-0@@ -45,4 +45,57 @@ static int __init prot_virt_setup(char *val)return rc; }early_param ("prot_virt" , prot_virt_setup); + +static int __init uv_init (unsigned long stor_base,unsigned long stor_len) +{ +struct uv_cb_init uvcb = { + .header.cmd =UVC_CMD_INIT_UV , + .header.len =sizeof (uvcb), + .stor_origin = stor_base, + .stor_len = stor_len, + }; +int cc; + + cc =uv_call (0 , (uint64_t )&uvcb); +if (cc || uvcb.header.rc !=UVC_RC_EXECUTED ) { +pr_err ("Ultravisor init failed with cc: %d rc: 0x%hx\n" , cc, + uvcb.header.rc); +return -1 ; + } +return 0 ; +} + +void __init setup_uv (void ) +{ +unsigned long uv_stor_base; + +if (!prot_virt_host) +return ; + + uv_stor_base = (unsigned long )memblock_alloc_try_nid ( + uv_info.uv_base_stor_len,SZ_1M ,SZ_2G , +MEMBLOCK_ALLOC_ACCESSIBLE ,NUMA_NO_NODE ); +if (!uv_stor_base) { +pr_info ("Failed to reserve %lu bytes for ultravisor base storage\n" , + uv_info.uv_base_stor_len); + goto fail; + } + +if (uv_init (uv_stor_base, uv_info.uv_base_stor_len)) { +memblock_free (uv_stor_base, uv_info.uv_base_stor_len); + goto fail; + } + +pr_info ("Reserving %luMB as ultravisor base storage\n" , + uv_info.uv_base_stor_len >>20 ); +return ; +fail: + prot_virt_host =0 ; +} + +void adjust_to_uv_max (unsigned long *vmax) +{ +if (prot_virt_host && *vmax > uv_info.max_sec_stor_addr) + *vmax = uv_info.max_sec_stor_addr; +}#endif
Re: [RFC 03/37] s390/protvirt: add ultravisor initialization
In reply to Janosch FrankQuoted 13 lines · On Thu, 24 Oct 2019 07:40:25 -0400 Janosch Frank <[email protected]> wrote:
From: Vasily Gorbik <[email protected]>
Before being able to host protected virtual machines, donate some of the memory to the ultravisor. Besides that the ultravisor might impose addressing limitations for memory used to back protected VM storage. Treat that limit as protected virtualization host's virtual memory limit.
Signed-off-by Vasily Gorbik <[email protected]>--- arch/s390/include/asm/uv.h | 16 ++++++++++++ arch/s390/kernel/setup.c | 3 +++ arch/s390/kernel/uv.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)
(...)
Quoted 14 lines
arch/s390/kernel/uv.c +6
-0@@ -45,4 +45,57 @@ static int __init prot_virt_setup(char *val)return rc; }early_param ("prot_virt" , prot_virt_setup); + +static int __init uv_init (unsigned long stor_base,unsigned long stor_len) +{ +struct uv_cb_init uvcb = { + .header.cmd =UVC_CMD_INIT_UV , + .header.len =sizeof (uvcb),
arch/s390/kernel/uv.c static int __init prot_virt_setup(char *val) · line 63
Quoted 10 lines
arch/s390/kernel/uv.c +10
-0+ .stor_origin = stor_base, + .stor_len = stor_len, + }; +int cc; + + cc =uv_call (0 , (uint64_t )&uvcb); +if (cc || uvcb.header.rc !=UVC_RC_EXECUTED ) { +pr_err ("Ultravisor init failed with cc: %d rc: 0x%hx\n" , cc, + uvcb.header.rc); +return -1 ;
Is there any reasonable case where that call might fail if we have the facility installed? Bad stor_base, maybe?
Quoted 20 lines
arch/s390/kernel/uv.c +20
-0+ } +return 0 ; +} + +void __init setup_uv (void ) +{ +unsigned long uv_stor_base; + +if (!prot_virt_host) +return ; + + uv_stor_base = (unsigned long )memblock_alloc_try_nid ( + uv_info.uv_base_stor_len,SZ_1M ,SZ_2G , +MEMBLOCK_ALLOC_ACCESSIBLE ,NUMA_NO_NODE ); +if (!uv_stor_base) { +pr_info ("Failed to reserve %lu bytes for ultravisor base storage\n" , + uv_info.uv_base_stor_len); + goto fail; + } +
arch/s390/kernel/uv.c static int __init prot_virt_setup(char *val) · line 93
Quoted 10 lines
arch/s390/kernel/uv.c +10
-0+if (uv_init (uv_stor_base, uv_info.uv_base_stor_len)) { +memblock_free (uv_stor_base, uv_info.uv_base_stor_len); + goto fail; + } + +pr_info ("Reserving %luMB as ultravisor base storage\n" , + uv_info.uv_base_stor_len >>20 ); +return ; +fail: + prot_virt_host =0 ;
So, what happens if the user requested protected virtualization and any of the above failed? We turn off host support, so any attempt to start a protected virtualization guest on that host will fail (hopefully with a meaningful error), I guess.
Is there any use case where we'd want to make failure to set this up fatal?
Quoted 8 lines
arch/s390/kernel/uv.c +7
-0+} + +void adjust_to_uv_max (unsigned long *vmax) +{ +if (prot_virt_host && *vmax > uv_info.max_sec_stor_addr) + *vmax = uv_info.max_sec_stor_addr; +}#endif
Janosch Frank
maintainerRe: [RFC 03/37] s390/protvirt: add ultravisor initialization
Quoted 38 lines · Cornelia Huck
Quoted 13 lines · On Thu, 24 Oct 2019 07:40:25 -0400 Janosch Frank <[email protected]> wrote:
From: Vasily Gorbik <[email protected]>
Before being able to host protected virtual machines, donate some of the memory to the ultravisor. Besides that the ultravisor might impose addressing limitations for memory used to back protected VM storage. Treat that limit as protected virtualization host's virtual memory limit.
Signed-off-by Vasily Gorbik <[email protected]>--- arch/s390/include/asm/uv.h | 16 ++++++++++++ arch/s390/kernel/setup.c | 3 +++ arch/s390/kernel/uv.c | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)(...)
Quoted 19 lines
arch/s390/kernel/uv.c +11
-0@@ -45,4 +45,57 @@ static int __init prot_virt_setup(char *val)return rc; }early_param ("prot_virt" , prot_virt_setup); + +static int __init uv_init (unsigned long stor_base,unsigned long stor_len) +{ +struct uv_cb_init uvcb = { + .header.cmd =UVC_CMD_INIT_UV , + .header.len =sizeof (uvcb), + .stor_origin = stor_base, + .stor_len = stor_len, + }; +int cc; +
Quoted 8 lines
arch/s390/kernel/uv.c static int __init prot_virt_setup(char *val) · line 63
Quoted 5 lines
arch/s390/kernel/uv.c +5
-0+ cc =uv_call (0 , (uint64_t )&uvcb); +if (cc || uvcb.header.rc !=UVC_RC_EXECUTED ) { +pr_err ("Ultravisor init failed with cc: %d rc: 0x%hx\n" , cc, + uvcb.header.rc); +return -1 ;Is there any reasonable case where that call might fail if we have the facility installed? Bad
stor_base, maybe?
Yes, wrong storage locations, length, etc...
Also if we are running with more than one CPU or the Ultravisor encountered some internal error.
Quoted 28 lines
Quoted 28 lines
arch/s390/kernel/uv.c +27
-0+ } +return 0 ; +} + +void __init setup_uv (void ) +{ +unsigned long uv_stor_base; + +if (!prot_virt_host) +return ; + + uv_stor_base = (unsigned long )memblock_alloc_try_nid ( + uv_info.uv_base_stor_len,SZ_1M ,SZ_2G , +MEMBLOCK_ALLOC_ACCESSIBLE ,NUMA_NO_NODE ); +if (!uv_stor_base) { +pr_info ("Failed to reserve %lu bytes for ultravisor base storage\n" , + uv_info.uv_base_stor_len); + goto fail; + } + +if (uv_init (uv_stor_base, uv_info.uv_base_stor_len)) { +memblock_free (uv_stor_base, uv_info.uv_base_stor_len); + goto fail; + } + +pr_info ("Reserving %luMB as ultravisor base storage\n" , + uv_info.uv_base_stor_len >>20 );
Quoted 9 lines
arch/s390/kernel/uv.c static int __init prot_virt_setup(char *val) · line 93
Quoted 3 lines
arch/s390/kernel/uv.c +3
-0+return ; +fail: + prot_virt_host =0 ;So, what happens if the user requested protected virtualization and any of the above failed? We turn off host support, so any attempt to start a protected virtualization guest on that host will fail (hopefully with a meaningful error), I guess.
STFLE 161, and the associated diag308 subcodes 8-10 will not be available to any VM. So yes, the stuv that starts a protected guest will print a message.
Quoted 2 lines
Is there any use case where we'd want to make failure to set this up fatal?
Not really.
Quoted 10 lines
Quoted 9 lines
arch/s390/kernel/uv.c +7
-0+} + +void adjust_to_uv_max (unsigned long *vmax) +{ +if (prot_virt_host && *vmax > uv_info.max_sec_stor_addr) + *vmax = uv_info.max_sec_stor_addr; +}#endif
Janosch Frank
maintainerRFC 4/37 KVM: s390: protvirt: Add initial lifecycle handling
In reply to Janosch FrankLet's add a KVM interface to create and destroy protected VMs.
--- arch/s390/include/asm/kvm_host.h | 24 +++- arch/s390/include/asm/uv.h | 110 ++++++++++++++ arch/s390/kvm/Makefile | 2 +- arch/s390/kvm/kvm-s390.c | 173 +++++++++++++++++++++- arch/s390/kvm/kvm-s390.h | 47 ++++++ arch/s390/kvm/pv.c | 237 +++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 33 +++++ 7 files changed, 622 insertions(+), 4 deletions(-) create mode 100644 arch/s390/kvm/pv.c
arch/s390/include/asm/kvm_host.h +22 -2
@@ -155,7 +155,13 @@ struct kvm_s390_sie_block {__u8 reserved08[4 ];/* 0x0008 */ #define PROG_IN_SIE (1<<0)__u32 prog0c;/* 0x000c */ -__u8 reserved10[16 ];/* 0x0010 */ +union { +__u8 reserved10[16 ];/* 0x0010 */ +struct { +__u64 pv_handle_cpu; +__u64 pv_handle_config; + }; + };#define PROG_BLOCK_SIE (1<<0)#define PROG_REQUEST (1<<1)atomic_t prog20;/* 0x0020 */
@@ -228,7 +234,7 @@ struct kvm_s390_sie_block {#define ECB3_RI 0x01__u8 ecb3;/* 0x0063 */ __u32 scaol;/* 0x0064 */ -__u8 reserved68;/* 0x0068 */ +__u8 sdf;/* 0x0068 */ __u8 epdx;/* 0x0069 */ __u8 reserved6a[2 ];/* 0x006a */ __u32 todpr;/* 0x006c */
@@ -640,6 +646,11 @@ struct kvm_guestdbg_info_arch {unsigned long last_bp; }; +struct kvm_s390_pv_vcpu { +u64 handle; +unsigned long stor_base; +}; +struct kvm_vcpu_arch {struct kvm_s390_sie_block *sie_block;/* if vsie is active, currently executed shadow sie control block */
@@ -668,6 +679,7 @@ struct kvm_vcpu_arch {__u64 cputm_start;bool gs_enabled;bool skey_enabled; +struct kvm_s390_pv_vcpu pv; };struct kvm_vm_stat {
@@ -841,6 +853,13 @@ struct kvm_s390_gisa_interrupt {DECLARE_BITMAP (kicked_mask,KVM_MAX_VCPUS ); }; +struct kvm_s390_pv { +u64 handle; +u64 guest_len; +unsigned long stor_base; +void *stor_var; +}; +struct kvm_arch {void *sca;int use_esca;
@@ -876,6 +895,7 @@ struct kvm_arch{DECLARE_BITMAP (cpu_feat,KVM_S390_VM_CPU_FEAT_NR_BITS );DECLARE_BITMAP (idle_mask,KVM_MAX_VCPUS );struct kvm_s390_gisa_interrupt gisa_int; +struct kvm_s390_pv pv; };#define KVM_HVA_ERR_BAD (-1UL)
arch/s390/include/asm/uv.h +110 -0
145 lines not on this page · raw message
arch/s390/kvm/Makefile +1 -1
@@ -9,6 +9,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/async_pf.o $(KVM)/irqch ccflags-y := -Ivirt/kvm -Iarch/s390/kvm kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o -kvm-objs += diag.o gaccess.o guestdbg.o vsie.o +kvm-objs += diag.o gaccess.o guestdbg.o vsie.o $(if $(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST),pv.o) obj-$(CONFIG_KVM) += kvm.o
arch/s390/kvm/kvm-s390.c +172 -1
240 lines not on this page · raw message
arch/s390/kvm/kvm-s390.h +47 -0
53 lines not on this page · raw message
arch/s390/kvm/pv.c new file +237 -0
237 lines not on this page · raw message
include/uapi/linux/kvm.h +33 -0
@@ -1000,6 +1000,7 @@ struct kvm_ppc_resize_hpt {#define KVM_CAP_PMU_EVENT_FILTER 173#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175 +#define KVM_CAP_S390_PROTECTED 180#ifdef KVM_CAP_IRQ_ROUTING
@@ -1461,6 +1462,38 @@ struct kvm_enc_region {/* Available with KVM_CAP_ARM_SVE */ #define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) +struct kvm_s390_pv_sec_parm { +__u64 origin; +__u64 length; +}; + +struct kvm_s390_pv_unp { +__u64 addr; +__u64 size; +__u64 tweak; +}; + +enum pv_cmd_id { +KVM_PV_VM_CREATE , +KVM_PV_VM_DESTROY , +KVM_PV_VM_SET_SEC_PARMS , +KVM_PV_VM_UNPACK , +KVM_PV_VM_VERIFY , +KVM_PV_VCPU_CREATE , +KVM_PV_VCPU_DESTROY , +}; + +struct kvm_pv_cmd { +__u32 cmd; +__u16 rc; +__u16 rrc; +__u64 data; +}; + +/* Available with KVM_CAP_S390_SE */ +#define KVM_S390_PV_COMMAND _IOW(KVMIO, 0xc3, struct kvm_pv_cmd) +#define KVM_S390_PV_COMMAND_VCPU _IOW(KVMIO, 0xc4, struct kvm_pv_cmd) +/* Secure Encrypted Virtualization command */ enum sev_cmd_id {/* Guest initialization commands */
Signature · 1 line
2.20.1
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
Quoted 1 line · Janosch Frank
Let's add a KVM interface to create and destroy protected VMs.
More details please.
[...]
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2177
Quoted 12 lines
arch/s390/kvm/kvm-s390.c +11
-0+#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv (struct kvm *kvm,struct kvm_pv_cmd *cmd) +{ +int r =0 ; +void __user *argp = (void __user *)cmd->data; + +switch (cmd->cmd) { +case KVM_PV_VM_CREATE : { + r =kvm_s390_pv_alloc_vm (kvm); +if (r) +break ;
So ... I can create multiple VMs?
Especially, I can call KVM_PV_VM_CREATE two times, setting "kvm->arch.pv.stor_var = NULL and leaking memory" on the second call. Not sure if that's desirable.
Shouldn't this be something like "KVM_PV_VM_INIT" and then make sure it can only be called once?
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2190
Quoted 13 lines
arch/s390/kvm/kvm-s390.c +13
-0+ +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); +/* FMT 4 SIE needs esca */ + r =sca_switch_to_extended (kvm); +if (!r) + r =kvm_s390_pv_create_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_DESTROY : { +/* All VCPUs have to be destroyed before this call. */
Then please verify that? "KVM_PV_VM_DEINIT"
Also, who guarantees that user space calls this at all? Why is that needed? (IOW, when does user space call this?)
Quoted 297 lines
arch/s390/kvm/kvm-s390.c +141
-1+mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); + r =kvm_s390_pv_destroy_vm (kvm); +if (!r) +kvm_s390_pv_dealloc_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_SET_SEC_PARMS : { +struct kvm_s390_pv_sec_parm parms = {}; +void *hdr; + + r = -EFAULT ; +if (copy_from_user (&parms, argp,sizeof (parms))) +break ; + +/* Currently restricted to 8KB */ + r = -EINVAL ; +if (parms.length >PAGE_SIZE *2 ) +break ; + + r = -ENOMEM ; + hdr =vmalloc (parms.length); +if (!hdr) +break ; + + r = -EFAULT ; +if (!copy_from_user (hdr, (void __user *)parms.origin, + parms.length)) + r =kvm_s390_pv_set_sec_parms (kvm, hdr, parms.length); + +vfree (hdr); +break ; + } +case KVM_PV_VM_UNPACK : { +struct kvm_s390_pv_unp unp = {}; + + r = -EFAULT ; +if (copy_from_user (&unp, argp,sizeof (unp))) +break ; + + r =kvm_s390_pv_unpack (kvm, unp.addr, unp.size, unp.tweak); +break ; + } +case KVM_PV_VM_VERIFY : { +u32 ret; + + r = -EINVAL ; +if (!kvm_s390_pv_is_protected (kvm)) +break ; + + r =uv_cmd_nodata (kvm_s390_pv_handle (kvm), +UVC_CMD_VERIFY_IMG , + &ret); +VM_EVENT (kvm,3 ,"PROTVIRT VERIFY: rc %x rrc %x" , + ret >>16 , ret &0x0000ffff ); +break ; + } +default : + return -ENOTTY; + } +return r; +} +#endif +long kvm_arch_vm_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg) {@@ -2254,6 +2351,22 @@ long kvm_arch_vm_ioctl(struct file *filp,mutex_unlock (&kvm->slots_lock);break ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +case KVM_S390_PV_COMMAND : { +struct kvm_pv_cmd args; + + r = -EINVAL ; +if (!is_prot_virt_host ()) +break ; + + r = -EFAULT ; +if (copy_from_user (&args, argp,sizeof (args))) +break ; + + r =kvm_s390_handle_pv (kvm, &args); +break ; + } +#endif default : r = -ENOTTY ; }@@ -2529,6 +2642,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)if (vcpu->kvm->arch.use_cmma)kvm_s390_vcpu_unsetup_cmma (vcpu); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_handle_cpu (vcpu)) +kvm_s390_pv_destroy_cpu (vcpu);free_page ((unsigned long )(vcpu->arch.sie_block));kvm_vcpu_uninit (vcpu);@@ -2555,8 +2671,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm) {kvm_free_vcpus (kvm);sca_dispose (kvm); -debug_unregister (kvm->arch.dbf);kvm_s390_gisa_destroy (kvm); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_is_protected (kvm)) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm); + } +debug_unregister (kvm->arch.dbf);free_page ((unsigned long )kvm->arch.sie_page2);if (!kvm_is_ucontrol (kvm))gmap_remove (kvm->arch.gmap);@@ -2652,6 +2773,9 @@ static int sca_switch_to_extended(struct kvm *kvm)unsigned int vcpu_idx;u32 scaol, scaoh; +if (kvm->arch.use_esca) +return 0 ; + new_sca =alloc_pages_exact (sizeof (*new_sca),GFP_KERNEL |__GFP_ZERO);if (!new_sca)return -ENOMEM ;@@ -3073,6 +3197,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, rc =kvm_vcpu_init (vcpu, kvm, id);if (rc) goto out_free_sie_block; + +if (kvm_s390_pv_is_protected (kvm)) { + rc =kvm_s390_pv_create_cpu (vcpu); +if (rc) { +kvm_vcpu_uninit (vcpu); + goto out_free_sie_block; + } + } +VM_EVENT (kvm,3 ,"create cpu %d at 0x%pK, sie block at 0x%pK" , id, vcpu, vcpu->arch.sie_block);trace_kvm_s390_create_vcpu (id, vcpu, vcpu->arch.sie_block);@@ -4338,6 +4471,28 @@ long kvm_arch_vcpu_async_ioctl(struct file *filp,return -ENOIOCTLCMD ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv_vcpu (struct kvm_vcpu *vcpu, +struct kvm_pv_cmd *cmd) +{ +int r =0 ; + +switch (cmd->cmd) { +case KVM_PV_VCPU_CREATE : { + r =kvm_s390_pv_create_cpu (vcpu); +break ; + } +case KVM_PV_VCPU_DESTROY : { + r =kvm_s390_pv_destroy_cpu (vcpu); +break ; + } +default : + r = -ENOTTY ; + } +return r; +} +#endif +long kvm_arch_vcpu_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg) {@@ -4470,6 +4625,22 @@ long kvm_arch_vcpu_ioctl(struct file *filp, irq_state.len);break ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +case KVM_S390_PV_COMMAND_VCPU : { +struct kvm_pv_cmd args; + + r = -EINVAL ; +if (!is_prot_virt_host ()) +break ; + + r = -EFAULT ; +if (copy_from_user (&args, argp,sizeof (args))) +break ; + + r =kvm_s390_handle_pv_vcpu (vcpu, &args); +break ; + } +#endif default : r = -ENOTTY ; }arch/s390/kvm/kvm-s390.h +47
-0@@ -196,6 +196,53 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)return kvm->arch.user_cpu_state_ctrl !=0 ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +/* implemented in pv.c */ +void kvm_s390_pv_unpin (struct kvm *kvm); +void kvm_s390_pv_dealloc_vm (struct kvm *kvm); +int kvm_s390_pv_alloc_vm (struct kvm *kvm); +int kvm_s390_pv_create_vm (struct kvm *kvm); +int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_destroy_vm (struct kvm *kvm); +int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_set_sec_parms (struct kvm *kvm,void *hdr,u64 length); +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak); +int kvm_s390_pv_verify (struct kvm *kvm); + +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) +{ +return !!kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle (struct kvm *kvm) +{ +return kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) +{ +return vcpu->arch.pv.handle; +} +#else +static inline void kvm_s390_pv_unpin (struct kvm *kvm) {} +static inline void kvm_s390_pv_dealloc_vm (struct kvm *kvm) {} +static inline int kvm_s390_pv_alloc_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_destroy_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_set_sec_parms (struct kvm *kvm, +u64 origin,u64 length) {return 0 ; } +static inline int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr, +unsigned long size,unsigned long tweak) +{return 0 ; } +static inline int kvm_s390_pv_verify (struct kvm *kvm) {return 0 ; } +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +#endif +/* implemented in interrupt.c */ int kvm_s390_handle_wait (struct kvm_vcpu *vcpu);void kvm_s390_vcpu_wakeup (struct kvm_vcpu *vcpu);arch/s390/kvm/pv.c new file +38
-0@@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Hosting Secure Execution virtual machines +* +* Copyright IBM Corp. 2019 +* Author(s): Janosch Frank <[email protected]> +*/ +#include <linux/kvm.h> +#include <linux/kvm_host.h> +#include <linux/pagemap.h> +#include <asm/pgalloc.h> +#include <asm/gmap.h> +#include <asm/uv.h> +#include <asm/gmap.h> +#include <asm/mman.h> +#include "kvm-s390.h" + +void kvm_s390_pv_dealloc_vm (struct kvm *kvm) +{ +vfree (kvm->arch.pv.stor_var); +free_pages (kvm->arch.pv.stor_base, +get_order (uv_info.guest_base_stor_len)); +memset (&kvm->arch.pv,0 ,sizeof (kvm->arch.pv)); +} + +int kvm_s390_pv_alloc_vm (struct kvm *kvm) +{ +unsigned long base = uv_info.guest_base_stor_len; +unsigned long virt = uv_info.guest_virt_var_stor_len; +unsigned long npages =0 , vlen =0 ; +struct kvm_memslots *slots; +struct kvm_memory_slot *memslot; + + kvm->arch.pv.stor_var =NULL ; + kvm->arch.pv.stor_base =__get_free_pages (GFP_KERNEL ,get_order (base)); +if (!kvm->arch.pv.stor_base) +return -ENOMEM ; +
arch/s390/kvm/pv.c line 48
Quoted 10 lines
arch/s390/kvm/pv.c new file +10
-0+/* +* Calculate current guest storage for allocation of the +* variable storage, which is based on the length in MB. +* +* Slots are sorted by GFN +*/ +mutex_lock (&kvm->slots_lock); + slots =kvm_memslots (kvm); + memslot = slots->memslots; + npages = memslot->base_gfn + memslot->npages;
What if
a) your guest has multiple memory slots
b) you hotplug memory and add memslots later
Do you dence that, and if so, how?
arch/s390/kvm/pv.c line 54
Quoted 6 lines
arch/s390/kvm/pv.c new file +6
-0+ +mutex_unlock (&kvm->slots_lock); + kvm->arch.pv.guest_len = npages *PAGE_SIZE ; + +/* Allocate variable storage */ + vlen =ALIGN (virt * ((npages *PAGE_SIZE ) /HPAGE_SIZE ),PAGE_SIZE );
I get the feeling that prot virt mainly consumes memory ;)
Quoted 225 lines
arch/s390/kvm/pv.c new file +183
-0+ vlen += uv_info.guest_virt_base_stor_len; + kvm->arch.pv.stor_var =vzalloc (vlen); +if (!kvm->arch.pv.stor_var) { +kvm_s390_pv_dealloc_vm (kvm); +return -ENOMEM ; + } +return 0 ; +} + +int kvm_s390_pv_destroy_vm (struct kvm *kvm) +{ +int rc; +u32 ret; + + rc =uv_cmd_nodata (kvm_s390_pv_handle (kvm), +UVC_CMD_DESTROY_SEC_CONF , &ret); +VM_EVENT (kvm,3 ,"PROTVIRT DESTROY VM: rc %x rrc %x" , + ret >>16 , ret &0x0000ffff ); +return rc; +} + +int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu) +{ +int rc =0 ; +u32 ret; + +if (kvm_s390_pv_handle_cpu (vcpu)) { + rc =uv_cmd_nodata (kvm_s390_pv_handle_cpu (vcpu), +UVC_CMD_DESTROY_SEC_CPU , + &ret); + +VCPU_EVENT (vcpu,3 ,"PROTVIRT DESTROY VCPU: cpu %d rc %x rrc %x" , + vcpu->vcpu_id, ret >>16 , ret &0x0000ffff ); + } + +free_pages (vcpu->arch.pv.stor_base, +get_order (uv_info.guest_cpu_stor_len)); +/* Clear cpu and vm handle */ +memset (&vcpu->arch.sie_block->reserved10,0 , +sizeof (vcpu->arch.sie_block->reserved10)); +memset (&vcpu->arch.pv,0 ,sizeof (vcpu->arch.pv)); + vcpu->arch.sie_block->sdf =0 ; +return rc; +} + +int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) +{ +int rc; +struct uv_cb_csc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CPU , + .header.len =sizeof (uvcb), + }; + +/* EEXIST and ENOENT? */ +if (kvm_s390_pv_handle_cpu (vcpu)) +return -EINVAL ; + + vcpu->arch.pv.stor_base =__get_free_pages (GFP_KERNEL , +get_order (uv_info.guest_cpu_stor_len)); +if (!vcpu->arch.pv.stor_base) +return -ENOMEM ; + +/* Input */ + uvcb.guest_handle =kvm_s390_pv_handle (vcpu->kvm); + uvcb.num = vcpu->arch.sie_block->icpua; + uvcb.state_origin = (u64 )vcpu->arch.sie_block; + uvcb.stor_origin = (u64 )vcpu->arch.pv.stor_base; + + rc =uv_call (0 , (u64)&uvcb); +VCPU_EVENT (vcpu,3 ,"PROTVIRT CREATE VCPU: cpu %d handle %llx rc %x rrc %x" , + vcpu->vcpu_id, uvcb.cpu_handle, uvcb.header.rc, + uvcb.header.rrc); + +/* Output */ + vcpu->arch.pv.handle = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_cpu = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_config =kvm_s390_pv_handle (vcpu->kvm); + vcpu->arch.sie_block->sdf =2 ; +if (!rc) +return 0 ; + +kvm_s390_pv_destroy_cpu (vcpu); +return -EINVAL ; +} + +int kvm_s390_pv_create_vm (struct kvm *kvm) +{ +int rc; + +struct uv_cb_cgc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CONF , + .header.len =sizeof (uvcb) + }; + +if (kvm_s390_pv_handle (kvm)) +return -EINVAL ; + +/* Inputs */ + uvcb.guest_stor_origin =0 ;/* MSO is 0 for KVM */ + uvcb.guest_stor_len = kvm->arch.pv.guest_len; + uvcb.guest_asce = kvm->arch.gmap->asce; + uvcb.conf_base_stor_origin = (u64 )kvm->arch.pv.stor_base; + uvcb.conf_var_stor_origin = (u64 )kvm->arch.pv.stor_var; + + rc =uv_call (0 , (u64)&uvcb); +VM_EVENT (kvm,3 ,"PROTVIRT CREATE VM: handle %llx len %llx rc %x rrc %x" , + uvcb.guest_handle, uvcb.guest_stor_len, uvcb.header.rc, + uvcb.header.rrc); + +/* Outputs */ + kvm->arch.pv.handle = uvcb.guest_handle; + +if (rc && (uvcb.header.rc &0x8000 )) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm); +return -EINVAL ; + } +return rc; +} + +int kvm_s390_pv_set_sec_parms (struct kvm *kvm, +void *hdr,u64 length) +{ +int rc; +struct uv_cb_ssc uvcb = { + .header.cmd =UVC_CMD_SET_SEC_CONF_PARAMS , + .header.len =sizeof (uvcb), + .sec_header_origin = (u64 )hdr, + .sec_header_len = length, + .guest_handle =kvm_s390_pv_handle (kvm), + }; + +if (!kvm_s390_pv_handle (kvm)) +return -EINVAL ; + + rc =uv_call (0 , (u64)&uvcb); +VM_EVENT (kvm,3 ,"PROTVIRT VM SET PARMS: rc %x rrc %x" , + uvcb.header.rc, uvcb.header.rrc); +if (rc) +return -EINVAL ; +return 0 ; +} + +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int i, rc =0 ; +struct uv_cb_unp uvcb = { + .header.cmd =UVC_CMD_UNPACK_IMG , + .header.len =sizeof (uvcb), + .guest_handle =kvm_s390_pv_handle (kvm), + .tweak[0 ] = tweak + }; + +if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) +return -EINVAL ; + + +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , + addr, size); +for (i =0 ; i < size /PAGE_SIZE ; i++) { + uvcb.gaddr = addr + i *PAGE_SIZE ; + uvcb.tweak[1 ] = i *PAGE_SIZE ; +retry: + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +continue ; +/* If not yet mapped fault and retry */ +if (uvcb.header.rc ==0x10a ) { + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (rc) +return rc; + goto retry; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +break ; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished with rc %x rrc %x" , + uvcb.header.rc, uvcb.header.rrc); +return rc; +}include/uapi/linux/kvm.h +26
-0@@ -1000,6 +1000,7 @@ struct kvm_ppc_resize_hpt {#define KVM_CAP_PMU_EVENT_FILTER 173#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175 +#define KVM_CAP_S390_PROTECTED 180#ifdef KVM_CAP_IRQ_ROUTING @@ -1461,6 +1462,38 @@ struct kvm_enc_region {/* Available with KVM_CAP_ARM_SVE */ #define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) +struct kvm_s390_pv_sec_parm { +__u64 origin; +__u64 length; +}; + +struct kvm_s390_pv_unp { +__u64 addr; +__u64 size; +__u64 tweak; +}; + +enum pv_cmd_id { +KVM_PV_VM_CREATE , +KVM_PV_VM_DESTROY , +KVM_PV_VM_SET_SEC_PARMS , +KVM_PV_VM_UNPACK , +KVM_PV_VM_VERIFY , +KVM_PV_VCPU_CREATE , +KVM_PV_VCPU_DESTROY , +}; + +struct kvm_pv_cmd { +__u32 cmd; +__u16 rc; +__u16 rrc;
include/uapi/linux/kvm.h struct kvm_enc_region { · line 1499
Quoted 10 lines
include/uapi/linux/kvm.h +7
-0+__u64 data; +}; + +/* Available with KVM_CAP_S390_SE */ +#define KVM_S390_PV_COMMAND _IOW(KVMIO, 0xc3, struct kvm_pv_cmd) +#define KVM_S390_PV_COMMAND_VCPU _IOW(KVMIO, 0xc4, struct kvm_pv_cmd) +/* Secure Encrypted Virtualization command */ enum sev_cmd_id {/* Guest initialization commands */
This is a lengthy patch and I ahven't explored anything yet :)
I do wonder if it makes sense to split this up. VM, VCPUs, parameters, Extract+verify ...
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
Quoted 602 lines · David Hildenbrand
Quoted 1 line · Janosch Frank
Let's add a KVM interface to create and destroy protected VMs.
More details please.
[...]
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2177
Quoted 12 lines
arch/s390/kvm/kvm-s390.c +11
-0+#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv (struct kvm *kvm,struct kvm_pv_cmd *cmd) +{ +int r =0 ; +void __user *argp = (void __user *)cmd->data; + +switch (cmd->cmd) { +case KVM_PV_VM_CREATE : { + r =kvm_s390_pv_alloc_vm (kvm); +if (r) +break ;So ... I can create multiple VMs?
Especially, I can call
KVM_PV_VM_CREATEtwo times, setting "kvm->arch.pv.stor_var= NULL and leaking memory" on the second call. Not sure if that's desirable.Shouldn't this be something like "
KVM_PV_VM_INIT" and then make sure it can only be called once?arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2190
Quoted 13 lines
arch/s390/kvm/kvm-s390.c +13
-0+ +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); +/* FMT 4 SIE needs esca */ + r =sca_switch_to_extended (kvm); +if (!r) + r =kvm_s390_pv_create_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_DESTROY : { +/* All VCPUs have to be destroyed before this call. */ Then please verify that? "
KVM_PV_VM_DEINIT"Also, who guarantees that user space calls this at all? Why is that needed? (IOW, when does user space call this?)
Quoted 297 lines
arch/s390/kvm/kvm-s390.c +141
-1+mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); + r =kvm_s390_pv_destroy_vm (kvm); +if (!r) +kvm_s390_pv_dealloc_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_SET_SEC_PARMS : { +struct kvm_s390_pv_sec_parm parms = {}; +void *hdr; + + r = -EFAULT ; +if (copy_from_user (&parms, argp,sizeof (parms))) +break ; + +/* Currently restricted to 8KB */ + r = -EINVAL ; +if (parms.length >PAGE_SIZE *2 ) +break ; + + r = -ENOMEM ; + hdr =vmalloc (parms.length); +if (!hdr) +break ; + + r = -EFAULT ; +if (!copy_from_user (hdr, (void __user *)parms.origin, + parms.length)) + r =kvm_s390_pv_set_sec_parms (kvm, hdr, parms.length); + +vfree (hdr); +break ; + } +case KVM_PV_VM_UNPACK : { +struct kvm_s390_pv_unp unp = {}; + + r = -EFAULT ; +if (copy_from_user (&unp, argp,sizeof (unp))) +break ; + + r =kvm_s390_pv_unpack (kvm, unp.addr, unp.size, unp.tweak); +break ; + } +case KVM_PV_VM_VERIFY : { +u32 ret; + + r = -EINVAL ; +if (!kvm_s390_pv_is_protected (kvm)) +break ; + + r =uv_cmd_nodata (kvm_s390_pv_handle (kvm), +UVC_CMD_VERIFY_IMG , + &ret); +VM_EVENT (kvm,3 ,"PROTVIRT VERIFY: rc %x rrc %x" , + ret >>16 , ret &0x0000ffff ); +break ; + } +default : + return -ENOTTY; + } +return r; +} +#endif +long kvm_arch_vm_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg) {@@ -2254,6 +2351,22 @@ long kvm_arch_vm_ioctl(struct file *filp,mutex_unlock (&kvm->slots_lock);break ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +case KVM_S390_PV_COMMAND : { +struct kvm_pv_cmd args; + + r = -EINVAL ; +if (!is_prot_virt_host ()) +break ; + + r = -EFAULT ; +if (copy_from_user (&args, argp,sizeof (args))) +break ; + + r =kvm_s390_handle_pv (kvm, &args); +break ; + } +#endif default : r = -ENOTTY ; }@@ -2529,6 +2642,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)if (vcpu->kvm->arch.use_cmma)kvm_s390_vcpu_unsetup_cmma (vcpu); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_handle_cpu (vcpu)) +kvm_s390_pv_destroy_cpu (vcpu);free_page ((unsigned long )(vcpu->arch.sie_block));kvm_vcpu_uninit (vcpu);@@ -2555,8 +2671,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm) {kvm_free_vcpus (kvm);sca_dispose (kvm); -debug_unregister (kvm->arch.dbf);kvm_s390_gisa_destroy (kvm); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_is_protected (kvm)) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm); + } +debug_unregister (kvm->arch.dbf);free_page ((unsigned long )kvm->arch.sie_page2);if (!kvm_is_ucontrol (kvm))gmap_remove (kvm->arch.gmap);@@ -2652,6 +2773,9 @@ static int sca_switch_to_extended(struct kvm *kvm)unsigned int vcpu_idx;u32 scaol, scaoh; +if (kvm->arch.use_esca) +return 0 ; + new_sca =alloc_pages_exact (sizeof (*new_sca),GFP_KERNEL |__GFP_ZERO);if (!new_sca)return -ENOMEM ;@@ -3073,6 +3197,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, rc =kvm_vcpu_init (vcpu, kvm, id);if (rc) goto out_free_sie_block; + +if (kvm_s390_pv_is_protected (kvm)) { + rc =kvm_s390_pv_create_cpu (vcpu); +if (rc) { +kvm_vcpu_uninit (vcpu); + goto out_free_sie_block; + } + } +VM_EVENT (kvm,3 ,"create cpu %d at 0x%pK, sie block at 0x%pK" , id, vcpu, vcpu->arch.sie_block);trace_kvm_s390_create_vcpu (id, vcpu, vcpu->arch.sie_block);@@ -4338,6 +4471,28 @@ long kvm_arch_vcpu_async_ioctl(struct file *filp,return -ENOIOCTLCMD ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv_vcpu (struct kvm_vcpu *vcpu, +struct kvm_pv_cmd *cmd) +{ +int r =0 ; + +switch (cmd->cmd) { +case KVM_PV_VCPU_CREATE : { + r =kvm_s390_pv_create_cpu (vcpu); +break ; + } +case KVM_PV_VCPU_DESTROY : { + r =kvm_s390_pv_destroy_cpu (vcpu); +break ; + } +default : + r = -ENOTTY ; + } +return r; +} +#endif +long kvm_arch_vcpu_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg) {@@ -4470,6 +4625,22 @@ long kvm_arch_vcpu_ioctl(struct file *filp, irq_state.len);break ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +case KVM_S390_PV_COMMAND_VCPU : { +struct kvm_pv_cmd args; + + r = -EINVAL ; +if (!is_prot_virt_host ()) +break ; + + r = -EFAULT ; +if (copy_from_user (&args, argp,sizeof (args))) +break ; + + r =kvm_s390_handle_pv_vcpu (vcpu, &args); +break ; + } +#endif default : r = -ENOTTY ; }arch/s390/kvm/kvm-s390.h +47
-0@@ -196,6 +196,53 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)return kvm->arch.user_cpu_state_ctrl !=0 ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +/* implemented in pv.c */ +void kvm_s390_pv_unpin (struct kvm *kvm); +void kvm_s390_pv_dealloc_vm (struct kvm *kvm); +int kvm_s390_pv_alloc_vm (struct kvm *kvm); +int kvm_s390_pv_create_vm (struct kvm *kvm); +int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_destroy_vm (struct kvm *kvm); +int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_set_sec_parms (struct kvm *kvm,void *hdr,u64 length); +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak); +int kvm_s390_pv_verify (struct kvm *kvm); + +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) +{ +return !!kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle (struct kvm *kvm) +{ +return kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) +{ +return vcpu->arch.pv.handle; +} +#else +static inline void kvm_s390_pv_unpin (struct kvm *kvm) {} +static inline void kvm_s390_pv_dealloc_vm (struct kvm *kvm) {} +static inline int kvm_s390_pv_alloc_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_destroy_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_set_sec_parms (struct kvm *kvm, +u64 origin,u64 length) {return 0 ; } +static inline int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr, +unsigned long size,unsigned long tweak) +{return 0 ; } +static inline int kvm_s390_pv_verify (struct kvm *kvm) {return 0 ; } +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +#endif +/* implemented in interrupt.c */ int kvm_s390_handle_wait (struct kvm_vcpu *vcpu);void kvm_s390_vcpu_wakeup (struct kvm_vcpu *vcpu);arch/s390/kvm/pv.c new file +38
-0@@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Hosting Secure Execution virtual machines +* +* Copyright IBM Corp. 2019 +* Author(s): Janosch Frank <[email protected]> +*/ +#include <linux/kvm.h> +#include <linux/kvm_host.h> +#include <linux/pagemap.h> +#include <asm/pgalloc.h> +#include <asm/gmap.h> +#include <asm/uv.h> +#include <asm/gmap.h> +#include <asm/mman.h> +#include "kvm-s390.h" + +void kvm_s390_pv_dealloc_vm (struct kvm *kvm) +{ +vfree (kvm->arch.pv.stor_var); +free_pages (kvm->arch.pv.stor_base, +get_order (uv_info.guest_base_stor_len)); +memset (&kvm->arch.pv,0 ,sizeof (kvm->arch.pv)); +} + +int kvm_s390_pv_alloc_vm (struct kvm *kvm) +{ +unsigned long base = uv_info.guest_base_stor_len; +unsigned long virt = uv_info.guest_virt_var_stor_len; +unsigned long npages =0 , vlen =0 ; +struct kvm_memslots *slots; +struct kvm_memory_slot *memslot; + + kvm->arch.pv.stor_var =NULL ; + kvm->arch.pv.stor_base =__get_free_pages (GFP_KERNEL ,get_order (base)); +if (!kvm->arch.pv.stor_base) +return -ENOMEM ; +arch/s390/kvm/pv.c line 48
Quoted 10 lines
arch/s390/kvm/pv.c new file +10
-0+/* +* Calculate current guest storage for allocation of the +* variable storage, which is based on the length in MB. +* +* Slots are sorted by GFN +*/ +mutex_lock (&kvm->slots_lock); + slots =kvm_memslots (kvm); + memslot = slots->memslots; + npages = memslot->base_gfn + memslot->npages;What if
a) your guest has multiple memory slots
b) you hotplug memory and add memslots laterDo you dence that, and if so, how?
arch/s390/kvm/pv.c line 54
Quoted 6 lines
arch/s390/kvm/pv.c new file +6
-0+ +mutex_unlock (&kvm->slots_lock); + kvm->arch.pv.guest_len = npages *PAGE_SIZE ; + +/* Allocate variable storage */ + vlen =ALIGN (virt * ((npages *PAGE_SIZE ) /HPAGE_SIZE ),PAGE_SIZE );I get the feeling that prot virt mainly consumes memory ;)
Quoted 229 lines
arch/s390/kvm/pv.c new file +183
-0+ vlen += uv_info.guest_virt_base_stor_len; + kvm->arch.pv.stor_var =vzalloc (vlen); +if (!kvm->arch.pv.stor_var) { +kvm_s390_pv_dealloc_vm (kvm); +return -ENOMEM ; + } +return 0 ; +} + +int kvm_s390_pv_destroy_vm (struct kvm *kvm) +{ +int rc; +u32 ret; + + rc =uv_cmd_nodata (kvm_s390_pv_handle (kvm), +UVC_CMD_DESTROY_SEC_CONF , &ret); +VM_EVENT (kvm,3 ,"PROTVIRT DESTROY VM: rc %x rrc %x" , + ret >>16 , ret &0x0000ffff ); +return rc; +} + +int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu) +{ +int rc =0 ; +u32 ret; + +if (kvm_s390_pv_handle_cpu (vcpu)) { + rc =uv_cmd_nodata (kvm_s390_pv_handle_cpu (vcpu), +UVC_CMD_DESTROY_SEC_CPU , + &ret); + +VCPU_EVENT (vcpu,3 ,"PROTVIRT DESTROY VCPU: cpu %d rc %x rrc %x" , + vcpu->vcpu_id, ret >>16 , ret &0x0000ffff ); + } + +free_pages (vcpu->arch.pv.stor_base, +get_order (uv_info.guest_cpu_stor_len)); +/* Clear cpu and vm handle */ +memset (&vcpu->arch.sie_block->reserved10,0 , +sizeof (vcpu->arch.sie_block->reserved10)); +memset (&vcpu->arch.pv,0 ,sizeof (vcpu->arch.pv)); + vcpu->arch.sie_block->sdf =0 ; +return rc; +} + +int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) +{ +int rc; +struct uv_cb_csc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CPU , + .header.len =sizeof (uvcb), + }; + +/* EEXIST and ENOENT? */ +if (kvm_s390_pv_handle_cpu (vcpu)) +return -EINVAL ; + + vcpu->arch.pv.stor_base =__get_free_pages (GFP_KERNEL , +get_order (uv_info.guest_cpu_stor_len)); +if (!vcpu->arch.pv.stor_base) +return -ENOMEM ; + +/* Input */ + uvcb.guest_handle =kvm_s390_pv_handle (vcpu->kvm); + uvcb.num = vcpu->arch.sie_block->icpua; + uvcb.state_origin = (u64 )vcpu->arch.sie_block; + uvcb.stor_origin = (u64 )vcpu->arch.pv.stor_base; + + rc =uv_call (0 , (u64)&uvcb); +VCPU_EVENT (vcpu,3 ,"PROTVIRT CREATE VCPU: cpu %d handle %llx rc %x rrc %x" , + vcpu->vcpu_id, uvcb.cpu_handle, uvcb.header.rc, + uvcb.header.rrc); + +/* Output */ + vcpu->arch.pv.handle = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_cpu = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_config =kvm_s390_pv_handle (vcpu->kvm); + vcpu->arch.sie_block->sdf =2 ; +if (!rc) +return 0 ; + +kvm_s390_pv_destroy_cpu (vcpu); +return -EINVAL ; +} + +int kvm_s390_pv_create_vm (struct kvm *kvm) +{ +int rc; + +struct uv_cb_cgc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CONF , + .header.len =sizeof (uvcb) + }; + +if (kvm_s390_pv_handle (kvm)) +return -EINVAL ; + +/* Inputs */ + uvcb.guest_stor_origin =0 ;/* MSO is 0 for KVM */ + uvcb.guest_stor_len = kvm->arch.pv.guest_len; + uvcb.guest_asce = kvm->arch.gmap->asce; + uvcb.conf_base_stor_origin = (u64 )kvm->arch.pv.stor_base; + uvcb.conf_var_stor_origin = (u64 )kvm->arch.pv.stor_var; + + rc =uv_call (0 , (u64)&uvcb); +VM_EVENT (kvm,3 ,"PROTVIRT CREATE VM: handle %llx len %llx rc %x rrc %x" , + uvcb.guest_handle, uvcb.guest_stor_len, uvcb.header.rc, + uvcb.header.rrc); + +/* Outputs */ + kvm->arch.pv.handle = uvcb.guest_handle; + +if (rc && (uvcb.header.rc &0x8000 )) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm); +return -EINVAL ; + } +return rc; +} + +int kvm_s390_pv_set_sec_parms (struct kvm *kvm, +void *hdr,u64 length) +{ +int rc; +struct uv_cb_ssc uvcb = { + .header.cmd =UVC_CMD_SET_SEC_CONF_PARAMS , + .header.len =sizeof (uvcb), + .sec_header_origin = (u64 )hdr, + .sec_header_len = length, + .guest_handle =kvm_s390_pv_handle (kvm), + }; + +if (!kvm_s390_pv_handle (kvm)) +return -EINVAL ; + + rc =uv_call (0 , (u64)&uvcb); +VM_EVENT (kvm,3 ,"PROTVIRT VM SET PARMS: rc %x rrc %x" , + uvcb.header.rc, uvcb.header.rrc); +if (rc) +return -EINVAL ; +return 0 ; +} + +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int i, rc =0 ; +struct uv_cb_unp uvcb = { + .header.cmd =UVC_CMD_UNPACK_IMG , + .header.len =sizeof (uvcb), + .guest_handle =kvm_s390_pv_handle (kvm), + .tweak[0 ] = tweak + }; + +if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) +return -EINVAL ; + + +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , + addr, size); +for (i =0 ; i < size /PAGE_SIZE ; i++) { + uvcb.gaddr = addr + i *PAGE_SIZE ; + uvcb.tweak[1 ] = i *PAGE_SIZE ; +retry: + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +continue ; +/* If not yet mapped fault and retry */ +if (uvcb.header.rc ==0x10a ) { + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (rc) +return rc; + goto retry; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +break ; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished with rc %x rrc %x" , + uvcb.header.rc, uvcb.header.rrc); +return rc; +}include/uapi/linux/kvm.h +31
-0@@ -1000,6 +1000,7 @@ struct kvm_ppc_resize_hpt {#define KVM_CAP_PMU_EVENT_FILTER 173#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175 +#define KVM_CAP_S390_PROTECTED 180#ifdef KVM_CAP_IRQ_ROUTING @@ -1461,6 +1462,38 @@ struct kvm_enc_region {/* Available with KVM_CAP_ARM_SVE */ #define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) +struct kvm_s390_pv_sec_parm { +__u64 origin; +__u64 length; +}; + +struct kvm_s390_pv_unp { +__u64 addr; +__u64 size; +__u64 tweak; +}; + +enum pv_cmd_id { +KVM_PV_VM_CREATE , +KVM_PV_VM_DESTROY , +KVM_PV_VM_SET_SEC_PARMS , +KVM_PV_VM_UNPACK , +KVM_PV_VM_VERIFY , +KVM_PV_VCPU_CREATE , +KVM_PV_VCPU_DESTROY , +}; + +struct kvm_pv_cmd { +__u32 cmd; +__u16 rc; +__u16 rrc; +__u64 data; +}; + +/* Available with KVM_CAP_S390_SE */ +#define KVM_S390_PV_COMMAND _IOW(KVMIO, 0xc3, struct kvm_pv_cmd)
Quoted 8 lines
include/uapi/linux/kvm.h struct kvm_enc_region { · line 1499
Quoted 6 lines
include/uapi/linux/kvm.h +2
-0+#define KVM_S390_PV_COMMAND_VCPU _IOW(KVMIO, 0xc4, struct kvm_pv_cmd) +/* Secure Encrypted Virtualization command */ enum sev_cmd_id {/* Guest initialization commands */ This is a lengthy patch and I ahven't explored anything yet :)
lol, everything. :)
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
In reply to Janosch FrankQuoted 13 lines · Janosch Frank
Let's add a KVM interface to create and destroy protected VMs.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 24 +++- arch/s390/include/asm/uv.h | 110 ++++++++++++++ arch/s390/kvm/Makefile | 2 +- arch/s390/kvm/kvm-s390.c | 173 +++++++++++++++++++++- arch/s390/kvm/kvm-s390.h | 47 ++++++ arch/s390/kvm/pv.c | 237 +++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 33 +++++ 7 files changed, 622 insertions(+), 4 deletions(-) create mode 100644 arch/s390/kvm/pv.c
[...]
Quoted 10 lines
arch/s390/kvm/kvm-s390.c +10
-0+case KVM_PV_VM_UNPACK : { +struct kvm_s390_pv_unp unp = {}; + + r = -EFAULT ; +if (copy_from_user (&unp, argp,sizeof (unp))) +break ; + + r =kvm_s390_pv_unpack (kvm, unp.addr, unp.size, unp.tweak); +break ; + }
[....]
Quoted 7 lines
arch/s390/kvm/pv.c new file +7
-0+int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int i, rc =0 ; +struct uv_cb_unp uvcb = { + .header.cmd =UVC_CMD_UNPACK_IMG , + .header.len =sizeof (uvcb),
arch/s390/kvm/pv.c line 214
Quoted 10 lines
arch/s390/kvm/pv.c new file +10
-0+ .guest_handle = kvm_s390_pv_handle(kvm), + .tweak[0] = tweak + }; + +if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) +return -EINVAL ; + + +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , + addr, size);
Does it make sense to check for addr and addr+size to be within the memory size of the guest? The uv_call or gmap_fault will fail later on, but we could do an early exit if the the site is wrong.
Quoted 22 lines
arch/s390/kvm/pv.c new file +19
-0+for (i =0 ; i < size /PAGE_SIZE ; i++) { + uvcb.gaddr = addr + i *PAGE_SIZE ; + uvcb.tweak[1 ] = i *PAGE_SIZE ; +retry: + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +continue ; +/* If not yet mapped fault and retry */ +if (uvcb.header.rc ==0x10a ) { + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (rc) +return rc; + goto retry; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +break ; + }
[...]
Janosch Frank
maintainerRe: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
Quoted 46 lines · Christian Borntraeger
Quoted 13 lines · Janosch Frank
Let's add a KVM interface to create and destroy protected VMs.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 24 +++- arch/s390/include/asm/uv.h | 110 ++++++++++++++ arch/s390/kvm/Makefile | 2 +- arch/s390/kvm/kvm-s390.c | 173 +++++++++++++++++++++- arch/s390/kvm/kvm-s390.h | 47 ++++++ arch/s390/kvm/pv.c | 237 +++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 33 +++++ 7 files changed, 622 insertions(+), 4 deletions(-) create mode 100644 arch/s390/kvm/pv.c[...]
Quoted 10 lines
arch/s390/kvm/kvm-s390.c +10
-0+case KVM_PV_VM_UNPACK : { +struct kvm_s390_pv_unp unp = {}; + + r = -EFAULT ; +if (copy_from_user (&unp, argp,sizeof (unp))) +break ; + + r =kvm_s390_pv_unpack (kvm, unp.addr, unp.size, unp.tweak); +break ; + }[....]
Quoted 13 lines
arch/s390/kvm/pv.c new file +13
-0+int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int i, rc =0 ; +struct uv_cb_unp uvcb = { + .header.cmd =UVC_CMD_UNPACK_IMG , + .header.len =sizeof (uvcb), + .guest_handle =kvm_s390_pv_handle (kvm), + .tweak[0 ] = tweak + }; + +if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) +return -EINVAL ;
Quoted 8 lines
arch/s390/kvm/pv.c line 214
Quoted 4 lines
arch/s390/kvm/pv.c new file +4
-0+ + +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , + addr, size);Does it make sense to check for addr and addr+size to be within the memory size of the guest? The
uv_callorgmap_faultwill fail later on, but we could do an early exit if the the site is wrong.
Yeah, Marc already brought that up because of a testcase of his. I'll add a check, but before that I need to understand what makes us loop so long that we get RCU warnings.
Quoted 28 lines
Quoted 26 lines
arch/s390/kvm/pv.c new file +19
-0+for (i =0 ; i < size /PAGE_SIZE ; i++) { + uvcb.gaddr = addr + i *PAGE_SIZE ; + uvcb.tweak[1 ] = i *PAGE_SIZE ; +retry: + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +continue ; +/* If not yet mapped fault and retry */ +if (uvcb.header.rc ==0x10a ) { + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (rc) +return rc; + goto retry; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +break ; + }[...]
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
In reply to Janosch FrankQuoted 11 lines · On Thu, 24 Oct 2019 07:40:26 -0400 Janosch Frank <[email protected]> wrote:
Let's add a KVM interface to create and destroy protected VMs.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 24 +++- arch/s390/include/asm/uv.h | 110 ++++++++++++++ arch/s390/kvm/Makefile | 2 +- arch/s390/kvm/kvm-s390.c | 173 +++++++++++++++++++++- arch/s390/kvm/kvm-s390.h | 47 ++++++ arch/s390/kvm/pv.c | 237 +++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 33 +++++
Any new ioctls and caps probably want a mention in Documentation/virt/kvm/api.txt :)
Quoted 2 lines
7 files changed, 622 insertions(+), 4 deletions(-) create mode 100644 arch/s390/kvm/pv.c
(...)
Quoted 27 lines
arch/s390/kvm/kvm-s390.c +23
-0@@ -2157,6 +2164,96 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,return r; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv (struct kvm *kvm,struct kvm_pv_cmd *cmd) +{ +int r =0 ; +void __user *argp = (void __user *)cmd->data; + +switch (cmd->cmd) { +case KVM_PV_VM_CREATE : { + r =kvm_s390_pv_alloc_vm (kvm); +if (r) +break ; + +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); +/* FMT 4 SIE needs esca */ + r =sca_switch_to_extended (kvm); +if (!r) + r =kvm_s390_pv_create_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_DESTROY : {
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2199
Quoted 10 lines
arch/s390/kvm/kvm-s390.c +10
-0+/* All VCPUs have to be destroyed before this call. */ +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); + r =kvm_s390_pv_destroy_vm (kvm); +if (!r) +kvm_s390_pv_dealloc_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + }
Would be helpful to have some code that shows when/how these are called
- do you have any plans to post something soon?
(...)
arch/s390/kvm/kvm-s390.c void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) · line 2646
Quoted 6 lines
arch/s390/kvm/kvm-s390.c +2
-0@@ -2529,6 +2642,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)if (vcpu->kvm->arch.use_cmma)kvm_s390_vcpu_unsetup_cmma (vcpu); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_handle_cpu (vcpu))
I was a bit confused by that function name... maybe kvm_s390_pv_cpu_get_handle()?
Also, if this always returns 0 if the config option is off, you probably don't need to check for that option?
Quoted 5 lines
arch/s390/kvm/kvm-s390.c +1
-0+kvm_s390_pv_destroy_cpu (vcpu);free_page ((unsigned long )(vcpu->arch.sie_block));kvm_vcpu_uninit (vcpu);
arch/s390/kvm/kvm-s390.c void kvm_arch_destroy_vm(struct kvm *kvm) · line 2678
Quoted 9 lines
arch/s390/kvm/kvm-s390.c +4
-1@@ -2555,8 +2671,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm) {kvm_free_vcpus (kvm);sca_dispose (kvm); -debug_unregister (kvm->arch.dbf);kvm_s390_gisa_destroy (kvm); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_is_protected (kvm)) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm);
It seems the pv vm can be either destroyed via the ioctl above or in the course of normal vm destruction. When is which way supposed to be used? Also, it seems kvm_s390_pv_destroy_vm() can fail -- can that be a problem in this code path?
Quoted 5 lines
arch/s390/kvm/kvm-s390.c +2
-0+ } +debug_unregister (kvm->arch.dbf);free_page ((unsigned long )kvm->arch.sie_page2);if (!kvm_is_ucontrol (kvm))gmap_remove (kvm->arch.gmap);
(...)
Quoted 18 lines
arch/s390/kvm/kvm-s390.h +10
-0@@ -196,6 +196,53 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)return kvm->arch.user_cpu_state_ctrl !=0 ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +/* implemented in pv.c */ +void kvm_s390_pv_unpin (struct kvm *kvm); +void kvm_s390_pv_dealloc_vm (struct kvm *kvm); +int kvm_s390_pv_alloc_vm (struct kvm *kvm); +int kvm_s390_pv_create_vm (struct kvm *kvm); +int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_destroy_vm (struct kvm *kvm); +int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_set_sec_parms (struct kvm *kvm,void *hdr,u64 length);
arch/s390/kvm/kvm-s390.h static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm) · line 218
Quoted 10 lines
arch/s390/kvm/kvm-s390.h +10
-0+int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak); +int kvm_s390_pv_verify (struct kvm *kvm); + +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) +{ +return !!kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle (struct kvm *kvm)
This function name is less confusing than the one below, but maybe also rename this to kvm_s390_pv_get_handle() for consistency?
Quoted 30 lines
arch/s390/kvm/kvm-s390.h +27
-0+{ +return kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) +{ +return vcpu->arch.pv.handle; +} +#else +static inline void kvm_s390_pv_unpin (struct kvm *kvm) {} +static inline void kvm_s390_pv_dealloc_vm (struct kvm *kvm) {} +static inline int kvm_s390_pv_alloc_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_destroy_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_set_sec_parms (struct kvm *kvm, +u64 origin,u64 length) {return 0 ; } +static inline int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr, +unsigned long size,unsigned long tweak) +{return 0 ; } +static inline int kvm_s390_pv_verify (struct kvm *kvm) {return 0 ; } +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +#endif +/* implemented in interrupt.c */ int kvm_s390_handle_wait (struct kvm_vcpu *vcpu);void kvm_s390_vcpu_wakeup (struct kvm_vcpu *vcpu);
(...)
arch/s390/kvm/kvm-s390.h
Quoted 9 lines
arch/s390/kvm/kvm-s390.h +9
-0+int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) +{ +int rc; +struct uv_cb_csc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CPU , + .header.len =sizeof (uvcb), + }; + +/* EEXIST and ENOENT? */
?
Quoted 20 lines
arch/s390/kvm/kvm-s390.h +20
-0+if (kvm_s390_pv_handle_cpu (vcpu)) +return -EINVAL ; + + vcpu->arch.pv.stor_base =__get_free_pages (GFP_KERNEL , +get_order (uv_info.guest_cpu_stor_len)); +if (!vcpu->arch.pv.stor_base) +return -ENOMEM ; + +/* Input */ + uvcb.guest_handle =kvm_s390_pv_handle (vcpu->kvm); + uvcb.num = vcpu->arch.sie_block->icpua; + uvcb.state_origin = (u64 )vcpu->arch.sie_block; + uvcb.stor_origin = (u64 )vcpu->arch.pv.stor_base; + + rc =uv_call (0 , (u64)&uvcb); +VCPU_EVENT (vcpu,3 ,"PROTVIRT CREATE VCPU: cpu %d handle %llx rc %x rrc %x" , + vcpu->vcpu_id, uvcb.cpu_handle, uvcb.header.rc, + uvcb.header.rrc); + +/* Output */
arch/s390/kvm/kvm-s390.h
Quoted 10 lines
arch/s390/kvm/kvm-s390.h +10
-0+ vcpu->arch.pv.handle = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_cpu = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_config =kvm_s390_pv_handle (vcpu->kvm); + vcpu->arch.sie_block->sdf =2 ; +if (!rc) +return 0 ; + +kvm_s390_pv_destroy_cpu (vcpu); +return -EINVAL ; +}
(...)
Only a quick readthrough, as this patch is longish.
Janosch Frank
maintainerRe: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
Quoted 15 lines · Cornelia Huck
Quoted 11 lines · On Thu, 24 Oct 2019 07:40:26 -0400 Janosch Frank <[email protected]> wrote:
Let's add a KVM interface to create and destroy protected VMs.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 24 +++- arch/s390/include/asm/uv.h | 110 ++++++++++++++ arch/s390/kvm/Makefile | 2 +- arch/s390/kvm/kvm-s390.c | 173 +++++++++++++++++++++- arch/s390/kvm/kvm-s390.h | 47 ++++++ arch/s390/kvm/pv.c | 237 +++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 33 +++++
Quoted 2 lines
Any new ioctls and caps probably want a mention in
Documentation/virt/kvm/api.txt:)
Noted
Quoted 38 lines
Quoted 3 lines
7 files changed, 622 insertions(+), 4 deletions(-) create mode 100644 arch/s390/kvm/pv.c(...)
Quoted 32 lines
arch/s390/kvm/kvm-s390.c +28
-0@@ -2157,6 +2164,96 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,return r; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv (struct kvm *kvm,struct kvm_pv_cmd *cmd) +{ +int r =0 ; +void __user *argp = (void __user *)cmd->data; + +switch (cmd->cmd) { +case KVM_PV_VM_CREATE : { + r =kvm_s390_pv_alloc_vm (kvm); +if (r) +break ; + +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); +/* FMT 4 SIE needs esca */ + r =sca_switch_to_extended (kvm); +if (!r) + r =kvm_s390_pv_create_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_DESTROY : { +/* All VCPUs have to be destroyed before this call. */ +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); + r =kvm_s390_pv_destroy_vm (kvm); +if (!r)
Quoted 8 lines
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2199
Quoted 5 lines
arch/s390/kvm/kvm-s390.c +5
-0+kvm_s390_pv_dealloc_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + }Would be helpful to have some code that shows when/how these are called
- do you have any plans to post something soon?
Qemu patches will be in internal review soonish and afterwards I'll post them upstream
Quoted 5 lines
(...)
Quoted 2 lines
(quoted diff) +0
-0@@ -2529,6 +2642,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
Quoted 7 lines
arch/s390/kvm/kvm-s390.c void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) · line 2646
Quoted 4 lines
arch/s390/kvm/kvm-s390.c +2
-0if (vcpu->kvm->arch.use_cmma)kvm_s390_vcpu_unsetup_cmma (vcpu); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_handle_cpu (vcpu))I was a bit confused by that function name... maybe
kvm_s390_pv_cpu_get_handle()?
Sure
Quoted 3 lines
Also, if this always returns 0 if the config option is off, you probably don't need to check for that option?
Hmm, if we decide to remove the config option altogether then it's not needed anyway and I think that's what Christian wants.
Quoted 4 lines
Quoted 4 lines
arch/s390/kvm/kvm-s390.c +1
-0+kvm_s390_pv_destroy_cpu (vcpu);free_page ((unsigned long )(vcpu->arch.sie_block));
Quoted 16 lines
arch/s390/kvm/kvm-s390.c void kvm_arch_destroy_vm(struct kvm *kvm) · line 2678
Quoted 11 lines
arch/s390/kvm/kvm-s390.c +4
-1kvm_vcpu_uninit (vcpu);@@ -2555,8 +2671,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm) {kvm_free_vcpus (kvm);sca_dispose (kvm); -debug_unregister (kvm->arch.dbf);kvm_s390_gisa_destroy (kvm); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_is_protected (kvm)) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm);It seems the pv vm can be either destroyed via the ioctl above or in the course of normal vm destruction. When is which way supposed to be used? Also, it seems
kvm_s390_pv_destroy_vm()can fail -- can that be a problem in this code path?
On a reboot we need to tear down the protected VM and boot from unprotected mode again. If the VM shuts down we go through this cleanup path. If it fails the kernel will loose the memory that was allocated to start the VM.
Quoted 32 lines
Quoted 6 lines
arch/s390/kvm/kvm-s390.c +2
-0+ } +debug_unregister (kvm->arch.dbf);free_page ((unsigned long )kvm->arch.sie_page2);if (!kvm_is_ucontrol (kvm))gmap_remove (kvm->arch.gmap);(...)
Quoted 23 lines
arch/s390/kvm/kvm-s390.h +15
-0@@ -196,6 +196,53 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)return kvm->arch.user_cpu_state_ctrl !=0 ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +/* implemented in pv.c */ +void kvm_s390_pv_unpin (struct kvm *kvm); +void kvm_s390_pv_dealloc_vm (struct kvm *kvm); +int kvm_s390_pv_alloc_vm (struct kvm *kvm); +int kvm_s390_pv_create_vm (struct kvm *kvm); +int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_destroy_vm (struct kvm *kvm); +int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_set_sec_parms (struct kvm *kvm,void *hdr,u64 length); +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak); +int kvm_s390_pv_verify (struct kvm *kvm); + +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm)
Quoted 8 lines
arch/s390/kvm/kvm-s390.h static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm) · line 218
Quoted 5 lines
arch/s390/kvm/kvm-s390.h +5
-0+{ +return !!kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle (struct kvm *kvm)This function name is less confusing than the one below, but maybe also rename this to
kvm_s390_pv_get_handle()for consistency?
kvm_s390_pv_kvm_handle?
Quoted 34 lines
Quoted 31 lines
arch/s390/kvm/kvm-s390.h +27
-0+{ +return kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) +{ +return vcpu->arch.pv.handle; +} +#else +static inline void kvm_s390_pv_unpin (struct kvm *kvm) {} +static inline void kvm_s390_pv_dealloc_vm (struct kvm *kvm) {} +static inline int kvm_s390_pv_alloc_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_destroy_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_set_sec_parms (struct kvm *kvm, +u64 origin,u64 length) {return 0 ; } +static inline int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr, +unsigned long size,unsigned long tweak) +{return 0 ; } +static inline int kvm_s390_pv_verify (struct kvm *kvm) {return 0 ; } +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +#endif +/* implemented in interrupt.c */ int kvm_s390_handle_wait (struct kvm_vcpu *vcpu);void kvm_s390_vcpu_wakeup (struct kvm_vcpu *vcpu);(...)
Quoted 11 lines
arch/s390/kvm/kvm-s390.h
Quoted 9 lines
arch/s390/kvm/kvm-s390.h +9
-0+int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) +{ +int rc; +struct uv_cb_csc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CPU , + .header.len =sizeof (uvcb), + }; + +/* EEXIST and ENOENT? */ ?
I was asking myself if EEXIST or ENOENT would be better error values than EINVAL.
Quoted 36 lines
Quoted 21 lines
arch/s390/kvm/kvm-s390.h +20
-0+if (kvm_s390_pv_handle_cpu (vcpu)) +return -EINVAL ; + + vcpu->arch.pv.stor_base =__get_free_pages (GFP_KERNEL , +get_order (uv_info.guest_cpu_stor_len)); +if (!vcpu->arch.pv.stor_base) +return -ENOMEM ; + +/* Input */ + uvcb.guest_handle =kvm_s390_pv_handle (vcpu->kvm); + uvcb.num = vcpu->arch.sie_block->icpua; + uvcb.state_origin = (u64 )vcpu->arch.sie_block; + uvcb.stor_origin = (u64 )vcpu->arch.pv.stor_base; + + rc =uv_call (0 , (u64)&uvcb); +VCPU_EVENT (vcpu,3 ,"PROTVIRT CREATE VCPU: cpu %d handle %llx rc %x rrc %x" , + vcpu->vcpu_id, uvcb.cpu_handle, uvcb.header.rc, + uvcb.header.rrc); + +/* Output */ arch/s390/kvm/kvm-s390.h
Quoted 10 lines
arch/s390/kvm/kvm-s390.h +10
-0+ vcpu->arch.pv.handle = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_cpu = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_config =kvm_s390_pv_handle (vcpu->kvm); + vcpu->arch.sie_block->sdf =2 ; +if (!rc) +return 0 ; + +kvm_s390_pv_destroy_cpu (vcpu); +return -EINVAL ; +}(...)
Only a quick readthrough, as this patch is longish.
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
Quoted 8 lines · On Fri, 8 Nov 2019 08:36:35 +0100 Janosch Frank <[email protected]> wrote:
Quoted 7 lines · Cornelia Huck
Quoted 4 lines · On Thu, 24 Oct 2019 07:40:26 -0400 Janosch Frank <[email protected]> wrote:
arch/s390/kvm/kvm-s390.c +0
-0@@ -2157,6 +2164,96 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,return r; }
Quoted 16 lines
Quoted 8 lines
Quoted 8 lines
arch/s390/kvm/kvm-s390.c +8
-0+#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv (struct kvm *kvm,struct kvm_pv_cmd *cmd) +{ +int r =0 ; +void __user *argp = (void __user *)cmd->data; + +switch (cmd->cmd) { +case KVM_PV_VM_CREATE : {Quoted 8 lines
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2182
Quoted 8 lines
arch/s390/kvm/kvm-s390.c +8
-0+ r =kvm_s390_pv_alloc_vm (kvm); +if (r) +break ; + +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); +/* FMT 4 SIE needs esca */ + r =sca_switch_to_extended (kvm);
Looking at this again: this function calls kvm_s390_vcpu_block_all() (which probably does not hurt), but then kvm_s390_vcpu_unblock_all()... don't we want to keep the block across pv_create_vm() as well?
Also, can you maybe skip calling this function if we use the esca already?
Quoted 21 lines
Quoted 12 lines
Quoted 12 lines
arch/s390/kvm/kvm-s390.c +12
-0+if (!r) + r =kvm_s390_pv_create_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_DESTROY : { +/* All VCPUs have to be destroyed before this call. */ +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); + r =kvm_s390_pv_destroy_vm (kvm); +if (!r)Quoted 8 lines
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2199
Quoted 5 lines
arch/s390/kvm/kvm-s390.c +5
-0+kvm_s390_pv_dealloc_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + }Would be helpful to have some code that shows when/how these are called
- do you have any plans to post something soon?
Quoted 2 lines
Qemu patches will be in internal review soonish and afterwards I'll post them upstream
Great, looking forward to this :)
Quoted 14 lines
Quoted 6 lines
(...)
Quoted 2 lines
(quoted diff) +0
-0@@ -2529,6 +2642,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)Quoted 7 lines
arch/s390/kvm/kvm-s390.c void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) · line 2646
Quoted 4 lines
arch/s390/kvm/kvm-s390.c +2
-0if (vcpu->kvm->arch.use_cmma)kvm_s390_vcpu_unsetup_cmma (vcpu); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_handle_cpu (vcpu))I was a bit confused by that function name... maybe
kvm_s390_pv_cpu_get_handle()?
Quoted 8 lines
Sure
Quoted 3 lines
Also, if this always returns 0 if the config option is off, you probably don't need to check for that option?
Hmm, if we decide to remove the config option altogether then it's not needed anyway and I think that's what Christian wants.
That would be fine with me as well (I have not yet thought about all implications there, though.)
Quoted 22 lines
Quoted 5 lines
Quoted 5 lines
arch/s390/kvm/kvm-s390.c +1
-0+kvm_s390_pv_destroy_cpu (vcpu);free_page ((unsigned long )(vcpu->arch.sie_block));Quoted 16 lines
arch/s390/kvm/kvm-s390.c void kvm_arch_destroy_vm(struct kvm *kvm) · line 2678
Quoted 11 lines
arch/s390/kvm/kvm-s390.c +4
-1kvm_vcpu_uninit (vcpu);@@ -2555,8 +2671,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm) {kvm_free_vcpus (kvm);sca_dispose (kvm); -debug_unregister (kvm->arch.dbf);kvm_s390_gisa_destroy (kvm); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_is_protected (kvm)) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm);It seems the pv vm can be either destroyed via the ioctl above or in the course of normal vm destruction. When is which way supposed to be used? Also, it seems
kvm_s390_pv_destroy_vm()can fail -- can that be a problem in this code path?
Quoted 4 lines
On a reboot we need to tear down the protected VM and boot from unprotected mode again. If the VM shuts down we go through this cleanup path. If it fails the kernel will loose the memory that was allocated to start the VM.
Shouldn't you at least log a moan in that case? Hopefully, this happens very rarely, but the dbf will be gone...
Quoted 42 lines
Quoted 33 lines
Quoted 7 lines
arch/s390/kvm/kvm-s390.c +2
-0+ } +debug_unregister (kvm->arch.dbf);free_page ((unsigned long )kvm->arch.sie_page2);if (!kvm_is_ucontrol (kvm))gmap_remove (kvm->arch.gmap);(...)
Quoted 23 lines
arch/s390/kvm/kvm-s390.h +15
-0@@ -196,6 +196,53 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)return kvm->arch.user_cpu_state_ctrl !=0 ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +/* implemented in pv.c */ +void kvm_s390_pv_unpin (struct kvm *kvm); +void kvm_s390_pv_dealloc_vm (struct kvm *kvm); +int kvm_s390_pv_alloc_vm (struct kvm *kvm); +int kvm_s390_pv_create_vm (struct kvm *kvm); +int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_destroy_vm (struct kvm *kvm); +int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_set_sec_parms (struct kvm *kvm,void *hdr,u64 length); +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak); +int kvm_s390_pv_verify (struct kvm *kvm); + +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm)Quoted 8 lines
arch/s390/kvm/kvm-s390.h static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm) · line 218
Quoted 5 lines
arch/s390/kvm/kvm-s390.h +5
-0+{ +return !!kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle (struct kvm *kvm)This function name is less confusing than the one below, but maybe also rename this to
kvm_s390_pv_get_handle()for consistency?
Quoted 1 line
kvm_s390_pv_kvm_handle?
kvm_s390_pv_kvm_get_handle() would mirror the cpu function :) </bikeshed>
Quoted 47 lines
Quoted 35 lines
Quoted 32 lines
arch/s390/kvm/kvm-s390.h +27
-0+{ +return kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) +{ +return vcpu->arch.pv.handle; +} +#else +static inline void kvm_s390_pv_unpin (struct kvm *kvm) {} +static inline void kvm_s390_pv_dealloc_vm (struct kvm *kvm) {} +static inline int kvm_s390_pv_alloc_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_destroy_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_set_sec_parms (struct kvm *kvm, +u64 origin,u64 length) {return 0 ; } +static inline int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr, +unsigned long size,unsigned long tweak) +{return 0 ; } +static inline int kvm_s390_pv_verify (struct kvm *kvm) {return 0 ; } +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +#endif +/* implemented in interrupt.c */ int kvm_s390_handle_wait (struct kvm_vcpu *vcpu);void kvm_s390_vcpu_wakeup (struct kvm_vcpu *vcpu);(...)
Quoted 11 lines
arch/s390/kvm/kvm-s390.h
Quoted 9 lines
arch/s390/kvm/kvm-s390.h +9
-0+int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) +{ +int rc; +struct uv_cb_csc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CPU , + .header.len =sizeof (uvcb), + }; + +/* EEXIST and ENOENT? */ ?
Quoted 2 lines
I was asking myself if EEXIST or ENOENT would be better error values than EINVAL.
EEXIST might be better, but I don't really like ENOENT.
Quoted 39 lines
Quoted 37 lines
Quoted 22 lines
arch/s390/kvm/kvm-s390.h +20
-0+if (kvm_s390_pv_handle_cpu (vcpu)) +return -EINVAL ; + + vcpu->arch.pv.stor_base =__get_free_pages (GFP_KERNEL , +get_order (uv_info.guest_cpu_stor_len)); +if (!vcpu->arch.pv.stor_base) +return -ENOMEM ; + +/* Input */ + uvcb.guest_handle =kvm_s390_pv_handle (vcpu->kvm); + uvcb.num = vcpu->arch.sie_block->icpua; + uvcb.state_origin = (u64 )vcpu->arch.sie_block; + uvcb.stor_origin = (u64 )vcpu->arch.pv.stor_base; + + rc =uv_call (0 , (u64)&uvcb); +VCPU_EVENT (vcpu,3 ,"PROTVIRT CREATE VCPU: cpu %d handle %llx rc %x rrc %x" , + vcpu->vcpu_id, uvcb.cpu_handle, uvcb.header.rc, + uvcb.header.rrc); + +/* Output */ arch/s390/kvm/kvm-s390.h
Quoted 10 lines
arch/s390/kvm/kvm-s390.h +10
-0+ vcpu->arch.pv.handle = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_cpu = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_config =kvm_s390_pv_handle (vcpu->kvm); + vcpu->arch.sie_block->sdf =2 ; +if (!rc) +return 0 ; + +kvm_s390_pv_destroy_cpu (vcpu); +return -EINVAL ; +}(...)
Only a quick readthrough, as this patch is longish.
Janosch Frank
maintainerRe: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
Quoted 23 lines · Cornelia Huck
Quoted 20 lines · On Fri, 8 Nov 2019 08:36:35 +0100 Janosch Frank <[email protected]> wrote:
Quoted 19 lines · Cornelia Huck
Quoted 16 lines · On Thu, 24 Oct 2019 07:40:26 -0400 Janosch Frank <[email protected]> wrote:
arch/s390/kvm/kvm-s390.c +12
-0@@ -2157,6 +2164,96 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,return r; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv (struct kvm *kvm,struct kvm_pv_cmd *cmd) +{ +int r =0 ; +void __user *argp = (void __user *)cmd->data; + +switch (cmd->cmd) { +case KVM_PV_VM_CREATE : { + r =kvm_s390_pv_alloc_vm (kvm); +if (r) +break ; +
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2182
Quoted 4 lines
arch/s390/kvm/kvm-s390.c +4
-0+mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); +/* FMT 4 SIE needs esca */ + r =sca_switch_to_extended (kvm);Looking at this again: this function calls
kvm_s390_vcpu_block_all()(which probably does not hurt), but thenkvm_s390_vcpu_unblock_all()... don't we want to keep the block acrosspv_create_vm()as well?
Yeah
Quoted 3 lines
Also, can you maybe skip calling this function if we use the esca already?
Did I forget to include that in the patchset?
I extended sca_switch_to_extended() to just return in that case.
Quoted 75 lines
Quoted 22 lines
Quoted 13 lines
Quoted 13 lines
arch/s390/kvm/kvm-s390.c +12
-0+if (!r) + r =kvm_s390_pv_create_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_DESTROY : { +/* All VCPUs have to be destroyed before this call. */ +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); + r =kvm_s390_pv_destroy_vm (kvm); +if (!r)Quoted 8 lines
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2199
Quoted 5 lines
arch/s390/kvm/kvm-s390.c +5
-0+kvm_s390_pv_dealloc_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + }Would be helpful to have some code that shows when/how these are called
- do you have any plans to post something soon?Quoted 2 lines
Qemu patches will be in internal review soonish and afterwards I'll post them upstream
Great, looking forward to this :)
Quoted 14 lines
Quoted 6 lines
(...)
Quoted 2 lines
(quoted diff) +0
-0@@ -2529,6 +2642,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)Quoted 7 lines
arch/s390/kvm/kvm-s390.c void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) · line 2646
Quoted 4 lines
arch/s390/kvm/kvm-s390.c +2
-0if (vcpu->kvm->arch.use_cmma)kvm_s390_vcpu_unsetup_cmma (vcpu); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_handle_cpu (vcpu))I was a bit confused by that function name... maybe
kvm_s390_pv_cpu_get_handle()?Quoted 8 lines
Sure
Quoted 3 lines
Also, if this always returns 0 if the config option is off, you probably don't need to check for that option?
Hmm, if we decide to remove the config option altogether then it's not needed anyway and I think that's what Christian wants.
That would be fine with me as well (I have not yet thought about all implications there, though.)
Quoted 22 lines
Quoted 21 lines
Quoted 7 lines
arch/s390/kvm/kvm-s390.c +1
-0+kvm_s390_pv_destroy_cpu (vcpu);free_page ((unsigned long )(vcpu->arch.sie_block));kvm_vcpu_uninit (vcpu);arch/s390/kvm/kvm-s390.c void kvm_arch_destroy_vm(struct kvm *kvm) · line 2678
Quoted 9 lines
arch/s390/kvm/kvm-s390.c +4
-1@@ -2555,8 +2671,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm) {kvm_free_vcpus (kvm);sca_dispose (kvm); -debug_unregister (kvm->arch.dbf);kvm_s390_gisa_destroy (kvm); +if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) && +kvm_s390_pv_is_protected (kvm)) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm);It seems the pv vm can be either destroyed via the ioctl above or in the course of normal vm destruction. When is which way supposed to be used? Also, it seems
kvm_s390_pv_destroy_vm()can fail -- can that be a problem in this code path?
Quoted 7 lines
Quoted 4 lines
On a reboot we need to tear down the protected VM and boot from unprotected mode again. If the VM shuts down we go through this cleanup path. If it fails the kernel will loose the memory that was allocated to start the VM.
Shouldn't you at least log a moan in that case? Hopefully, this happens very rarely, but the dbf will be gone...
That's why I created the uv dbf :-)
Well, it shouldn't happen at all so maybe a WARN will be a good option
Quoted 139 lines
Quoted 43 lines
Quoted 34 lines
Quoted 8 lines
arch/s390/kvm/kvm-s390.c +2
-0+ } +debug_unregister (kvm->arch.dbf);free_page ((unsigned long )kvm->arch.sie_page2);if (!kvm_is_ucontrol (kvm))gmap_remove (kvm->arch.gmap);(...)
Quoted 23 lines
arch/s390/kvm/kvm-s390.h +15
-0@@ -196,6 +196,53 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)return kvm->arch.user_cpu_state_ctrl !=0 ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +/* implemented in pv.c */ +void kvm_s390_pv_unpin (struct kvm *kvm); +void kvm_s390_pv_dealloc_vm (struct kvm *kvm); +int kvm_s390_pv_alloc_vm (struct kvm *kvm); +int kvm_s390_pv_create_vm (struct kvm *kvm); +int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_destroy_vm (struct kvm *kvm); +int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu); +int kvm_s390_pv_set_sec_parms (struct kvm *kvm,void *hdr,u64 length); +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak); +int kvm_s390_pv_verify (struct kvm *kvm); + +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm)Quoted 8 lines
arch/s390/kvm/kvm-s390.h static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm) · line 218
Quoted 5 lines
arch/s390/kvm/kvm-s390.h +5
-0+{ +return !!kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle (struct kvm *kvm)This function name is less confusing than the one below, but maybe also rename this to
kvm_s390_pv_get_handle()for consistency?Quoted 1 line
kvm_s390_pv_kvm_handle?
kvm_s390_pv_kvm_get_handle()would mirror the cpu function :) </bikeshed>Quoted 47 lines
Quoted 35 lines
Quoted 32 lines
arch/s390/kvm/kvm-s390.h +27
-0+{ +return kvm->arch.pv.handle; +} + +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) +{ +return vcpu->arch.pv.handle; +} +#else +static inline void kvm_s390_pv_unpin (struct kvm *kvm) {} +static inline void kvm_s390_pv_dealloc_vm (struct kvm *kvm) {} +static inline int kvm_s390_pv_alloc_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_destroy_vm (struct kvm *kvm) {return 0 ; } +static inline int kvm_s390_pv_destroy_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +static inline int kvm_s390_pv_set_sec_parms (struct kvm *kvm, +u64 origin,u64 length) {return 0 ; } +static inline int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr, +unsigned long size,unsigned long tweak) +{return 0 ; } +static inline int kvm_s390_pv_verify (struct kvm *kvm) {return 0 ; } +static inline bool kvm_s390_pv_is_protected (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle (struct kvm *kvm) {return 0 ; } +static inline u64 kvm_s390_pv_handle_cpu (struct kvm_vcpu *vcpu) {return 0 ; } +#endif +/* implemented in interrupt.c */ int kvm_s390_handle_wait (struct kvm_vcpu *vcpu);void kvm_s390_vcpu_wakeup (struct kvm_vcpu *vcpu);(...)
Quoted 11 lines
arch/s390/kvm/kvm-s390.h
Quoted 9 lines
arch/s390/kvm/kvm-s390.h +9
-0+int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) +{ +int rc; +struct uv_cb_csc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CPU , + .header.len =sizeof (uvcb), + }; + +/* EEXIST and ENOENT? */ ?
Quoted 2 lines
I was asking myself if EEXIST or ENOENT would be better error values than EINVAL.
EEXIST might be better, but I don't really like ENOENT.
Quoted 39 lines
Quoted 37 lines
Quoted 22 lines
arch/s390/kvm/kvm-s390.h +20
-0+if (kvm_s390_pv_handle_cpu (vcpu)) +return -EINVAL ; + + vcpu->arch.pv.stor_base =__get_free_pages (GFP_KERNEL , +get_order (uv_info.guest_cpu_stor_len)); +if (!vcpu->arch.pv.stor_base) +return -ENOMEM ; + +/* Input */ + uvcb.guest_handle =kvm_s390_pv_handle (vcpu->kvm); + uvcb.num = vcpu->arch.sie_block->icpua; + uvcb.state_origin = (u64 )vcpu->arch.sie_block; + uvcb.stor_origin = (u64 )vcpu->arch.pv.stor_base; + + rc =uv_call (0 , (u64)&uvcb); +VCPU_EVENT (vcpu,3 ,"PROTVIRT CREATE VCPU: cpu %d handle %llx rc %x rrc %x" , + vcpu->vcpu_id, uvcb.cpu_handle, uvcb.header.rc, + uvcb.header.rrc); + +/* Output */ arch/s390/kvm/kvm-s390.h
Quoted 10 lines
arch/s390/kvm/kvm-s390.h +10
-0+ vcpu->arch.pv.handle = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_cpu = uvcb.cpu_handle; + vcpu->arch.sie_block->pv_handle_config =kvm_s390_pv_handle (vcpu->kvm); + vcpu->arch.sie_block->sdf =2 ; +if (!rc) +return 0 ; + +kvm_s390_pv_destroy_cpu (vcpu); +return -EINVAL ; +}(...)
Only a quick readthrough, as this patch is longish.
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
Quoted 33 lines · On Mon, 11 Nov 2019 17:39:15 +0100 Janosch Frank <[email protected]> wrote:
Quoted 23 lines · Cornelia Huck
Quoted 20 lines · On Fri, 8 Nov 2019 08:36:35 +0100 Janosch Frank <[email protected]> wrote:
Quoted 19 lines · Cornelia Huck
Quoted 16 lines · On Thu, 24 Oct 2019 07:40:26 -0400 Janosch Frank <[email protected]> wrote:
arch/s390/kvm/kvm-s390.c +12
-0@@ -2157,6 +2164,96 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,return r; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv (struct kvm *kvm,struct kvm_pv_cmd *cmd) +{ +int r =0 ; +void __user *argp = (void __user *)cmd->data; + +switch (cmd->cmd) { +case KVM_PV_VM_CREATE : { + r =kvm_s390_pv_alloc_vm (kvm); +if (r) +break ; +Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
arch/s390/kvm/kvm-s390.c static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2182
Quoted 4 lines
arch/s390/kvm/kvm-s390.c +4
-0+mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); +/* FMT 4 SIE needs esca */ + r =sca_switch_to_extended (kvm);Looking at this again: this function calls
kvm_s390_vcpu_block_all()(which probably does not hurt), but thenkvm_s390_vcpu_unblock_all()... don't we want to keep the block acrosspv_create_vm()as well?
Quoted 8 lines
Yeah
Quoted 3 lines
Also, can you maybe skip calling this function if we use the esca already?
Did I forget to include that in the patchset?
I extendedsca_switch_to_extended()to just return in that case.
If you did, I likely missed it; way too much stuff to review :)
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
arch/s390/kvm/kvm-s390.c +6
-0+if (!r) + r =kvm_s390_pv_create_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + }
(...)
Quoted 21 lines
Quoted 21 lines
Quoted 20 lines
Quoted 7 lines
Quoted 7 lines
arch/s390/kvm/kvm-s390.c +1
-1@@ -2555,8 +2671,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm) {kvm_free_vcpus (kvm);sca_dispose (kvm); -debug_unregister (kvm->arch.dbf);kvm_s390_gisa_destroy (kvm); + if (IS_ENABLED(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST) &&Quoted 8 lines
arch/s390/kvm/kvm-s390.c void kvm_arch_destroy_vm(struct kvm *kvm) · line 2678
Quoted 3 lines
arch/s390/kvm/kvm-s390.c +3
-0+ kvm_s390_pv_is_protected(kvm)) { +kvm_s390_pv_destroy_vm (kvm); +kvm_s390_pv_dealloc_vm (kvm);It seems the pv vm can be either destroyed via the ioctl above or in the course of normal vm destruction. When is which way supposed to be used? Also, it seems
kvm_s390_pv_destroy_vm()can fail -- can that be a problem in this code path?On a reboot we need to tear down the protected VM and boot from unprotected mode again. If the VM shuts down we go through this cleanup path. If it fails the kernel will loose the memory that was allocated to start the VM.
Quoted 4 lines
Quoted 2 lines
Shouldn't you at least log a moan in that case? Hopefully, this happens very rarely, but the dbf will be gone...
That's why I created the uv dbf :-)
Again, way too easy to get lost in these changes :)
Quoted 1 line
Well, it shouldn't happen at all so maybe a WARN will be a good option
Yeah, if it this is one of these "should not happen" things, a WARN sounds good.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
arch/s390/kvm/kvm-s390.c +2
-0+ } +debug_unregister (kvm->arch.dbf);free_page ((unsigned long )kvm->arch.sie_page2);if (!kvm_is_ucontrol (kvm))gmap_remove (kvm->arch.gmap);
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
In reply to Cornelia HuckQuoted 4 lines · Cornelia Huck
Quoted 1 line · On Fri, 8 Nov 2019 08:36:35 +0100 Janosch Frank <[email protected]> wrote:
On 11/7/19 5:29 PM, Cornelia Huck wrote:
[...]
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
arch/s390/kvm/pv.c line 108
Quoted 10 lines
arch/s390/kvm/pv.c new file +9
-0+int kvm_s390_pv_create_cpu (struct kvm_vcpu *vcpu) +{ +int rc; +struct uv_cb_csc uvcb = { + .header.cmd =UVC_CMD_CREATE_SEC_CPU , + .header.len =sizeof (uvcb), + }; + +/* EEXIST and ENOENT? */ ?
Quoted 8 lines
Quoted 2 lines
I was asking myself if EEXIST or ENOENT would be better error values than EINVAL.
EEXIST might be better, but I don't really like ENOENT.
Quoted 3 lines
Quoted 3 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ if (kvm_s390_pv_handle_cpu(vcpu)) + return -EINVAL;
FWIW, I'd also vote for EEXIST here.
Thomas
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
In reply to Janosch FrankQuoted 1 line · Janosch Frank
Let's add a KVM interface to create and destroy protected VMs.
I agree with David, some more description here would be helpful.
Quoted 18 lines
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 24 +++- arch/s390/include/asm/uv.h | 110 ++++++++++++++ arch/s390/kvm/Makefile | 2 +- arch/s390/kvm/kvm-s390.c | 173 +++++++++++++++++++++- arch/s390/kvm/kvm-s390.h | 47 ++++++ arch/s390/kvm/pv.c | 237 +++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 33 +++++ 7 files changed, 622 insertions(+), 4 deletions(-)create mode 100644
arch/s390/kvm/pv.carch/s390/include/asm/kvm_host.h +0
-0@@ -155,7 +155,13 @@ struct kvm_s390_sie_block {__u8 reserved08[4 ];/* 0x0008 */
arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 164
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +7
-1#define PROG_IN_SIE (1<<0)__u32 prog0c;/* 0x000c */ -__u8 reserved10[16 ];/* 0x0010 */ +union { +__u8 reserved10[16 ];/* 0x0010 */ +struct { +__u64 pv_handle_cpu; +__u64 pv_handle_config; + }; + };
Why do you need to keep reserved10[] here? Simply replace it with the two new fields, and get rid of the union?
Quoted 4 lines
arch/s390/include/asm/kvm_host.h +4
-0+/* +* Generic cmd executor for calls that only transport the cpu or guest +* handle and the command. +*/
arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block {
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +10
-0+static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) +{ +int rc; +struct uv_cb_nodata uvcb = { + .header.cmd = cmd, + .header.len =sizeof (uvcb), + .handle = handle, + }; + +WARN (!handle,"No handle provided to Ultravisor call cmd %x\n" , cmd);
If this is not supposed to happen, I thing you should return here instead of doing the uv_call() below? Or maybe even turn this into a BUG() statement?
Quoted 5 lines
arch/s390/include/asm/kvm_host.h +5
-0+ rc =uv_call (0 , (u64)&uvcb); +if (ret) + *ret = *(u32 *)&uvcb.header.rc; +return rc ? -EINVAL :0 ; +}
[...]
arch/s390/include/asm/kvm_host.h static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2173
Quoted 11 lines
arch/s390/include/asm/kvm_host.h +7
-0@@ -2157,6 +2164,96 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,return r; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv (struct kvm *kvm,struct kvm_pv_cmd *cmd) +{ +int r =0 ; +void __user *argp = (void __user *)cmd->data; + +switch (cmd->cmd) {
Why are you using curly braces for the case statements below? They do not seem to be necessary in most cases?
Quoted 28 lines
arch/s390/include/asm/kvm_host.h +28
-0+case KVM_PV_VM_CREATE : { + r =kvm_s390_pv_alloc_vm (kvm); +if (r) +break ; + +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); +/* FMT 4 SIE needs esca */ + r =sca_switch_to_extended (kvm); +if (!r) + r =kvm_s390_pv_create_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_DESTROY : { +/* All VCPUs have to be destroyed before this call. */ +mutex_lock (&kvm->lock); +kvm_s390_vcpu_block_all (kvm); + r =kvm_s390_pv_destroy_vm (kvm); +if (!r) +kvm_s390_pv_dealloc_vm (kvm); +kvm_s390_vcpu_unblock_all (kvm); +mutex_unlock (&kvm->lock); +break ; + } +case KVM_PV_VM_SET_SEC_PARMS : { +struct kvm_s390_pv_sec_parm parms = {};
arch/s390/include/asm/kvm_host.h static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2211
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +10
-0+void *hdr; + + r = -EFAULT ; +if (copy_from_user (&parms, argp,sizeof (parms))) +break ; + +/* Currently restricted to 8KB */ + r = -EINVAL ; +if (parms.length >PAGE_SIZE *2 ) +break ;
I think you should also check fr parms.length == 0 ... otherwise you'll get an unfriendly complaint from vmalloc().
Quoted 29 lines
arch/s390/include/asm/kvm_host.h +29
-0+ r = -ENOMEM ; + hdr =vmalloc (parms.length); +if (!hdr) +break ; + + r = -EFAULT ; +if (!copy_from_user (hdr, (void __user *)parms.origin, + parms.length)) + r =kvm_s390_pv_set_sec_parms (kvm, hdr, parms.length); + +vfree (hdr); +break ; + } +case KVM_PV_VM_UNPACK : { +struct kvm_s390_pv_unp unp = {}; + + r = -EFAULT ; +if (copy_from_user (&unp, argp,sizeof (unp))) +break ; + + r =kvm_s390_pv_unpack (kvm, unp.addr, unp.size, unp.tweak); +break ; + } +case KVM_PV_VM_VERIFY : { +u32 ret; + + r = -EINVAL ; +if (!kvm_s390_pv_is_protected (kvm)) +break ;
arch/s390/include/asm/kvm_host.h static int kvm_s390_set_cmma_bits(struct kvm *kvm, · line 2250
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +10
-0+ + r =uv_cmd_nodata (kvm_s390_pv_handle (kvm), +UVC_CMD_VERIFY_IMG , + &ret); +VM_EVENT (kvm,3 ,"PROTVIRT VERIFY: rc %x rrc %x" , + ret >>16 , ret &0x0000ffff ); +break ; + } +default : +return -ENOTTY ;
Is ENOTTY the right thing to return for an invalid cmd here? It might get confused with the ioctl not being available at all? Maybe EINVAL would be better?
Quoted 5 lines
arch/s390/include/asm/kvm_host.h +5
-0+ } +return r; +} +#endif +
[...]
arch/s390/include/asm/kvm_host.h long kvm_arch_vcpu_async_ioctl(struct file *filp, · line 4480
Quoted 11 lines
arch/s390/include/asm/kvm_host.h +7
-0@@ -4338,6 +4471,28 @@ long kvm_arch_vcpu_async_ioctl(struct file *filp,return -ENOIOCTLCMD ; } +#ifdef CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST +static int kvm_s390_handle_pv_vcpu (struct kvm_vcpu *vcpu, +struct kvm_pv_cmd *cmd) +{ +int r =0 ; + +switch (cmd->cmd) {
Also no need for the curly braces of the case statements here?
arch/s390/include/asm/kvm_host.h long kvm_arch_vcpu_async_ioctl(struct file *filp, · line 4490
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +10
-0+case KVM_PV_VCPU_CREATE : { + r =kvm_s390_pv_create_cpu (vcpu); +break ; + } +case KVM_PV_VCPU_DESTROY : { + r =kvm_s390_pv_destroy_cpu (vcpu); +break ; + } +default : + r = -ENOTTY ;
Or EINVAL?
arch/s390/include/asm/kvm_host.h long kvm_arch_vcpu_async_ioctl(struct file *filp, · line 4494
Quoted 4 lines
arch/s390/include/asm/kvm_host.h +4
-0+ } +return r; +} +#endif
Thomas
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
In reply to Janosch FrankQuoted 4 lines · Janosch Frank
Let's add a KVM interface to create and destroy protected VMs.
Signed-off-by Janosch Frank <[email protected]>---
[...]
arch/s390/kvm/pv.c line 210
Quoted 13 lines
arch/s390/kvm/pv.c new file +13
-0+int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int i, rc =0 ; +struct uv_cb_unp uvcb = { + .header.cmd =UVC_CMD_UNPACK_IMG , + .header.len =sizeof (uvcb), + .guest_handle =kvm_s390_pv_handle (kvm), + .tweak[0 ] = tweak + }; + +if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) +return -EINVAL ;
Also check for size == 0 ?
Review
Quoted 2 lines
(quoted diff) +2
-0+ +
Remove one of the two empty lines, please.
Quoted 10 lines
arch/s390/kvm/pv.c new file +10
-0+VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , + addr, size); +for (i =0 ; i < size /PAGE_SIZE ; i++) { + uvcb.gaddr = addr + i *PAGE_SIZE ; + uvcb.tweak[1 ] = i *PAGE_SIZE ; +retry: + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +continue ; +/* If not yet mapped fault and retry */
arch/s390/kvm/pv.c line 232
Quoted 10 lines
arch/s390/kvm/pv.c new file +10
-0+if (uvcb.header.rc ==0x10a ) { + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (rc) +return rc; + goto retry; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +break ;
A break at the end of the for-loop ... that's really not what I'd expect.
Could you please invert the logic here, i.e.:
if (uvcb.header.rc != 0x10a) {
VM_EVENT(...)
break;
}
rc = gmap_fault(...)
...I think you might even get rid of that ugly "goto", too, that way?
arch/s390/kvm/pv.c line 237
Quoted 5 lines
arch/s390/kvm/pv.c new file +5
-0+ } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished with rc %x rrc %x" , + uvcb.header.rc, uvcb.header.rrc); +return rc; +}
Thomas
Janosch Frank
maintainerRe: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
Quoted 6 lines · Thomas Huth
Quoted 4 lines · Janosch Frank
Let's add a KVM interface to create and destroy protected VMs.
Signed-off-by Janosch Frank <[email protected]>---
[...]
Quoted 15 lines
arch/s390/kvm/pv.c line 210
Quoted 13 lines
arch/s390/kvm/pv.c new file +13
-0+int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int i, rc =0 ; +struct uv_cb_unp uvcb = { + .header.cmd =UVC_CMD_UNPACK_IMG , + .header.len =sizeof (uvcb), + .guest_handle =kvm_s390_pv_handle (kvm), + .tweak[0 ] = tweak + }; + +if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) +return -EINVAL ;Also check for size == 0 ?
Yep
Quoted 5 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ +Remove one of the two empty lines, please.
Yep
Quoted 26 lines
Quoted 11 lines
arch/s390/kvm/pv.c new file +10
-0+VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , + addr, size); +for (i =0 ; i < size /PAGE_SIZE ; i++) { + uvcb.gaddr = addr + i *PAGE_SIZE ; + uvcb.tweak[1 ] = i *PAGE_SIZE ; +retry: + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +continue ; +/* If not yet mapped fault and retry */ arch/s390/kvm/pv.c line 232
Quoted 10 lines
arch/s390/kvm/pv.c new file +10
-0+if (uvcb.header.rc ==0x10a ) { + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (rc) +return rc; + goto retry; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +break ;A break at the end of the for-loop ... that's really not what I'd expect.
Could you please invert the logic here, i.e.:
Quoted 8 lines
if (uvcb.header.rc != 0x10a) { VM_EVENT(...) break; } rc = gmap_fault(...) ...I think you might even get rid of that ugly "goto", too, that way?
But without the goto we would increment i, no?
I'll try to find a solution, maybe using while, but then we need to manage i incrementation.
Quoted 9 lines
arch/s390/kvm/pv.c line 237
Quoted 6 lines
arch/s390/kvm/pv.c new file +5
-0+ } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished with rc %x rrc %x" , + uvcb.header.rc, uvcb.header.rrc); +return rc; +}Thomas
Janosch Frank
maintainerPATCH 1/1 Fix unpack
In reply to Thomas HuthThat should be easier to read :)
--- arch/s390/kvm/pv.c | 60 +++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 25 deletions(-)
arch/s390/kvm/pv.c +35 -25
@@ -195,43 +195,53 @@ int kvm_s390_pv_set_sec_parms(struct kvm *kvm,return 0 ; } -int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, -unsigned long tweak) +static int unpack_one (struct kvm *kvm,unsigned long addr,u64 tweak[2 ]) { -int i, rc =0 ; +int rc;struct uv_cb_unp uvcb = { .header.cmd =UVC_CMD_UNPACK_IMG , .header.len =sizeof (uvcb), .guest_handle =kvm_s390_pv_handle (kvm), - .tweak[0 ] = tweak + .gaddr = addr, + .tweak[0 ] = tweak[0 ], + .tweak[1 ] = tweak[1 ], }; -if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) -return -EINVAL ; + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +return rc; +if (uvcb.header.rc ==0x10a ) { +/* If not yet mapped fault and retry */ + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (!rc) +return -EAGAIN ; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +return rc; +} +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int rc =0 ; +u64 tw[2 ] = {tweak,0 }; + +if (addr & ~PAGE_MASK || !size || size & ~PAGE_MASK ) +return -EINVAL ;VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , addr, size); -for (i =0 ; i < size /PAGE_SIZE ; i++) { - uvcb.gaddr = addr + i *PAGE_SIZE ; - uvcb.tweak[1 ] = i *PAGE_SIZE ; -retry: - rc =uv_call (0 , (u64)&uvcb); -if (!rc) +while (tw[1 ] < size) { + rc =unpack_one (kvm, addr, tw); +if (rc == -EAGAIN )continue ; -/* If not yet mapped fault and retry */ -if (uvcb.header.rc ==0x10a ) { - rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, -FAULT_FLAG_WRITE ); -if (rc) -return rc; - goto retry; - } -VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , - uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); -break ; +if (rc) +break ; + addr +=PAGE_SIZE ; + tw[1 ] +=PAGE_SIZE ; } -VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished with rc %x rrc %x" , - uvcb.header.rc, uvcb.header.rrc); +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished rc %x" , rc);return rc; }
Signature · 1 line
2.20.1
Re: [PATCH] Fix unpack
Quoted 81 lines · Janosch Frank
That should be easier to read :)
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/kvm/pv.c | 60 +++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 25 deletions(-)arch/s390/kvm/pv.c +30
-23@@ -195,43 +195,53 @@ int kvm_s390_pv_set_sec_parms(struct kvm *kvm,return 0 ; } -int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, -unsigned long tweak) +static int unpack_one (struct kvm *kvm,unsigned long addr,u64 tweak[2 ]) { -int i, rc =0 ; +int rc;struct uv_cb_unp uvcb = { .header.cmd =UVC_CMD_UNPACK_IMG , .header.len =sizeof (uvcb), .guest_handle =kvm_s390_pv_handle (kvm), - .tweak[0 ] = tweak + .gaddr = addr, + .tweak[0 ] = tweak[0 ], + .tweak[1 ] = tweak[1 ], }; -if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) -return -EINVAL ; + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +return rc; +if (uvcb.header.rc ==0x10a ) { +/* If not yet mapped fault and retry */ + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (!rc) +return -EAGAIN ; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +return rc; +} +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int rc =0 ; +u64 tw[2 ] = {tweak,0 }; + +if (addr & ~PAGE_MASK || !size || size & ~PAGE_MASK ) +return -EINVAL ;VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , addr, size); -for (i =0 ; i < size /PAGE_SIZE ; i++) { - uvcb.gaddr = addr + i *PAGE_SIZE ; - uvcb.tweak[1 ] = i *PAGE_SIZE ; -retry: - rc =uv_call (0 , (u64)&uvcb); -if (!rc) +while (tw[1 ] < size) { + rc =unpack_one (kvm, addr, tw); +if (rc == -EAGAIN )continue ; -/* If not yet mapped fault and retry */ -if (uvcb.header.rc ==0x10a ) { - rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, -FAULT_FLAG_WRITE ); -if (rc) -return rc; - goto retry; - } -VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , - uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); -break ;
arch/s390/kvm/pv.c int kvm_s390_pv_set_sec_parms(struct kvm *kvm, · line 247
Quoted 10 lines
arch/s390/kvm/pv.c +5
-2+if (rc) +break ; + addr +=PAGE_SIZE ; + tw[1 ] +=PAGE_SIZE ; } -VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished with rc %x rrc %x" , - uvcb.header.rc, uvcb.header.rrc); +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished rc %x" , rc);return rc; }
Yes, I think that will be better, thanks!
Thomas
Re: [PATCH] Fix unpack
In reply to Janosch FrankOn Wed, 13 Nov 2019 09:03:06 -0500
Janosch Frank <[email protected]> wrote:
You seem to have dropped some cc:s :(
Quoted 80 lines
That should be easier to read :)
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/kvm/pv.c | 60 +++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 25 deletions(-)arch/s390/kvm/pv.c +30
-23@@ -195,43 +195,53 @@ int kvm_s390_pv_set_sec_parms(struct kvm *kvm,return 0 ; } -int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, -unsigned long tweak) +static int unpack_one (struct kvm *kvm,unsigned long addr,u64 tweak[2 ]) { -int i, rc =0 ; +int rc;struct uv_cb_unp uvcb = { .header.cmd =UVC_CMD_UNPACK_IMG , .header.len =sizeof (uvcb), .guest_handle =kvm_s390_pv_handle (kvm), - .tweak[0 ] = tweak + .gaddr = addr, + .tweak[0 ] = tweak[0 ], + .tweak[1 ] = tweak[1 ], }; -if (addr & ~PAGE_MASK || size & ~PAGE_MASK ) -return -EINVAL ; + rc =uv_call (0 , (u64)&uvcb); +if (!rc) +return rc; +if (uvcb.header.rc ==0x10a ) { +/* If not yet mapped fault and retry */ + rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, +FAULT_FLAG_WRITE ); +if (!rc) +return -EAGAIN ; + } +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , + uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); +return rc; +} +int kvm_s390_pv_unpack (struct kvm *kvm,unsigned long addr,unsigned long size, +unsigned long tweak) +{ +int rc =0 ; +u64 tw[2 ] = {tweak,0 }; + +if (addr & ~PAGE_MASK || !size || size & ~PAGE_MASK ) +return -EINVAL ;VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: start addr %lx size %lx" , addr, size); -for (i =0 ; i < size /PAGE_SIZE ; i++) { - uvcb.gaddr = addr + i *PAGE_SIZE ; - uvcb.tweak[1 ] = i *PAGE_SIZE ; -retry: - rc =uv_call (0 , (u64)&uvcb); -if (!rc) +while (tw[1 ] < size) { + rc =unpack_one (kvm, addr, tw); +if (rc == -EAGAIN )continue ; -/* If not yet mapped fault and retry */ -if (uvcb.header.rc ==0x10a ) { - rc =gmap_fault (kvm->arch.gmap, uvcb.gaddr, -FAULT_FLAG_WRITE ); -if (rc) -return rc; - goto retry; - } -VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: failed addr %llx rc %x rrc %x" , - uvcb.gaddr, uvcb.header.rc, uvcb.header.rrc); -break ;
arch/s390/kvm/pv.c int kvm_s390_pv_set_sec_parms(struct kvm *kvm, · line 247
Quoted 10 lines
arch/s390/kvm/pv.c +5
-2+if (rc) +break ; + addr +=PAGE_SIZE ; + tw[1 ] +=PAGE_SIZE ; } -VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished with rc %x rrc %x" , - uvcb.header.rc, uvcb.header.rrc); +VM_EVENT (kvm,3 ,"PROTVIRT VM UNPACK: finished rc %x" , rc);return rc; }
Yes, this looks more readable.
Re: [RFC 04/37] KVM: s390: protvirt: Add initial lifecycle handling
In reply to Janosch FrankQuoted 8 lines · On Thu, 24 Oct 2019 07:40:26 -0400 Janosch Frank <[email protected]> wrote:
arch/s390/include/asm/uv.h +8
-0+/* +* Generic cmd executor for calls that only transport the cpu or guest +* handle and the command. +*/ +static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) +{ +int rc; +struct uv_cb_nodata uvcb = {
arch/s390/include/asm/uv.h static inline int is_prot_virt_host(void) · line 279
Quoted 10 lines
arch/s390/include/asm/uv.h +10
-0+ .header.cmd = cmd, + .header.len = sizeof(uvcb), + .handle = handle, + }; + +WARN (!handle,"No handle provided to Ultravisor call cmd %x\n" , cmd); + rc =uv_call (0 , (u64)&uvcb); +if (ret) + *ret = *(u32 *)&uvcb.header.rc; +return rc ? -EINVAL :0 ;
Why go ahead with doing the uv call if it doesn't have a handle anyway? Or why warn, if you already know it is going to fail? I assume this can only happen if you have a logic error in the kvm code?
Quoted 1 line
+}
Janosch Frank
maintainerRFC 5/37 s390: KVM: Export PV handle to gmap
In reply to Janosch FrankWe need it in the next patch, when doing memory management for the guest in the kernel's fault handler, where otherwise we wouldn't have access to the handle.
--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/pv.c | 1 + 2 files changed, 2 insertions(+)
arch/s390/include/asm/gmap.h +1 -0
@@ -61,6 +61,7 @@ struct gmap {spinlock_t shadow_lock;struct gmap *parent;unsigned long orig_asce; +unsigned long se_handle;int edat_level;bool removed;bool initialized;
arch/s390/kvm/pv.c +1 -0
@@ -169,6 +169,7 @@ int kvm_s390_pv_create_vm(struct kvm *kvm)kvm_s390_pv_dealloc_vm (kvm);return -EINVAL ; } + kvm->arch.gmap->se_handle = uvcb.guest_handle;return rc; }
Signature · 1 line
2.20.1
Re: [RFC 05/37] s390: KVM: Export PV handle to gmap
Quoted 28 lines · Janosch Frank
We need it in the next patch, when doing memory management for the guest in the kernel's fault handler, where otherwise we wouldn't have access to the handle.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/pv.c | 1 + 2 files changed, 2 insertions(+)arch/s390/include/asm/gmap.h +1
-0@@ -61,6 +61,7 @@ struct gmap {spinlock_t shadow_lock;struct gmap *parent;unsigned long orig_asce; +unsigned long se_handle;int edat_level;bool removed;bool initialized;arch/s390/kvm/pv.c +0
-0
arch/s390/kvm/pv.c int kvm_s390_pv_create_vm(struct kvm *kvm) · line 175
Quoted 7 lines
arch/s390/kvm/pv.c +1
-0@@ -169,6 +169,7 @@ int kvm_s390_pv_create_vm(struct kvm *kvm)kvm_s390_pv_dealloc_vm (kvm);return -EINVAL ; } + kvm->arch.gmap->se_handle = uvcb.guest_handle;return rc; }
I'd suggest squashing that into the patch that needs it.
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRFC 6/37 s390: UV: Add import and export to UV library
In reply to Janosch FrankThe convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.
All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
arch/s390/include/asm/uv.h +51 -0
@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002
@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) return rc ? -EINVAL : 0; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported +*/ +static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb), + .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ; +return -EINVAL ; +} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr + }; + + cc =uv_call (0 , (u64)&uvcb); + +if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ; +return -EINVAL ; +} +void setup_uv (void );void adjust_to_uv_max (unsigned long *vmax);#else
@@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);static inline void setup_uv (void ) {}static inline void adjust_to_uv_max (unsigned long *vmax) {}static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) {return 0 ; } +static inline int uv_convert_from_secure (unsigned long paddr) {return 0 ; } +static inline int uv_convert_to_secure (unsigned long handle,unsigned long gaddr) {return 0 ; }#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
Signature · 1 line
2.20.1
Re: [RFC 06/37] s390: UV: Add import and export to UV library
Quoted 5 lines · Janosch Frank
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
How does paging play along with pinning the pages (from uv_convert_to_secure() -> kvm_s390_pv_pin_page()) in a follow up patch? Can you paint me the bigger picture?
Just so I understand:
When a page is "secure", it is actually unencrypted but only the guest can access it. If the host accesses it, there is an exception.
When a page is "not secure", it is encrypted but only the host can read it. If the guest accesses it, there is an exception.
Based on these exceptions, you are able to request to convert back and forth.
Quoted 90 lines
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)arch/s390/include/asm/uv.h +51
-0@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) return rc ? -EINVAL : 0; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported +*/ +static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb), + .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ; +return -EINVAL ; +} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr + }; + + cc =uv_call (0 , (u64)&uvcb); + +if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ; +return -EINVAL ; +} +void setup_uv (void );void adjust_to_uv_max (unsigned long *vmax);#else @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);static inline void setup_uv (void ) {}static inline void adjust_to_uv_max (unsigned long *vmax) {}static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) {return 0 ; } +static inline int uv_convert_from_secure (unsigned long paddr) {return 0 ; } +static inline int uv_convert_to_secure (unsigned long handle,unsigned long gaddr) {return 0 ; }#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRe: [RFC 06/37] s390: UV: Add import and export to UV library
Quoted 10 lines · David Hildenbrand
Quoted 5 lines · Janosch Frank
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
How does paging play along with pinning the pages (from
uv_convert_to_secure()->kvm_s390_pv_pin_page()) in a follow up patch? Can you paint me the bigger picture?
That's a stale comment I should have removed before sending... The current patches do not support paging.
Quoted 11 lines
Just so I understand:
When a page is "secure", it is actually unencrypted but only the guest can access it. If the host accesses it, there is an exception.
When a page is "not secure", it is encrypted but only the host can read it. If the guest accesses it, there is an exception.
Based on these exceptions, you are able to request to convert back and forth.
Yes
Shared pages are the exception, because they are accessible to both parties.
Quoted 94 lines
Quoted 92 lines
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)arch/s390/include/asm/uv.h +51
-0@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) return rc ? -EINVAL : 0; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported +*/ +static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb), + .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ; +return -EINVAL ; +} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr + }; + + cc =uv_call (0 , (u64)&uvcb); + +if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ; +return -EINVAL ; +} +void setup_uv (void );void adjust_to_uv_max (unsigned long *vmax);#else @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);static inline void setup_uv (void ) {}static inline void adjust_to_uv_max (unsigned long *vmax) {}static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) {return 0 ; } +static inline int uv_convert_from_secure (unsigned long paddr) {return 0 ; } +static inline int uv_convert_to_secure (unsigned long handle,unsigned long gaddr) {return 0 ; }#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
Re: [RFC 06/37] s390: UV: Add import and export to UV library
Quoted 8 lines · Janosch Frank
Quoted 7 lines · David Hildenbrand
Quoted 5 lines · Janosch Frank
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
Quoted 6 lines
Quoted 3 lines
How does paging play along with pinning the pages (from
uv_convert_to_secure()->kvm_s390_pv_pin_page()) in a follow up patch? Can you paint me the bigger picture?That's a stale comment I should have removed before sending... The current patches do not support paging.
Note that once you pin you really have to disable the balloon in the QEMU (inhibit it).
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRe: [RFC 06/37] s390: UV: Add import and export to UV library
Quoted 13 lines · David Hildenbrand
Quoted 12 lines · Janosch Frank
Quoted 10 lines · David Hildenbrand
Quoted 5 lines · Janosch Frank
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
How does paging play along with pinning the pages (from
uv_convert_to_secure()->kvm_s390_pv_pin_page()) in a follow up patch? Can you paint me the bigger picture?
Quoted 6 lines
Quoted 2 lines
That's a stale comment I should have removed before sending... The current patches do not support paging.
Note that once you pin you really have to disable the balloon in the QEMU (inhibit it).
Yes, and you need the iommu for virtio.
We didn't yet fully discuss how to handle that.
Re: [RFC 06/37] s390: UV: Add import and export to UV library
In reply to Janosch FrankQuoted 39 lines · Janosch Frank
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)arch/s390/include/asm/uv.h +6
-0@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)return rc ? -EINVAL :0 ; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported
arch/s390/include/asm/uv.h static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) · line 297
Quoted 10 lines
arch/s390/include/asm/uv.h +10
-0+*/ +static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb), + .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ;
As discussed on the KVM forum. We should also check for uvcb.header.rc != UVC_RC_EXECUTED
I know, we cant really do much if this fails, but we certainly want to know.
Quoted 20 lines
arch/s390/include/asm/uv.h +20
-0+return -EINVAL ; +} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr
arch/s390/include/asm/uv.h static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) · line 327
Quoted 10 lines
arch/s390/include/asm/uv.h +10
-0+ }; + + cc =uv_call (0 , (u64)&uvcb); + +if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ;
again, we should probably check for rc != UVC_RC_EXECUTED to detect any other problem.
Quoted 16 lines
arch/s390/include/asm/uv.h +5
-0+ return -EINVAL; +} +void setup_uv (void );void adjust_to_uv_max (unsigned long *vmax);#else @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);static inline void setup_uv (void ) {}static inline void adjust_to_uv_max (unsigned long *vmax) {}static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) {return 0 ; } +static inline int uv_convert_from_secure (unsigned long paddr) {return 0 ; } +static inline int uv_convert_to_secure (unsigned long handle,unsigned long gaddr) {return 0 ; }#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
Janosch Frank
maintainerRe: [RFC 06/37] s390: UV: Add import and export to UV library
Quoted 86 lines · Christian Borntraeger
Quoted 39 lines · Janosch Frank
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)arch/s390/include/asm/uv.h +6
-0@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)return rc ? -EINVAL :0 ; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported arch/s390/include/asm/uv.h static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) · line 297
Quoted 10 lines
arch/s390/include/asm/uv.h +10
-0+*/ +static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb), + .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ;As discussed on the KVM forum. We should also check for uvcb.header.rc !=
UVC_RC_EXECUTED
I know, we cant really do much if this fails, but we certainly want to know.Quoted 24 lines
arch/s390/include/asm/uv.h +24
-0+return -EINVAL ; +} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr + }; + + cc =uv_call (0 , (u64)&uvcb); +
Quoted 8 lines
arch/s390/include/asm/uv.h static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) · line 327
Quoted 6 lines
arch/s390/include/asm/uv.h +6
-0+if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ;again, we should probably check for rc !=
UVC_RC_EXECUTEDto detect any other problem.
That's handled by the CC and the return below. CC == 1 means error
cc == 0 is success, that's why we return erly on cc == 0
Quoted 17 lines
Quoted 17 lines
arch/s390/include/asm/uv.h +5
-0+ return -EINVAL; +} +void setup_uv (void );void adjust_to_uv_max (unsigned long *vmax);#else @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);static inline void setup_uv (void ) {}static inline void adjust_to_uv_max (unsigned long *vmax) {}static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) {return 0 ; } +static inline int uv_convert_from_secure (unsigned long paddr) {return 0 ; } +static inline int uv_convert_to_secure (unsigned long handle,unsigned long gaddr) {return 0 ; }#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
Re: [RFC 06/37] s390: UV: Add import and export to UV library
Quoted 96 lines · Janosch Frank
Quoted 86 lines · Christian Borntraeger
Quoted 39 lines · Janosch Frank
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)arch/s390/include/asm/uv.h +6
-0@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)return rc ? -EINVAL :0 ; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported arch/s390/include/asm/uv.h static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) · line 297
Quoted 10 lines
arch/s390/include/asm/uv.h +10
-0+*/ +static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb), + .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ;As discussed on the KVM forum. We should also check for uvcb.header.rc !=
UVC_RC_EXECUTED
I know, we cant really do much if this fails, but we certainly want to know.Quoted 24 lines
arch/s390/include/asm/uv.h +24
-0+return -EINVAL ; +} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr + }; + + cc =uv_call (0 , (u64)&uvcb); +Quoted 8 lines
arch/s390/include/asm/uv.h static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) · line 327
Quoted 6 lines
arch/s390/include/asm/uv.h +6
-0+if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ;again, we should probably check for rc !=
UVC_RC_EXECUTEDto detect any other problem.
Quoted 3 lines
That's handled by the CC and the return below. CC == 1 means error
cc == 0 is success, that's why we return erly on cc == 0
Right, uv_call return depends on CC. Nevermind.
Re: [RFC 06/37] s390: UV: Add import and export to UV library
In reply to Janosch FrankQuoted 6 lines · Janosch Frank
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
Quoted 8 lines
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
Signed-off-by Janosch Frank <[email protected]>
After re-reading.
Quoted 81 lines
--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)arch/s390/include/asm/uv.h +51
-0@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) return rc ? -EINVAL : 0; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported +*/ +static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb), + .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ; +return -EINVAL ; +} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr + }; + + cc =uv_call (0 , (u64)&uvcb); + +if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ; +return -EINVAL ; +} +void setup_uv (void );void adjust_to_uv_max (unsigned long *vmax);#else @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);static inline void setup_uv (void ) {}static inline void adjust_to_uv_max (unsigned long *vmax) {}static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) {return 0 ; } +static inline int uv_convert_from_secure (unsigned long paddr) {return 0 ; } +static inline int uv_convert_to_secure (unsigned long handle,unsigned long gaddr) {return 0 ; }#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
Re: [RFC 06/37] s390: UV: Add import and export to UV library
In reply to Janosch FrankQuoted 40 lines · On Thu, 24 Oct 2019 07:40:28 -0400 Janosch Frank <[email protected]> wrote:
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)arch/s390/include/asm/uv.h +7
-0@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)return rc ? -EINVAL :0 ; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported +*/
arch/s390/include/asm/uv.h static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) · line 298
Quoted 10 lines
arch/s390/include/asm/uv.h +10
-0+static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb), + .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ; +return -EINVAL ;
No possibility for other return codes here (e.g. -EFAULT)? (Asking because you look at a rc in the control block in the reverse function.)
Quoted 44 lines
arch/s390/include/asm/uv.h +34
-0+} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr + }; + + cc =uv_call (0 , (u64)&uvcb); + +if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ; +return -EINVAL ; +} +void setup_uv (void );void adjust_to_uv_max (unsigned long *vmax);#else @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);static inline void setup_uv (void ) {}static inline void adjust_to_uv_max (unsigned long *vmax) {}static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) {return 0 ; } +static inline int uv_convert_from_secure (unsigned long paddr) {return 0 ; } +static inline int uv_convert_to_secure (unsigned long handle,unsigned long gaddr) {return 0 ; }#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
Janosch Frank
maintainerRe: [RFC 06/37] s390: UV: Add import and export to UV library
Quoted 48 lines · Cornelia Huck
Quoted 45 lines · On Thu, 24 Oct 2019 07:40:28 -0400 Janosch Frank <[email protected]> wrote:
The convert to/from secure (or also "import/export") ultravisor calls are need for page management, i.e. paging, of secure execution VM.
Export encrypts a secure guest's page and makes it accessible to the guest for paging.
Import makes a page accessible to a secure guest.
On the first import of that page, the page will be cleared by the Ultravisor before it is given to the guest.All following imports will decrypt a exported page and verify integrity before giving the page to the guest.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/uv.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)arch/s390/include/asm/uv.h +12
-0@@ -15,6 +15,7 @@#include <linux/errno.h> #include <linux/bug.h> #include <asm/page.h> +#include <asm/gmap.h> #define UVC_RC_EXECUTED 0x0001#define UVC_RC_INV_CMD 0x0002@@ -279,6 +280,54 @@ static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret)return rc ? -EINVAL :0 ; } +/* +* Requests the Ultravisor to encrypt a guest page and make it +* accessible to the host for paging (export). +* +* @paddr: Absolute host address of page to be exported +*/ +static inline int uv_convert_from_secure (unsigned long paddr) +{ +struct uv_cb_cfs uvcb = { + .header.cmd =UVC_CMD_CONV_FROM_SEC_STOR , + .header.len =sizeof (uvcb),
Quoted 8 lines
arch/s390/include/asm/uv.h static inline int uv_cmd_nodata(u64 handle, u16 cmd, u32 *ret) · line 298
Quoted 5 lines
arch/s390/include/asm/uv.h +5
-0+ .paddr = paddr + }; +if (!uv_call (0 , (u64)&uvcb)) +return 0 ; +return -EINVAL ;No possibility for other return codes here (e.g.
-EFAULT)? (Asking because you look at a rc in the control block in the reverse function.)
Notice the "paddr" variable?
We work on physical memory for this UV call, all error codes that are defined are either input errors (not possible via the exception handlers), a KVM management error or an attack on the VM.
Quoted 46 lines
Quoted 45 lines
arch/s390/include/asm/uv.h +34
-0+} + +/* +* Requests the Ultravisor to make a page accessible to a guest +* (import). If it's brought in the first time, it will be cleared. If +* it has been exported before, it will be decrypted and integrity +* checked. +* +* @handle: Ultravisor guest handle +* @gaddr: Guest 2 absolute address to be imported +*/ +static inline int uv_convert_to_secure (struct gmap *gmap,unsigned long gaddr) +{ +int cc; +struct uv_cb_cts uvcb = { + .header.cmd =UVC_CMD_CONV_TO_SEC_STOR , + .header.len =sizeof (uvcb), + .guest_handle = gmap->se_handle, + .gaddr = gaddr + }; + + cc =uv_call (0 , (u64)&uvcb); + +if (!cc) +return 0 ; +if (uvcb.header.rc ==0x104 ) +return -EEXIST ; +if (uvcb.header.rc ==0x10a ) +return -EFAULT ; +return -EINVAL ; +} +void setup_uv (void );void adjust_to_uv_max (unsigned long *vmax);#else @@ -286,6 +335,8 @@ void adjust_to_uv_max(unsigned long *vmax);static inline void setup_uv (void ) {}static inline void adjust_to_uv_max (unsigned long *vmax) {}static inline int uv_cmd_nodata (u64 handle,u16 cmd,u32 *ret) {return 0 ; } +static inline int uv_convert_from_secure (unsigned long paddr) {return 0 ; } +static inline int uv_convert_to_secure (unsigned long handle,unsigned long gaddr) {return 0 ; }#endif #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || \
Janosch Frank
maintainerRFC 7/37 KVM: s390: protvirt: Secure memory is not mergeable
In reply to Janosch FrankKSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-)
arch/s390/include/asm/gmap.h +1 -0
@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,void gmap_sync_dirty_log_pmd (struct gmap *gmap,unsigned long dirty_bitmap[4 ],unsigned long gaddr,unsigned long vmaddr); +int gmap_mark_unmergeable (void );#endif /* _ASM_S390_GMAP_H */
arch/s390/kvm/kvm-s390.c +6 -0
@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */
arch/s390/mm/gmap.c +18 -10
@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie); +int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) { + mm->context.uses_skeys =0 ; +return -ENOMEM ; + } + } + mm->def_flags &= ~VM_MERGEABLE ; +return 0 ; +} +EXPORT_SYMBOL_GPL (gmap_mark_unmergeable); +/* * Enable storage key handling from now on and initialize the storage * keys with the default key.
@@ -2593,7 +2610,6 @@ static const struct mm_walk_ops enable_skey_walk_ops = {int s390_enable_skey (void ) {struct mm_struct *mm = current->mm; -struct vm_area_struct *vma;int rc =0 ;down_write (&mm->mmap_sem);
@@ -2601,15 +2617,7 @@ int s390_enable_skey(void) goto out_up; mm->context.uses_skeys =1 ; -for (vma = mm->mmap; vma; vma = vma->vm_next) { -if (ksm_madvise (vma, vma->vm_start, vma->vm_end, -MADV_UNMERGEABLE , &vma->vm_flags)) { - mm->context.uses_skeys =0 ; - rc = -ENOMEM ; - goto out_up; - } - } - mm->def_flags &= ~VM_MERGEABLE ; +gmap_mark_unmergeable ();walk_page_range (mm,0 ,TASK_SIZE , &enable_skey_walk_ops,NULL );
Signature · 1 line
2.20.1
Re: [RFC 07/37] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 48 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,void gmap_sync_dirty_log_pmd (struct gmap *gmap,unsigned long dirty_bitmap[4 ],unsigned long gaddr,unsigned long vmaddr); +int gmap_mark_unmergeable (void );#endif /* _ASM_S390_GMAP_H */ arch/s390/kvm/kvm-s390.c +6
-0@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */ arch/s390/mm/gmap.c +0
-0@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie);
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2559
Quoted 10 lines
arch/s390/mm/gmap.c +9
-0+int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) { + mm->context.uses_skeys =0 ;
That skey setting does not make too much sense when coming via kvm_s390_handle_pv(). handle that in the caller?
Quoted 37 lines
arch/s390/mm/gmap.c +9
-10+return -ENOMEM ; + } + } + mm->def_flags &= ~VM_MERGEABLE ; +return 0 ; +} +EXPORT_SYMBOL_GPL (gmap_mark_unmergeable); +/* * Enable storage key handling from now on and initialize the storage * keys with the default key. @@ -2593,7 +2610,6 @@ static const struct mm_walk_ops enable_skey_walk_ops = {int s390_enable_skey (void ) {struct mm_struct *mm = current->mm; -struct vm_area_struct *vma;int rc =0 ;down_write (&mm->mmap_sem);@@ -2601,15 +2617,7 @@ int s390_enable_skey(void) goto out_up; mm->context.uses_skeys =1 ; -for (vma = mm->mmap; vma; vma = vma->vm_next) { -if (ksm_madvise (vma, vma->vm_start, vma->vm_end, -MADV_UNMERGEABLE , &vma->vm_flags)) { - mm->context.uses_skeys =0 ; - rc = -ENOMEM ; - goto out_up; - } - } - mm->def_flags &= ~VM_MERGEABLE ; +gmap_mark_unmergeable ();walk_page_range (mm,0 ,TASK_SIZE , &enable_skey_walk_ops,NULL );
Signature · 3 lines
Thanks, David / dhildenb
Claudio Imbrenda
maintainerRe: [RFC 07/37] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 50 lines · On Thu, 24 Oct 2019 18:07:14 +0200 David Hildenbrand <[email protected]> wrote:
Quoted 49 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-)(quoted diff) +0
-0
b/arch/s390/include/asm/gmap.hindex6efc0b501227..eab6a2ec3599100644 ---a/arch/s390/include/asm/gmap.h
+++b/arch/s390/include/asm/gmap.h(quoted diff) +1
-0@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start, void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4], unsigned long gaddr, unsigned long vmaddr); +int gmap_mark_unmergeable(void); #endif /* _ASM_S390_GMAP_H */arch/s390/kvm/kvm-s390.c +6
-0@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd) if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */ arch/s390/mm/gmap.c +0
-0@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie);
Quoted 13 lines
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2559
Quoted 10 lines
arch/s390/mm/gmap.c +9
-0+int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) { + mm->context.uses_skeys =0 ;That skey setting does not make too much sense when coming via
kvm_s390_handle_pv(). handle that in the caller?
protected guests run keyless; any attempt to use keys in the guest will result in an exception in the guest.
Quoted 42 lines
Quoted 40 lines
arch/s390/mm/gmap.c +8
-0+return -ENOMEM ; + } + } + mm->def_flags &= ~VM_MERGEABLE ; +return 0 ; +} +EXPORT_SYMBOL_GPL (gmap_mark_unmergeable); +/* * Enable storage key handling from now on and initialize the storage
* keys with the default key.arch/s390/mm/gmap.c +1
-10@@ -2593,7 +2610,6 @@ static const struct mm_walk_ops enable_skey_walk_ops = { int s390_enable_skey(void) {struct mm_struct *mm = current->mm; -struct vm_area_struct *vma;int rc =0 ;down_write (&mm->mmap_sem);@@ -2601,15 +2617,7 @@ int s390_enable_skey(void) goto out_up; mm->context.uses_skeys =1 ; -for (vma = mm->mmap; vma; vma = vma->vm_next) { -if (ksm_madvise (vma, vma->vm_start, vma->vm_end, -MADV_UNMERGEABLE , &vma->vm_flags)) { - mm->context.uses_skeys =0 ; - rc = -ENOMEM ; - goto out_up; - } - } - mm->def_flags &= ~VM_MERGEABLE ; +gmap_mark_unmergeable (); walk_page_range(mm, 0, TASK_SIZE, &enable_skey_walk_ops,NULL);
Re: [RFC 07/37] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 67 lines · Claudio Imbrenda
Quoted 50 lines · On Thu, 24 Oct 2019 18:07:14 +0200 David Hildenbrand <[email protected]> wrote:
Quoted 49 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-)(quoted diff) +0
-0
b/arch/s390/include/asm/gmap.hindex6efc0b501227..eab6a2ec3599100644 ---a/arch/s390/include/asm/gmap.h
+++b/arch/s390/include/asm/gmap.h(quoted diff) +1
-0@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start, void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4], unsigned long gaddr, unsigned long vmaddr); +int gmap_mark_unmergeable(void); #endif /* _ASM_S390_GMAP_H */arch/s390/kvm/kvm-s390.c +6
-0@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd) if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */ arch/s390/mm/gmap.c +0
-0@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie);Quoted 13 lines
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2559
Quoted 10 lines
arch/s390/mm/gmap.c +9
-0+int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) { + mm->context.uses_skeys =0 ;That skey setting does not make too much sense when coming via
kvm_s390_handle_pv(). handle that in the caller?
Quoted 2 lines
protected guests run keyless; any attempt to use keys in the guest will result in an exception in the guest.
still, this is the recovery path for the "mm->context.uses_skeys = 1;" in enable_skey_walk_ops() and confuses reader (like me).
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRe: [RFC 07/37] KVM: s390: protvirt: Secure memory is not mergeable
In reply to David HildenbrandQuoted 50 lines · David Hildenbrand
Quoted 49 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,void gmap_sync_dirty_log_pmd (struct gmap *gmap,unsigned long dirty_bitmap[4 ],unsigned long gaddr,unsigned long vmaddr); +int gmap_mark_unmergeable (void );#endif /* _ASM_S390_GMAP_H */ arch/s390/kvm/kvm-s390.c +6
-0@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */ arch/s390/mm/gmap.c +0
-0@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie);
Quoted 12 lines
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2559
Quoted 9 lines
arch/s390/mm/gmap.c +9
-0+int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) { + mm->context.uses_skeys =0 ;That skey setting does not make too much sense when coming via
kvm_s390_handle_pv(). handle that in the caller?
Hmm, I think the name of that variable is just plain wrong. It should be "can_use_skeys" or "uses_unmergeable" (which would fit better into the mm context anyway) and then we could add a kvm->arch.uses_skeys to tell that we actually used them for migration checks, etc..
I had long discussions with Martin over these variable names a long time ago..
Re: [RFC 07/37] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 64 lines · Janosch Frank
Quoted 50 lines · David Hildenbrand
Quoted 49 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,void gmap_sync_dirty_log_pmd (struct gmap *gmap,unsigned long dirty_bitmap[4 ],unsigned long gaddr,unsigned long vmaddr); +int gmap_mark_unmergeable (void );#endif /* _ASM_S390_GMAP_H */ arch/s390/kvm/kvm-s390.c +6
-0@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */ arch/s390/mm/gmap.c +0
-0@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie);Quoted 12 lines
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2559
Quoted 9 lines
arch/s390/mm/gmap.c +9
-0+int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) { + mm->context.uses_skeys =0 ;That skey setting does not make too much sense when coming via
kvm_s390_handle_pv(). handle that in the caller?
Quoted 8 lines
Hmm, I think the name of that variable is just plain wrong. It should be "
can_use_skeys" or "uses_unmergeable" (which would fit better into the mm context anyway) and then we could add akvm->arch.uses_skeysto tell that we actually used them for migration checks, etc..I had long discussions with Martin over these variable names a long time ago..
uses_skeys is set during s390_enable_skey(). that is used when we
a) Call an skey instruction
b) Migrate skeys
So it should match "uses" or what am I missing?
If you look at the users of "mm_uses_skeys(mm)" I think "uses_unmergeable" would actually be misleading. (e.g., pgste_set_key()). it really means "somebody used skeys". The unmergable is just a required side effect.
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRe: [RFC 07/37] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 79 lines · David Hildenbrand
Quoted 64 lines · Janosch Frank
Quoted 50 lines · David Hildenbrand
Quoted 49 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,void gmap_sync_dirty_log_pmd (struct gmap *gmap,unsigned long dirty_bitmap[4 ],unsigned long gaddr,unsigned long vmaddr); +int gmap_mark_unmergeable (void );#endif /* _ASM_S390_GMAP_H */ arch/s390/kvm/kvm-s390.c +6
-0@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */ arch/s390/mm/gmap.c +0
-0@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie);Quoted 12 lines
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2559
Quoted 9 lines
arch/s390/mm/gmap.c +9
-0+int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) { + mm->context.uses_skeys =0 ;That skey setting does not make too much sense when coming via
kvm_s390_handle_pv(). handle that in the caller?Quoted 8 lines
Hmm, I think the name of that variable is just plain wrong. It should be "
can_use_skeys" or "uses_unmergeable" (which would fit better into the mm context anyway) and then we could add akvm->arch.uses_skeysto tell that we actually used them for migration checks, etc..I had long discussions with Martin over these variable names a long time ago..
uses_skeysis set durings390_enable_skey(). that is used when wea) Call an skey instruction
b) Migrate skeys
Quoted 6 lines
So it should match "uses" or what am I missing?
If you look at the users of "
mm_uses_skeys(mm)" I think "uses_unmergeable" would actually be misleading. (e.g.,pgste_set_key()). it really means "somebody used skeys". The unmergable is just a required side effect.
Hmm, we couldn't check struct kvm from pgtable.c anyway.
Oh well, I still don't like it very much but your arguments are better :-) Let's fix this.
Re: [RFC 07/37] KVM: s390: protvirt: Secure memory is not mergeable
In reply to Janosch FrankQuoted 81 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 28 ++++++++++++++++++---------- 3 files changed, 25 insertions(+), 10 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,void gmap_sync_dirty_log_pmd (struct gmap *gmap,unsigned long dirty_bitmap[4 ],unsigned long gaddr,unsigned long vmaddr); +int gmap_mark_unmergeable (void );#endif /* _ASM_S390_GMAP_H */ arch/s390/kvm/kvm-s390.c +6
-0@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */ arch/s390/mm/gmap.c +17
-1@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie); +int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) { + mm->context.uses_skeys =0 ; +return -ENOMEM ; + } + } + mm->def_flags &= ~VM_MERGEABLE ; +return 0 ; +} +EXPORT_SYMBOL_GPL (gmap_mark_unmergeable); +/* * Enable storage key handling from now on and initialize the storage * keys with the default key. @@ -2593,7 +2610,6 @@ static const struct mm_walk_ops enable_skey_walk_ops = {int s390_enable_skey (void ) {struct mm_struct *mm = current->mm; -struct vm_area_struct *vma;int rc =0 ;down_write (&mm->mmap_sem);@@ -2601,15 +2617,7 @@ int s390_enable_skey(void) goto out_up; mm->context.uses_skeys =1 ;
arch/s390/mm/gmap.c int s390_enable_skey(void) · line 2620
Quoted 10 lines
arch/s390/mm/gmap.c +1
-9-for (vma = mm->mmap; vma; vma = vma->vm_next) { -if (ksm_madvise (vma, vma->vm_start, vma->vm_end, -MADV_UNMERGEABLE , &vma->vm_flags)) { - mm->context.uses_skeys =0 ; - rc = -ENOMEM ; - goto out_up; - } - } - mm->def_flags &= ~VM_MERGEABLE ; +gmap_mark_unmergeable ();
also, here we are now ignoring errors?
This looks broken.
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRFC v2 1/1 KVM: s390: protvirt: Secure memory is not mergeable
In reply to Janosch FrankKSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 32 +++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 11 deletions(-)
arch/s390/include/asm/gmap.h +1 -0
@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,void gmap_sync_dirty_log_pmd (struct gmap *gmap,unsigned long dirty_bitmap[4 ],unsigned long gaddr,unsigned long vmaddr); +int gmap_mark_unmergeable (void );#endif /* _ASM_S390_GMAP_H */
arch/s390/kvm/kvm-s390.c +6 -0
@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */
arch/s390/mm/gmap.c +21 -11
@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie); +int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) +return -ENOMEM ; + } + mm->def_flags &= ~VM_MERGEABLE ; + +return 0 ; +} +EXPORT_SYMBOL_GPL (gmap_mark_unmergeable); +/* * Enable storage key handling from now on and initialize the storage * keys with the default key.
@@ -2593,24 +2610,17 @@ static const struct mm_walk_ops enable_skey_walk_ops = {int s390_enable_skey (void ) {struct mm_struct *mm = current->mm; -struct vm_area_struct *vma;int rc =0 ;down_write (&mm->mmap_sem);if (mm_uses_skeys (mm)) goto out_up; - mm->context.uses_skeys =1 ; -for (vma = mm->mmap; vma; vma = vma->vm_next) { -if (ksm_madvise (vma, vma->vm_start, vma->vm_end, -MADV_UNMERGEABLE , &vma->vm_flags)) { - mm->context.uses_skeys =0 ; - rc = -ENOMEM ; - goto out_up; - } - } - mm->def_flags &= ~VM_MERGEABLE ; + rc =gmap_mark_unmergeable (); +if (rc) + goto out_up; + mm->context.uses_skeys =1 ;walk_page_range (mm,0 ,TASK_SIZE , &enable_skey_walk_ops,NULL ); out_up:
Signature · 1 line
2.20.1
Re: [RFC v2] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 8 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>
v2 Looks better.
Quoted 91 lines
--- arch/s390/include/asm/gmap.h | 1 + arch/s390/kvm/kvm-s390.c | 6 ++++++ arch/s390/mm/gmap.c | 32 +++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 11 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -145,4 +145,5 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,void gmap_sync_dirty_log_pmd (struct gmap *gmap,unsigned long dirty_bitmap[4 ],unsigned long gaddr,unsigned long vmaddr); +int gmap_mark_unmergeable (void );#endif /* _ASM_S390_GMAP_H */ arch/s390/kvm/kvm-s390.c +6
-0@@ -2176,6 +2176,12 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)if (r)break ; +down_write (¤t->mm->mmap_sem); + r =gmap_mark_unmergeable (); +up_write (¤t->mm->mmap_sem); +if (r) +break ; +mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm);/* FMT 4 SIE needs esca */ arch/s390/mm/gmap.c +21
-11@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie); +int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + + +for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) +return -ENOMEM ; + } + mm->def_flags &= ~VM_MERGEABLE ; + +return 0 ; +} +EXPORT_SYMBOL_GPL (gmap_mark_unmergeable); +/* * Enable storage key handling from now on and initialize the storage * keys with the default key. @@ -2593,24 +2610,17 @@ static const struct mm_walk_ops enable_skey_walk_ops = {int s390_enable_skey (void ) {struct mm_struct *mm = current->mm; -struct vm_area_struct *vma;int rc =0 ;down_write (&mm->mmap_sem);if (mm_uses_skeys (mm)) goto out_up; - mm->context.uses_skeys =1 ; -for (vma = mm->mmap; vma; vma = vma->vm_next) { -if (ksm_madvise (vma, vma->vm_start, vma->vm_end, -MADV_UNMERGEABLE , &vma->vm_flags)) { - mm->context.uses_skeys =0 ; - rc = -ENOMEM ; - goto out_up; - } - } - mm->def_flags &= ~VM_MERGEABLE ; + rc =gmap_mark_unmergeable (); +if (rc) + goto out_up; + mm->context.uses_skeys =1 ;walk_page_range (mm,0 ,TASK_SIZE , &enable_skey_walk_ops,NULL ); out_up:
Re: [RFC v2] KVM: s390: protvirt: Secure memory is not mergeable
In reply to Janosch FrankQuoted 6 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Patch itself looks good to me, but I do wonder: Is this really needed when pinning all encrypted pages currently?
Not sure about races between KSM and the pinning/encrypting thread, similar to paging, though ...
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRe: [RFC v2] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 5 lines · David Hildenbrand
Quoted 4 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Quoted 9 lines
Quoted 2 lines
Let's mark the guest pages as unmergeable when we transition to secure mode.
Patch itself looks good to me, but I do wonder: Is this really needed when pinning all encrypted pages currently?
Not sure about races between KSM and the pinning/encrypting thread, similar to paging, though ...
The pinning was added several months after I wrote the patch. Now that we have it, we really need to have another proper look at the whole topic.
Thanks for your review :-)
David Hildenbrand
Reviewed-byRe: [RFC v2] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 16 lines · Janosch Frank
Quoted 5 lines · David Hildenbrand
Quoted 4 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Quoted 9 lines
Quoted 2 lines
Let's mark the guest pages as unmergeable when we transition to secure mode.
Patch itself looks good to me, but I do wonder: Is this really needed when pinning all encrypted pages currently?
Not sure about races between KSM and the pinning/encrypting thread, similar to paging, though ...
Quoted 5 lines
The pinning was added several months after I wrote the patch. Now that we have it, we really need to have another proper look at the whole topic.
Thanks for your review :-)
I'd certainly prefer this patch (+some way to mlock) over pinning ;)
You can have
For this patch, if you end up needing it :)
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC v2] KVM: s390: protvirt: Secure memory is not mergeable
In reply to Janosch FrankQuoted 9 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>---
[...]
Quoted 5 lines
arch/s390/mm/gmap.c +0
-0
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2556
Quoted 9 lines
arch/s390/mm/gmap.c +6
-0@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie); +int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +
Please remove one of the two empty lines.
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2567
Quoted 11 lines
arch/s390/mm/gmap.c +11
-0+for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) +return -ENOMEM ; + } + mm->def_flags &= ~VM_MERGEABLE ; + +return 0 ; +} +EXPORT_SYMBOL_GPL (gmap_mark_unmergeable); +
[...]
Apart from the cosmetic nit, the patch looks fine to me.
Janosch Frank
maintainerRe: [RFC v2] KVM: s390: protvirt: Secure memory is not mergeable
Quoted 19 lines · Thomas Huth
Quoted 9 lines · Janosch Frank
KSM will not work on secure pages, because when the kernel reads a secure page, it will be encrypted and hence no two pages will look the same.
Let's mark the guest pages as unmergeable when we transition to secure mode.
Signed-off-by Janosch Frank <[email protected]>---
[...]
Quoted 8 lines
arch/s390/mm/gmap.c +0
-0@@ -2548,6 +2548,23 @@ int s390_enable_sie(void) }EXPORT_SYMBOL_GPL (s390_enable_sie);
Quoted 8 lines
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2556
Quoted 6 lines
arch/s390/mm/gmap.c +6
-0+int gmap_mark_unmergeable (void ) +{ +struct mm_struct *mm = current->mm; +struct vm_area_struct *vma; + +Please remove one of the two empty lines.
Already gone
Quoted 8 lines
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2563
Quoted 8 lines
arch/s390/mm/gmap.c +7
-0+for (vma = mm->mmap; vma; vma = vma->vm_next) { +if (ksm_madvise (vma, vma->vm_start, vma->vm_end, +MADV_UNMERGEABLE , &vma->vm_flags)) +return -ENOMEM ; + } + mm->def_flags &= ~VM_MERGEABLE ; +
Also this one was removed
Quoted 10 lines
arch/s390/mm/gmap.c int s390_enable_sie(void) · line 2567
Quoted 4 lines
arch/s390/mm/gmap.c +4
-0+return 0 ; +} +EXPORT_SYMBOL_GPL (gmap_mark_unmergeable); +[...]
Apart from the cosmetic nit, the patch looks fine to me.
Reviewed-by Thomas Huth <[email protected]>
Thanks!
Janosch Frank
maintainerRFC 8/37 KVM: s390: add missing include in gmap.h
In reply to Janosch FrankFrom: Claudio Imbrenda <[email protected]>
gmap.h references radix trees, but does not include linux/radix-tree.h itself. Sources that include gmap.h but not also radix-tree.h will therefore fail to compile.
This simple patch adds the include for linux/radix-tree.h in gmap.h so that users of gmap.h will be able to compile.
--- arch/s390/include/asm/gmap.h | 1 + 1 file changed, 1 insertion(+)
arch/s390/include/asm/gmap.h +1 -0
@@ -10,6 +10,7 @@#define _ASM_S390_GMAP_H#include <linux/refcount.h> +#include <linux/radix-tree.h> /* Generic bits for GMAP notification on DAT table entry changes. */ #define GMAP_NOTIFY_SHADOW 0x2
Signature · 1 line
2.20.1
Re: [RFC 08/37] KVM: s390: add missing include in gmap.h
Quoted 20 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
gmap.hreferences radix trees, but does not includelinux/radix-tree.hitself. Sources that includegmap.hbut not alsoradix-tree.hwill therefore fail to compile.This simple patch adds the include for
linux/radix-tree.hingmap.hso that users ofgmap.hwill be able to compile.Signed-off-by Claudio Imbrenda <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + 1 file changed, 1 insertion(+)arch/s390/include/asm/gmap.h +0
-0
arch/s390/include/asm/gmap.h line 16
Quoted 7 lines
arch/s390/include/asm/gmap.h +1
-0@@ -10,6 +10,7 @@#define _ASM_S390_GMAP_H#include <linux/refcount.h> +#include <linux/radix-tree.h> /* Generic bits for GMAP notification on DAT table entry changes. */ #define GMAP_NOTIFY_SHADOW 0x2
Not sure if that's worth a separate patch, just squash it into the patch that needs it?
We usually don't care about includes as long as it compiles ...
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 08/37] KVM: s390: add missing include in gmap.h
In reply to Janosch FrankQuoted 20 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
gmap.hreferences radix trees, but does not includelinux/radix-tree.hitself. Sources that includegmap.hbut not alsoradix-tree.hwill therefore fail to compile.This simple patch adds the include for
linux/radix-tree.hingmap.hso that users ofgmap.hwill be able to compile.Signed-off-by Claudio Imbrenda <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + 1 file changed, 1 insertion(+)arch/s390/include/asm/gmap.h +0
-0
arch/s390/include/asm/gmap.h line 16
Quoted 7 lines
arch/s390/include/asm/gmap.h +1
-0@@ -10,6 +10,7 @@#define _ASM_S390_GMAP_H#include <linux/refcount.h> +#include <linux/radix-tree.h> /* Generic bits for GMAP notification on DAT table entry changes. */ #define GMAP_NOTIFY_SHADOW 0x2
Janosch Frank
maintainerRFC 9/37 KVM: s390: protvirt: Implement on-demand pinning
In reply to Janosch FrankFrom: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
--- arch/s390/include/asm/gmap.h | 1 + arch/s390/include/asm/uv.h | 6 +++++ arch/s390/kernel/uv.c | 20 ++++++++++++++ arch/s390/kvm/kvm-s390.c | 2 ++ arch/s390/kvm/pv.c | 51 ++++++++++++++++++++++++++++++------ 5 files changed, 72 insertions(+), 8 deletions(-)
arch/s390/include/asm/gmap.h +1 -0
@@ -63,6 +63,7 @@ struct gmap {struct gmap *parent;unsigned long orig_asce;unsigned long se_handle; +struct page **pinned_pages;int edat_level;bool removed;bool initialized;
arch/s390/include/asm/uv.h +6 -0
@@ -298,6 +298,7 @@ static inline int uv_convert_from_secure(unsigned long paddr)return -EINVAL ; } +int kvm_s390_pv_pin_page (struct gmap *gmap,unsigned long gpa);/* * Requests the Ultravisor to make a page accessible to a guest * (import). If it's brought in the first time, it will be cleared. If
@@ -317,6 +318,11 @@ static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr) .gaddr = gaddr }; +down_read (&gmap->mm->mmap_sem); + cc =kvm_s390_pv_pin_page (gmap, gaddr); +up_read (&gmap->mm->mmap_sem); +if (cc) +return cc; cc =uv_call (0 , (u64)&uvcb);if (!cc)
arch/s390/kernel/uv.c +20 -0
@@ -98,4 +98,24 @@ void adjust_to_uv_max(unsigned long *vmax)if (prot_virt_host && *vmax > uv_info.max_sec_stor_addr) *vmax = uv_info.max_sec_stor_addr; } + +int kvm_s390_pv_pin_page (struct gmap *gmap,unsigned long gpa) +{ +unsigned long hva, gfn = gpa /PAGE_SIZE ; +int rc; + +if (!gmap->pinned_pages) +return -EINVAL ; + hva =__gmap_translate (gmap, gpa); +if (IS_ERR_VALUE (hva)) +return -EFAULT ; +if (gmap->pinned_pages[gfn]) +return -EEXIST ; + rc =get_user_pages_fast (hva,1 ,FOLL_WRITE , gmap->pinned_pages + gfn); +if (rc <0 ) +return rc; +return 0 ; +} +EXPORT_SYMBOL_GPL (kvm_s390_pv_pin_page); +#endif
arch/s390/kvm/kvm-s390.c +2 -0
@@ -2196,6 +2196,7 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)/* All VCPUs have to be destroyed before this call. */ mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm); +kvm_s390_pv_unpin (kvm); r =kvm_s390_pv_destroy_vm (kvm);if (!r)kvm_s390_pv_dealloc_vm (kvm);
@@ -2680,6 +2681,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)kvm_s390_gisa_destroy (kvm);if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) &&kvm_s390_pv_is_protected (kvm)) { +kvm_s390_pv_unpin (kvm);kvm_s390_pv_destroy_vm (kvm);kvm_s390_pv_dealloc_vm (kvm); }
arch/s390/kvm/pv.c +43 -8
86 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 4 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
Please explain why you do stuff. Why do we have to pin the hole guest memory? Why can't we mlock() the hole memory to avoid swapping in user space?
This really screams for a proper explanation.
Quoted 190 lines
Signed-off-by Claudio Imbrenda <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/include/asm/uv.h | 6 +++++ arch/s390/kernel/uv.c | 20 ++++++++++++++ arch/s390/kvm/kvm-s390.c | 2 ++ arch/s390/kvm/pv.c | 51 ++++++++++++++++++++++++++++++------ 5 files changed, 72 insertions(+), 8 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -63,6 +63,7 @@ struct gmap {struct gmap *parent;unsigned long orig_asce;unsigned long se_handle; +struct page **pinned_pages;int edat_level;bool removed;bool initialized;arch/s390/include/asm/uv.h +6
-0@@ -298,6 +298,7 @@ static inline int uv_convert_from_secure(unsigned long paddr)return -EINVAL ; } +int kvm_s390_pv_pin_page (struct gmap *gmap,unsigned long gpa);/* * Requests the Ultravisor to make a page accessible to a guest * (import). If it's brought in the first time, it will be cleared. If @@ -317,6 +318,11 @@ static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr) .gaddr = gaddr }; +down_read (&gmap->mm->mmap_sem); + cc =kvm_s390_pv_pin_page (gmap, gaddr); +up_read (&gmap->mm->mmap_sem); +if (cc) +return cc; cc =uv_call (0 , (u64)&uvcb);if (!cc)arch/s390/kernel/uv.c +20
-0@@ -98,4 +98,24 @@ void adjust_to_uv_max(unsigned long *vmax)if (prot_virt_host && *vmax > uv_info.max_sec_stor_addr) *vmax = uv_info.max_sec_stor_addr; } + +int kvm_s390_pv_pin_page (struct gmap *gmap,unsigned long gpa) +{ +unsigned long hva, gfn = gpa /PAGE_SIZE ; +int rc; + +if (!gmap->pinned_pages) +return -EINVAL ; + hva =__gmap_translate (gmap, gpa); +if (IS_ERR_VALUE (hva)) +return -EFAULT ; +if (gmap->pinned_pages[gfn]) +return -EEXIST ; + rc =get_user_pages_fast (hva,1 ,FOLL_WRITE , gmap->pinned_pages + gfn); +if (rc <0 ) +return rc; +return 0 ; +} +EXPORT_SYMBOL_GPL (kvm_s390_pv_pin_page); +#endif arch/s390/kvm/kvm-s390.c +2
-0@@ -2196,6 +2196,7 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)/* All VCPUs have to be destroyed before this call. */ mutex_lock (&kvm->lock);kvm_s390_vcpu_block_all (kvm); +kvm_s390_pv_unpin (kvm); r =kvm_s390_pv_destroy_vm (kvm);if (!r)kvm_s390_pv_dealloc_vm (kvm);@@ -2680,6 +2681,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)kvm_s390_gisa_destroy (kvm);if (IS_ENABLED (CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST ) &&kvm_s390_pv_is_protected (kvm)) { +kvm_s390_pv_unpin (kvm);kvm_s390_pv_destroy_vm (kvm);kvm_s390_pv_dealloc_vm (kvm); }arch/s390/kvm/pv.c +43
-8@@ -15,8 +15,35 @@#include <asm/mman.h> #include "kvm-s390.h" +static void unpin_destroy (struct page **pages,int nr) +{ +int i; +struct page *page; +u8 *val; + +for (i =0 ; i < nr; i++) { + page = pages[i]; +if (!page)/* page was never used */ +continue ; + val = (void *)page_to_phys (page); +READ_ONCE (*val); +put_page (page); + } +} + +void kvm_s390_pv_unpin (struct kvm *kvm) +{ +unsigned long npages = kvm->arch.pv.guest_len /PAGE_SIZE ; + +mutex_lock (&kvm->slots_lock); +unpin_destroy (kvm->arch.gmap->pinned_pages, npages); +mutex_unlock (&kvm->slots_lock); +} +void kvm_s390_pv_dealloc_vm (struct kvm *kvm) { +vfree (kvm->arch.gmap->pinned_pages); + kvm->arch.gmap->pinned_pages =NULL ;vfree (kvm->arch.pv.stor_var);free_pages (kvm->arch.pv.stor_base,get_order (uv_info.guest_base_stor_len));@@ -28,7 +55,6 @@ int kvm_s390_pv_alloc_vm(struct kvm *kvm)unsigned long base = uv_info.guest_base_stor_len;unsigned long virt = uv_info.guest_virt_var_stor_len;unsigned long npages =0 , vlen =0 ; -struct kvm_memslots *slots;struct kvm_memory_slot *memslot; kvm->arch.pv.stor_var =NULL ;@@ -43,22 +69,26 @@ int kvm_s390_pv_alloc_vm(struct kvm *kvm)* Slots are sorted by GFN */ mutex_lock (&kvm->slots_lock); - slots =kvm_memslots (kvm); - memslot = slots->memslots; + memslot =kvm_memslots (kvm)->memslots; npages = memslot->base_gfn + memslot->npages; -mutex_unlock (&kvm->slots_lock); + + kvm->arch.gmap->pinned_pages =vzalloc (npages *sizeof (struct page *)); +if (!kvm->arch.gmap->pinned_pages) + goto out_err; kvm->arch.pv.guest_len = npages *PAGE_SIZE ;/* Allocate variable storage */ vlen =ALIGN (virt * ((npages *PAGE_SIZE ) /HPAGE_SIZE ),PAGE_SIZE ); vlen += uv_info.guest_virt_base_stor_len; kvm->arch.pv.stor_var =vzalloc (vlen); -if (!kvm->arch.pv.stor_var) { -kvm_s390_pv_dealloc_vm (kvm); -return -ENOMEM ; - } +if (!kvm->arch.pv.stor_var) + goto out_err;return 0 ; + +out_err: +kvm_s390_pv_dealloc_vm (kvm); +return -ENOMEM ; }int kvm_s390_pv_destroy_vm (struct kvm *kvm)@@ -216,6 +246,11 @@ int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size,for (i =0 ; i < size /PAGE_SIZE ; i++) { uvcb.gaddr = addr + i *PAGE_SIZE ; uvcb.tweak[1 ] = i *PAGE_SIZE ; +down_read (&kvm->mm->mmap_sem); + rc =kvm_s390_pv_pin_page (kvm->arch.gmap, uvcb.gaddr); +up_read (&kvm->mm->mmap_sem); +if (rc && (rc != -EEXIST )) +break ; retry: rc =uv_call (0 , (u64)&uvcb);if (!rc)
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 7 lines · David Hildenbrand
Quoted 4 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
Please explain why you do stuff. Why do we have to pin the hole guest memory? Why can't we
mlock()the hole memory to avoid swapping in user space?
Basically we pin the guest for the same reason as AMD did it for their SEV. It is hard to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
As we do not want to rely on the userspace to do the mlock this is now done in the kernel.
Quoted 187 lines
This really screams for a proper explanation.
Quoted 183 lines
Signed-off-by Claudio Imbrenda <[email protected]>---
arch/s390/include/asm/gmap.h| 1 + arch/s390/include/asm/uv.h | 6 +++++ arch/s390/kernel/uv.c | 20 ++++++++++++++ arch/s390/kvm/kvm-s390.c | 2 ++
arch/s390/kvm/pv.c | 51 ++++++++++++++++++++++++++++++------5 files changed, 72 insertions(+), 8 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -63,6 +63,7 @@ struct gmap { struct gmap *parent; unsigned long orig_asce; unsigned long se_handle; + struct page **pinned_pages; int edat_level; bool removed; bool initialized;arch/s390/include/asm/uv.h +0
-0@@ -298,6 +298,7 @@ static inline int uv_convert_from_secure(unsigned long paddr) return -EINVAL; } +int kvm_s390_pv_pin_page(struct gmap *gmap, unsigned long gpa); /** Requests the Ultravisor to make a page accessible to a guest * (import). If it's brought in the first time, it will be cleared. If @@ -317,6 +318,11 @@ static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr).gaddr = gaddr
};
+down_read(&gmap->mm->mmap_sem);
+ cc =kvm_s390_pv_pin_page(gmap, gaddr);
+up_read(&gmap->mm->mmap_sem);
+ if (cc)
+ return cc;
cc =uv_call(0, (u64)&uvcb);
if (!cc)arch/s390/kernel/uv.c +20
-0@@ -98,4 +98,24 @@ void adjust_to_uv_max(unsigned long *vmax) if (prot_virt_host && *vmax > uv_info.max_sec_stor_addr) *vmax = uv_info.max_sec_stor_addr; } + +int kvm_s390_pv_pin_page (struct gmap *gmap,unsigned long gpa) +{ + unsigned long hva, gfn = gpa / PAGE_SIZE; + int rc; + + if (!gmap->pinned_pages) + return -EINVAL; + hva = __gmap_translate(gmap, gpa); + if (IS_ERR_VALUE(hva)) + return -EFAULT; + if (gmap->pinned_pages[gfn]) + return -EEXIST; + rc = get_user_pages_fast(hva, 1, FOLL_WRITE, gmap->pinned_pages + gfn); + if (rc < 0) + return rc; + return 0; +} +EXPORT_SYMBOL_GPL (kvm_s390_pv_pin_page); + #endifarch/s390/kvm/kvm-s390.c +1
-0@@ -2196,6 +2196,7 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd) /* All VCPUs have to be destroyed before this call. */ mutex_lock(&kvm->lock); kvm_s390_vcpu_block_all(kvm); + kvm_s390_pv_unpin(kvm); r = kvm_s390_pv_destroy_vm(kvm); if (!r) kvm_s390_pv_dealloc_vm(kvm);@@ -2680,6 +2681,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm) kvm_s390_gisa_destroy(kvm);if (
IS_ENABLED(CONFIG_KVM_S390_PROTECTED_VIRTUALIZATION_HOST)&&kvm_s390_pv_is_protected(kvm)) {
+kvm_s390_pv_unpin(kvm);kvm_s390_pv_destroy_vm(kvm);kvm_s390_pv_dealloc_vm(kvm);
}arch/s390/kvm/pv.c +42
-8@@ -15,8 +15,35 @@ #include <asm/mman.h> #include "kvm-s390.h" +static void unpin_destroy(struct page **pages, int nr) +{ + int i; + struct page *page; + u8 *val; + + for (i = 0; i < nr; i++) { + page = pages[i]; + if (!page) /* page was never used */ + continue; + val = (void *)page_to_phys(page); + READ_ONCE(*val); + put_page(page); + } +} + +void kvm_s390_pv_unpin (struct kvm *kvm) +{ + unsigned long npages = kvm->arch.pv.guest_len / PAGE_SIZE; + + mutex_lock(&kvm->slots_lock); + unpin_destroy(kvm->arch.gmap->pinned_pages, npages); + mutex_unlock(&kvm->slots_lock); +} + void kvm_s390_pv_dealloc_vm(struct kvm *kvm) { + vfree(kvm->arch.gmap->pinned_pages); + kvm->arch.gmap->pinned_pages = NULL; vfree(kvm->arch.pv.stor_var); free_pages(kvm->arch.pv.stor_base, get_order(uv_info.guest_base_stor_len));@@ -28,7 +55,6 @@ int kvm_s390_pv_alloc_vm(struct kvm *kvm) unsigned long base = uv_info.guest_base_stor_len; unsigned long virt = uv_info.guest_virt_var_stor_len; unsigned long npages = 0, vlen = 0; - struct kvm_memslots *slots; struct kvm_memory_slot *memslot; kvm->arch.pv.stor_var = NULL;@@ -43,22 +69,26 @@ int kvm_s390_pv_alloc_vm(struct kvm *kvm)* Slots are sorted by GFN */ mutex_lock(&kvm->slots_lock); - slots = kvm_memslots(kvm); - memslot = slots->memslots; + memslot = kvm_memslots(kvm)->memslots; npages = memslot->base_gfn + memslot->npages; - mutex_unlock(&kvm->slots_lock); + + kvm->arch.gmap->pinned_pages = vzalloc(npages * sizeof(struct page *)); + if (!kvm->arch.gmap->pinned_pages) + goto out_err; kvm->arch.pv.guest_len = npages * PAGE_SIZE; /* Allocate variable storage */ vlen = ALIGN(virt * ((npages * PAGE_SIZE) / HPAGE_SIZE), PAGE_SIZE); vlen += uv_info.guest_virt_base_stor_len; kvm->arch.pv.stor_var = vzalloc(vlen); - if (!kvm->arch.pv.stor_var) { - kvm_s390_pv_dealloc_vm(kvm); - return -ENOMEM; - } + if (!kvm->arch.pv.stor_var) + goto out_err; return 0; + +out_err: + kvm_s390_pv_dealloc_vm(kvm); + return -ENOMEM; } int kvm_s390_pv_destroy_vm(struct kvm *kvm)@@ -216,6 +246,11 @@ int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size, for (i = 0; i < size / PAGE_SIZE; i++) { uvcb.gaddr = addr + i * PAGE_SIZE; uvcb.tweak[1] = i * PAGE_SIZE; + down_read(&kvm->mm->mmap_sem); + rc = kvm_s390_pv_pin_page(kvm->arch.gmap, uvcb.gaddr); + up_read(&kvm->mm->mmap_sem); + if (rc && (rc != -EEXIST)) + break;retry:
rc =uv_call(0, (u64)&uvcb);
if (!rc)
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 4 lines · Christian Borntraeger
Quoted 1 line · David Hildenbrand
On 24.10.19 13:40, Janosch Frank wrote:
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
From: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
Please explain why you do stuff. Why do we have to pin the hole guest memory? Why can't we
mlock()the hole memory to avoid swapping in user space?Basically we pin the guest for the same reason as AMD did it for their SEV. It is hard
Pinning all guest memory is very ugly. What you want is "don't page", what you get is unmovable pages all over the place. I was hoping that you could get around this by having an automatic back-and-forth conversion in place (due to the special new exceptions).
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
A proper automatic conversion should make this work. What am I missing?
Quoted 2 lines
As we do not want to rely on the userspace to do the mlock this is now done in the kernel.
I wonder if we could come up with an alternative (similar to how we override VM_MERGEABLE in the kernel) that can be called and ensured in the kernel. E.g., marking whole VMAs as "don't page" (I remember something like "special VMAs" like used for VDSOs that achieve exactly that, but I am absolutely no expert on that). That would be much nicer than pinning all pages and remembering what you pinned in huge page arrays ...
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRe: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 10 lines · David Hildenbrand
Quoted 9 lines · Christian Borntraeger
Quoted 6 lines · David Hildenbrand
Quoted 4 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Please explain why you do stuff. Why do we have to pin the hole guest memory? Why can't we
mlock()the hole memory to avoid swapping in user space?Basically we pin the guest for the same reason as AMD did it for their SEV. It is hard
Pinning all guest memory is very ugly. What you want is "don't page", what you get is unmovable pages all over the place. I was hoping that you could get around this by having an automatic back-and-forth conversion in place (due to the special new exceptions).
Yes, that's one of the ideas that have been circulating.
Quoted 11 lines
Quoted 5 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
Quoted 6 lines
A proper automatic conversion should make this work. What am I missing?
Quoted 2 lines
As we do not want to rely on the userspace to do the mlock this is now done in the kernel.
Quoted 7 lines
I wonder if we could come up with an alternative (similar to how we override
VM_MERGEABLEin the kernel) that can be called and ensured in the kernel. E.g., marking whole VMAs as "don't page" (I remember something like "special VMAs" like used for VDSOs that achieve exactly that, but I am absolutely no expert on that). That would be much nicer than pinning all pages and remembering what you pinned in huge page arrays ...
It might be more worthwhile to just accept one or two releases with pinning and fix the root of the problem than design a nice stopgap.
Btw. s390 is not alone with the problem and we'll try to have another discussion tomorrow with AMD to find a solution which works for more than one architecture.
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/O
I assume that this is a corner case where we don't really have to care about performance in the first shot.
Quoted 15 lines
Quoted 7 lines
A proper automatic conversion should make this work. What am I missing?
Quoted 2 lines
As we do not want to rely on the userspace to do the mlock this is now done in the kernel.
Quoted 7 lines
I wonder if we could come up with an alternative (similar to how we override
VM_MERGEABLEin the kernel) that can be called and ensured in the kernel. E.g., marking whole VMAs as "don't page" (I remember something like "special VMAs" like used for VDSOs that achieve exactly that, but I am absolutely no expert on that). That would be much nicer than pinning all pages and remembering what you pinned in huge page arrays ...
Quoted 2 lines
It might be more worthwhile to just accept one or two releases with pinning and fix the root of the problem than design a nice stopgap.
Quite honestly, to me this feels like a prototype hack that deserves a proper solution first. The issue with this hack is that it affects user space (esp. MADV_DONTNEED no longer working correctly). It's not just something you once fix in the kernel and be done with it.
Quoted 4 lines
Btw. s390 is not alone with the problem and we'll try to have another discussion tomorrow with AMD to find a solution which works for more than one architecture.
Let me know if there was an interesting outcome.
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRe: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 23 lines · David Hildenbrand
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
How hard would it be to
Quoted 7 lines
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/OI assume that this is a corner case where we don't really have to care about performance in the first shot.
Restarting IO can be quite difficult with CCW, we might need to change request data...
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
A proper automatic conversion should make this work. What am I missing?
Quoted 2 lines
As we do not want to rely on the userspace to do the mlock this is now done in the kernel.
I wonder if we could come up with an alternative (similar to how we override
VM_MERGEABLEin the kernel) that can be called and ensured in the kernel. E.g., marking whole VMAs as "don't page" (I remember something like "special VMAs" like used for VDSOs that achieve exactly that, but I am absolutely no expert on that). That would be much nicer than pinning all pages and remembering what you pinned in huge page arrays ...
Quoted 7 lines
Quoted 2 lines
It might be more worthwhile to just accept one or two releases with pinning and fix the root of the problem than design a nice stopgap.
Quite honestly, to me this feels like a prototype hack that deserves a proper solution first. The issue with this hack is that it affects user space (esp.
MADV_DONTNEEDno longer working correctly). It's not just something you once fix in the kernel and be done with it.
It is a hack, yes.
But we're not the only architecture to need it x86 pins all the memory at the start of the VM and that code is already upstream...
Quoted 7 lines
Quoted 4 lines
Btw. s390 is not alone with the problem and we'll try to have another discussion tomorrow with AMD to find a solution which works for more than one architecture.
Let me know if there was an interesting outcome.
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 29 lines · Janosch Frank
Quoted 28 lines · David Hildenbrand
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/O
Quoted 5 lines
Quoted 2 lines
I assume that this is a corner case where we don't really have to care about performance in the first shot.
Restarting IO can be quite difficult with CCW, we might need to change request data...
I am no I/O expert, so I can't comment if that would be possible :(
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
Quoted 5 lines
A proper automatic conversion should make this work. What am I missing?
Quoted 2 lines
As we do not want to rely on the userspace to do the mlock this is now done in the kernel.
Quoted 7 lines
I wonder if we could come up with an alternative (similar to how we override
VM_MERGEABLEin the kernel) that can be called and ensured in the kernel. E.g., marking whole VMAs as "don't page" (I remember something like "special VMAs" like used for VDSOs that achieve exactly that, but I am absolutely no expert on that). That would be much nicer than pinning all pages and remembering what you pinned in huge page arrays ...It might be more worthwhile to just accept one or two releases with pinning and fix the root of the problem than design a nice stopgap.
Quoted 8 lines
Quoted 4 lines
Quite honestly, to me this feels like a prototype hack that deserves a proper solution first. The issue with this hack is that it affects user space (esp.
MADV_DONTNEEDno longer working correctly). It's not just something you once fix in the kernel and be done with it.It is a hack, yes.
But we're not the only architecture to need it x86 pins all the memory at the start of the VM and that code is already upstream...
IMHO that doesn't make it any better. It is and remains a prototype hack in my opinion.
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
In reply to David HildenbrandQuoted 21 lines · David Hildenbrand
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
Quoted 7 lines
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/OI assume that this is a corner case where we don't really have to care about performance in the first shot.
We have looked into this. You would need to implement this in the low level handler for every I/O. DASD, FCP, PCI based NVME, iscsi. Where do you want to stop?
There is no proper global bounce buffer that works for everything.
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
A proper automatic conversion should make this work. What am I missing?
Quoted 2 lines
As we do not want to rely on the userspace to do the mlock this is now done in the kernel.
I wonder if we could come up with an alternative (similar to how we override
VM_MERGEABLEin the kernel) that can be called and ensured in the kernel. E.g., marking whole VMAs as "don't page" (I remember something like "special VMAs" like used for VDSOs that achieve exactly that, but I am absolutely no expert on that). That would be much nicer than pinning all pages and remembering what you pinned in huge page arrays ...
Quoted 4 lines
Quoted 2 lines
It might be more worthwhile to just accept one or two releases with pinning and fix the root of the problem than design a nice stopgap.
Quite honestly, to me this feels like a prototype hack that deserves a proper solution first. The issue with this hack is that it affects user space (esp.
MADV_DONTNEEDno longer working correctly). It's not just something you once fix in the kernel and be done with it.
I disagree. Pinning is a valid initial version. I would find it strange to allow it for AMD SEV, but not allowing it for s390x.
As far as I can tell MADV_DONTNEED continues to work within the bounds of specification. In fact, it does work (or does not depending on your perspective :-) ) exactly in the same way as on hugetlbfs,which is also a way of pinning.
And yes, I am in full agreement that we must work on lifting that restriction.
Quoted 6 lines
Quoted 4 lines
Btw. s390 is not alone with the problem and we'll try to have another discussion tomorrow with AMD to find a solution which works for more than one architecture.
Let me know if there was an interesting outcome.
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 30 lines · Christian Borntraeger
Quoted 27 lines · David Hildenbrand
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/O
Quoted 5 lines
Quoted 1 line
I assume that this is a corner case where we don't really have to care about performance in the first shot.
We have looked into this. You would need to implement this in the low level handler for every I/O. DASD, FCP, PCI based NVME, iscsi. Where do you want to stop?
If that's the real fix, we should do that. Maybe one can focus on the real use cases first. But I am no I/O expert, so my judgment might be completely wrong.
Quoted 16 lines
There is no proper global bounce buffer that works for everything.
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
A proper automatic conversion should make this work. What am I missing?
Quoted 2 lines
As we do not want to rely on the userspace to do the mlock this is now done in the kernel.
I wonder if we could come up with an alternative (similar to how we override
VM_MERGEABLEin the kernel) that can be called and ensured in the kernel. E.g., marking whole VMAs as "don't page" (I remember something like "special VMAs" like used for VDSOs that achieve exactly that, but I am absolutely no expert on that). That would be much nicer than pinning all pages and remembering what you pinned in huge page arrays ...
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
It might be more worthwhile to just accept one or two releases with pinning and fix the root of the problem than design a nice stopgap.
Quite honestly, to me this feels like a prototype hack that deserves a proper solution first. The issue with this hack is that it affects user space (esp.
MADV_DONTNEEDno longer working correctly). It's not just something you once fix in the kernel and be done with it.I disagree. Pinning is a valid initial version. I would find it strange to allow it for AMD SEV, but not allowing it for s390x.
"not allowing" is wrong. I don't like it, but I am not NACKing it. All I am saying is that this is for me a big fat "prototype" marker.
As a workaround, I would much rather want to see a "don't page" control (process/vma) than pinning every single page if "paging" is the only concern. Such an internal handling would not imply any real user space changes (as noted, like MADV_DONTNEED would see).
Quoted 2 lines
As far as I can tell
MADV_DONTNEEDcontinues to work within the bounds of specification. In fact, it does work (or does not depending on your
There is a reason why we disallow MADV_DONTNEED in QEMU when we have such vfio devices (e.g., balloon, postcopy live migration, ...). It does no longer work as specified for devices that pinned pages. You get inconsistent mappings.
Quoted 2 lines
perspective :-) ) exactly in the same way as on hugetlbfs,which is also a way of pinning.
MADV_DONTNEED is documented to not work on huge pages. That's a different story. You have to use FALLOC_FL_PUNCH_HOLE.
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 33 lines · David Hildenbrand
Quoted 32 lines · Christian Borntraeger
Quoted 28 lines · David Hildenbrand
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/OI assume that this is a corner case where we don't really have to care about performance in the first shot.
Quoted 8 lines
Quoted 3 lines
We have looked into this. You would need to implement this in the low level handler for every I/O. DASD, FCP, PCI based NVME, iscsi. Where do you want to stop?
If that's the real fix, we should do that. Maybe one can focus on the real use cases first. But I am no I/O expert, so my judgment might be completely wrong.
Oh, and by the way, as discussed you really only have to care about accesses via "real" I/O devices (IOW, not via the CPU). When accessing via the CPU, you should have automatic conversion back and forth. As I am no expert on I/O, I have no idea how iscsi fits into this picture here (especially on s390x).
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 43 lines · On Mon, 4 Nov 2019 15:42:11 +0100 David Hildenbrand <[email protected]> wrote:
Quoted 33 lines · David Hildenbrand
Quoted 32 lines · Christian Borntraeger
Quoted 28 lines · David Hildenbrand
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/OI assume that this is a corner case where we don't really have to care about performance in the first shot.
Quoted 8 lines
Quoted 3 lines
We have looked into this. You would need to implement this in the low level handler for every I/O. DASD, FCP, PCI based NVME, iscsi. Where do you want to stop?
If that's the real fix, we should do that. Maybe one can focus on the real use cases first. But I am no I/O expert, so my judgment might be completely wrong.
Quoted 6 lines
Oh, and by the way, as discussed you really only have to care about accesses via "real" I/O devices (IOW, not via the CPU). When accessing via the CPU, you should have automatic conversion back and forth. As I am no expert on I/O, I have no idea how iscsi fits into this picture here (especially on s390x).
By "real" I/O devices, you mean things like channel devices, right? (So everything where you basically hand off control to a different kind of processor.)
For classic channel I/O (as used by dasd), I'd expect something like getting a check condition on a ccw if the CU or device cannot access the memory. You will know how far the channel program has progressed, and might be able to restart (from the beginning or from that point). Probably has a chance of working for a subset of channel programs.
For QDIO (as used by FCP), I have no idea how this is could work, as we have long-running channel programs there and any error basically kills the queues, which you would have to re-setup from the beginning.
For PCI devices, I have no idea how the instructions even act.
From my point of view, that error/restart approach looks nice on paper, but it seems hard to make it work in the general case (and I'm unsure if it's possible at all.)
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 53 lines · Cornelia Huck
Quoted 43 lines · On Mon, 4 Nov 2019 15:42:11 +0100 David Hildenbrand <[email protected]> wrote:
Quoted 33 lines · David Hildenbrand
Quoted 32 lines · Christian Borntraeger
Quoted 28 lines · David Hildenbrand
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/OI assume that this is a corner case where we don't really have to care about performance in the first shot.
Quoted 8 lines
Quoted 3 lines
We have looked into this. You would need to implement this in the low level handler for every I/O. DASD, FCP, PCI based NVME, iscsi. Where do you want to stop?
If that's the real fix, we should do that. Maybe one can focus on the real use cases first. But I am no I/O expert, so my judgment might be completely wrong.
Quoted 6 lines
Oh, and by the way, as discussed you really only have to care about accesses via "real" I/O devices (IOW, not via the CPU). When accessing via the CPU, you should have automatic conversion back and forth. As I am no expert on I/O, I have no idea how iscsi fits into this picture here (especially on s390x).
Quoted 3 lines
By "real" I/O devices, you mean things like channel devices, right? (So everything where you basically hand off control to a different kind of processor.)
Exactly.
Quoted 6 lines
For classic channel I/O (as used by dasd), I'd expect something like getting a check condition on a ccw if the CU or device cannot access the memory. You will know how far the channel program has progressed, and might be able to restart (from the beginning or from that point). Probably has a chance of working for a subset of channel programs.
Yeah, sound sane to me.
Quoted 10 lines
For QDIO (as used by FCP), I have no idea how this is could work, as we have long-running channel programs there and any error basically kills the queues, which you would have to re-setup from the beginning.
For PCI devices, I have no idea how the instructions even act.
From my point of view, that error/restart approach looks nice on paper,
but it seems hard to make it work in the general case (and I'm unsure if it's possible at all.)
Then I'm afraid whoever designed protected virtualization didn't properly consider concurrent I/O access to encrypted pages. It might not be easy to sort out, though, so I understand why the I/O part was designed that way :)
I was wondering if one could implement some kind of automatic conversion "back and forth" on I/O access (or even on any access within the HW). I mean, "basically" it's just encrypting/decrypting the page and updating the state by the UV (+ synchronization, lol). But yeah, the UV is involved, and would be triggered somehow via I/O access to these pages. Right now that conversion is performed via exceptions by the OS explicitly. Instead of passing exceptions, the UV could convert automatically. Smells like massive HW changes, if possible and desired at all.
I do wonder what would happen if you back your guest memory not on anonymous memory but on e.g., a file. Could be that this eliminates all options besides pinning and fixing I/O, because we're talking about writeback and not paging.
HOWEVER, reading https://lwn.net/Articles/787636/
"Kara talked mostly about the writeback code; in some cases, it will simply skip pages that are pinned. But there are cases where those pages must be written out — "somebody has called fsync(), and they expect something to be saved". In this case, pinned pages will be written, but they will not be marked clean at the end of the operation; they will still be write-protected in the page tables while writeback is underway, though."
So, sounds like you will get concurrent I/O access even without paging ... and that would leave fixing I/O the only option with the current HW design AFAIKS :/
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
In reply to Cornelia HuckQuoted 67 lines · Cornelia Huck
Quoted 43 lines · On Mon, 4 Nov 2019 15:42:11 +0100 David Hildenbrand <[email protected]> wrote:
Quoted 33 lines · David Hildenbrand
Quoted 32 lines · Christian Borntraeger
Quoted 28 lines · David Hildenbrand
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
to synchronize page import/export with the I/O for paging. For example you can actually fault in a page that is currently under paging I/O. What do you do? import (so that the guest can run) or export (so that the I/O will work). As this turned out to be harder then we though we decided to defer paging to a later point in time.
Quoted 8 lines
Quoted 5 lines
I don't quite see the issue yet. If you page out, the page will automatically (on access) be converted to !secure/encrypted memory. If the UV/guest wants to access it, it will be automatically converted to secure/unencrypted memory. If you have concurrent access, it will be converted back and forth until one party is done.
IO does not trigger an export on an imported page, but an error condition in the IO subsystem. The page code does not read pages through
Ah, that makes it much clearer. Thanks!
Quoted 4 lines
the cpu, but often just asks the device to read directly and that's where everything goes wrong. We could bounce swapping, but chose to pin for now until we find a proper solution to that problem which nicely integrates into linux.
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/OI assume that this is a corner case where we don't really have to care about performance in the first shot.
Quoted 8 lines
Quoted 3 lines
We have looked into this. You would need to implement this in the low level handler for every I/O. DASD, FCP, PCI based NVME, iscsi. Where do you want to stop?
If that's the real fix, we should do that. Maybe one can focus on the real use cases first. But I am no I/O expert, so my judgment might be completely wrong.
Quoted 6 lines
Oh, and by the way, as discussed you really only have to care about accesses via "real" I/O devices (IOW, not via the CPU). When accessing via the CPU, you should have automatic conversion back and forth. As I am no expert on I/O, I have no idea how iscsi fits into this picture here (especially on s390x).
By "real" I/O devices, you mean things like channel devices, right? (So everything where you basically hand off control to a different kind of processor.)
For classic channel I/O (as used by dasd), I'd expect something like getting a check condition on a ccw if the CU or device cannot access the memory. You will know how far the channel program has progressed, and might be able to restart (from the beginning or from that point). Probably has a chance of working for a subset of channel programs.
For QDIO (as used by FCP), I have no idea how this is could work, as we have long-running channel programs there and any error basically kills the queues, which you would have to re-setup from the beginning.
Quoted 5 lines
For PCI devices, I have no idea how the instructions even act.
From my point of view, that error/restart approach looks nice on paper,
but it seems hard to make it work in the general case (and I'm unsure if it's possible at all.)
One thought: If all we do during an I/O request is read or write (or even a mixture), can we simply restart the whole I/O again, although we did partial reads/writes? This would eliminate the "know how far the channel program has progressed". On error, one would have to touch each involved page (e.g., try to read first byte to trigger a conversion) and restart the I/O. I can understand that this might sound simpler than it is (if it is even possible) and might still be problematic for QDIO as far as I understand. Just a thought.
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 35 lines · On Mon, 4 Nov 2019 19:38:27 +0100 David Hildenbrand <[email protected]> wrote:
Quoted 34 lines · Cornelia Huck
Quoted 20 lines · On Mon, 4 Nov 2019 15:42:11 +0100 David Hildenbrand <[email protected]> wrote:
Quoted 10 lines · David Hildenbrand
Quoted 8 lines · Christian Borntraeger
Quoted 7 lines
How hard would it be to
1. Detect the error condition
2. Try a read on the affected page from the CPU (will will automatically convert to encrypted/!secure)
3. Restart the I/OI assume that this is a corner case where we don't really have to care about performance in the first shot.
Quoted 8 lines
Quoted 3 lines
We have looked into this. You would need to implement this in the low level handler for every I/O. DASD, FCP, PCI based NVME, iscsi. Where do you want to stop?
If that's the real fix, we should do that. Maybe one can focus on the real use cases first. But I am no I/O expert, so my judgment might be completely wrong.
Quoted 6 lines
Oh, and by the way, as discussed you really only have to care about accesses via "real" I/O devices (IOW, not via the CPU). When accessing via the CPU, you should have automatic conversion back and forth. As I am no expert on I/O, I have no idea how iscsi fits into this picture here (especially on s390x).
By "real" I/O devices, you mean things like channel devices, right? (So everything where you basically hand off control to a different kind of processor.)
Quoted 5 lines
Quoted 5 lines
For classic channel I/O (as used by dasd), I'd expect something like getting a check condition on a ccw if the CU or device cannot access the memory. You will know how far the channel program has progressed, and might be able to restart (from the beginning or from that point). Probably has a chance of working for a subset of channel programs.
NB that there's more than simple reads/writes... could also be control commands, some of which do read/writes as well.
Quoted 11 lines
Quoted 10 lines
For QDIO (as used by FCP), I have no idea how this is could work, as we have long-running channel programs there and any error basically kills the queues, which you would have to re-setup from the beginning.
For PCI devices, I have no idea how the instructions even act.
From my point of view, that error/restart approach looks nice on paper,
but it seems hard to make it work in the general case (and I'm unsure if it's possible at all.)
Quoted 7 lines
One thought: If all we do during an I/O request is read or write (or even a mixture), can we simply restart the whole I/O again, although we did partial reads/writes? This would eliminate the "know how far the channel program has progressed". On error, one would have to touch each involved page (e.g., try to read first byte to trigger a conversion) and restart the I/O. I can understand that this might sound simpler than it is (if it is even possible)
Any control commands might have side effects, though. Problems there should be uncommon; there's still the _general_ case, though :(
Also, there's stuff like rewriting the channel program w/o prefetch, jumping with TIC, etc. Linux probably does not do the former, but at least the dasd driver uses NOP/TIC for error recovery.
Quoted 2 lines
and might still be problematic for QDIO as
far as I understand. Just a thought.
Yes, given that for QDIO, establishing the queues is simply one long-running channel program...
Claudio Imbrenda
maintainerRe: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
In reply to David HildenbrandQuoted 14 lines · On Thu, 31 Oct 2019 18:30:30 +0100 David Hildenbrand <[email protected]> wrote:
Quoted 13 lines · Christian Borntraeger
Quoted 9 lines · David Hildenbrand
Quoted 4 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
Please explain why you do stuff. Why do we have to pin the hole guest memory? Why can't we
mlock()the hole memory to avoid swapping in user space?
Quoted 7 lines
Quoted 2 lines
Basically we pin the guest for the same reason as AMD did it for their SEV. It is hard
Pinning all guest memory is very ugly. What you want is "don't page", what you get is unmovable pages all over the place. I was hoping that you could get around this by having an automatic back-and-forth conversion in place (due to the special new exceptions).
we're not pinning all of guest memory, btw, but only the pages that are actually used.
so if you have a *huge* guest, only the few pages used by the kernel and initrd are actually pinned at VM start. Then one by one the ones actually used when the guest is running get pinned on first use.
I don't need to add anything regarding the other points since the other have commented already :)
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
Quoted 20 lines · Claudio Imbrenda
Quoted 17 lines · On Thu, 31 Oct 2019 18:30:30 +0100 David Hildenbrand <[email protected]> wrote:
Quoted 15 lines · Christian Borntraeger
Quoted 9 lines · David Hildenbrand
Quoted 4 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
Please explain why you do stuff. Why do we have to pin the hole guest memory? Why can't we
mlock()the hole memory to avoid swapping in user space?Basically we pin the guest for the same reason as AMD did it for their SEV. It is hard
Quoted 7 lines
Quoted 4 lines
Pinning all guest memory is very ugly. What you want is "don't page", what you get is unmovable pages all over the place. I was hoping that you could get around this by having an automatic back-and-forth conversion in place (due to the special new exceptions).
we're not pinning all of guest memory, btw, but only the pages that are actually used.
Any longer-running guest will eventually touch all guest physical memory (e.g., page cache, page shuffling), so this is only an optimization for short running guests.
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
In reply to Janosch FrankQuoted 6 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
Signed-off-by Claudio Imbrenda <[email protected]>
[...]
Quoted 9 lines
arch/s390/kvm/pv.c +1
-0@@ -15,8 +15,35 @@#include <asm/mman.h> #include "kvm-s390.h" +static void unpin_destroy (struct page **pages,int nr)
arch/s390/kvm/pv.c line 28
Quoted 10 lines
arch/s390/kvm/pv.c +10
-0+{ +int i; +struct page *page; +u8 *val; + +for (i =0 ; i < nr; i++) { + page = pages[i]; +if (!page)/* page was never used */ +continue ; + val = (void *)page_to_phys (page);
Why dont we call the convert from secure directly here to avoid the fault overhead?
arch/s390/kvm/pv.c line 30
Quoted 2 lines
arch/s390/kvm/pv.c +2
-0+READ_ONCE (*val); +put_page (page);
as we also do the export here (via implicit reading that page) this can take a while. I think we must add a cond_resched here.
Quoted 3 lines
arch/s390/kvm/pv.c +3
-0+ } +} +
[...]
Quoted 27 lines
arch/s390/kvm/pv.c +10
-5-mutex_unlock (&kvm->slots_lock); + + kvm->arch.gmap->pinned_pages =vzalloc (npages *sizeof (struct page *)); +if (!kvm->arch.gmap->pinned_pages) + goto out_err; kvm->arch.pv.guest_len = npages *PAGE_SIZE ;/* Allocate variable storage */ vlen =ALIGN (virt * ((npages *PAGE_SIZE ) /HPAGE_SIZE ),PAGE_SIZE ); vlen += uv_info.guest_virt_base_stor_len; kvm->arch.pv.stor_var =vzalloc (vlen); -if (!kvm->arch.pv.stor_var) { -kvm_s390_pv_dealloc_vm (kvm); -return -ENOMEM ; - } +if (!kvm->arch.pv.stor_var) + goto out_err;return 0 ; + +out_err: +kvm_s390_pv_dealloc_vm (kvm); +return -ENOMEM ; }int kvm_s390_pv_destroy_vm (struct kvm *kvm)
arch/s390/kvm/pv.c int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size, · line 251
Quoted 6 lines
arch/s390/kvm/pv.c +3
-0@@ -216,6 +246,11 @@ int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size,for (i =0 ; i < size /PAGE_SIZE ; i++) { uvcb.gaddr = addr + i *PAGE_SIZE ; uvcb.tweak[1 ] = i *PAGE_SIZE ; +down_read (&kvm->mm->mmap_sem); + rc =kvm_s390_pv_pin_page (kvm->arch.gmap, uvcb.gaddr); +up_read (&kvm->mm->mmap_sem);
Here we should also have a cond_resched();
Quoted 6 lines
arch/s390/kvm/pv.c +2
-0+if (rc && (rc != -EEXIST )) +break ; retry: rc =uv_call (0 , (u64)&uvcb);if (!rc)
Re: [RFC 09/37] KVM: s390: protvirt: Implement on-demand pinning
In reply to Janosch FrankQuoted 39 lines · Janosch Frank
From: Claudio Imbrenda <[email protected]>
Pin the guest pages when they are first accessed, instead of all at the same time when starting the guest.
Signed-off-by Claudio Imbrenda <[email protected]>--- arch/s390/include/asm/gmap.h | 1 + arch/s390/include/asm/uv.h | 6 +++++ arch/s390/kernel/uv.c | 20 ++++++++++++++ arch/s390/kvm/kvm-s390.c | 2 ++ arch/s390/kvm/pv.c | 51 ++++++++++++++++++++++++++++++------ 5 files changed, 72 insertions(+), 8 deletions(-)arch/s390/include/asm/gmap.h +1
-0@@ -63,6 +63,7 @@ struct gmap {struct gmap *parent;unsigned long orig_asce;unsigned long se_handle; +struct page **pinned_pages;int edat_level;bool removed;bool initialized;arch/s390/include/asm/uv.h +1
-0@@ -298,6 +298,7 @@ static inline int uv_convert_from_secure(unsigned long paddr)return -EINVAL ; } +int kvm_s390_pv_pin_page (struct gmap *gmap,unsigned long gpa);/* * Requests the Ultravisor to make a page accessible to a guest * (import). If it's brought in the first time, it will be cleared. If
arch/s390/include/asm/uv.h static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr) · line 326
Quoted 9 lines
arch/s390/include/asm/uv.h +5
-0@@ -317,6 +318,11 @@ static inline int uv_convert_to_secure(struct gmap *gmap, unsigned long gaddr) .gaddr = gaddr }; +down_read (&gmap->mm->mmap_sem); + cc =kvm_s390_pv_pin_page (gmap, gaddr); +up_read (&gmap->mm->mmap_sem); +if (cc) +return cc; cc =uv_call (0 , (u64)&uvcb);
So, a theoretical question: Is any in-flight I/O from paging stopped when we try to pin the pages? I am no export on paging, but the comment from Christian ("you can actually fault in a page that is currently under paging I/O.") made me wonder.
Let's assume you could have parallel I/O on that page. You would do a uv_call() and convert the page to secure/unencrypted. The I/O can easily stumble over that (now inaccessible) page and report an error.
Or is any such race not possible because we are using get_user_pages_fast() vs. get_user_pages()? (then, I'd love to see a comment regarding that in the patch description)
Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRFC 10/37 s390: add (non)secure page access exceptions handlers
In reply to Janosch FrankFrom: Vasily Gorbik <[email protected]>
Add exceptions handlers performing transparent transition of non-secure pages to secure (import) upon guest access and secure pages to non-secure (export) upon hypervisor access.
Current assumption is that guest pages are pinned.
--- arch/s390/kernel/pgm_check.S | 4 +-- arch/s390/mm/fault.c | 64 ++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-)
arch/s390/kernel/pgm_check.S +2 -2
@@ -78,8 +78,8 @@ PGM_CHECK(do_dat_exception) /* 39 */ PGM_CHECK(do_dat_exception) /* 3a */ PGM_CHECK(do_dat_exception) /* 3b */ PGM_CHECK_DEFAULT /* 3c */ -PGM_CHECK_DEFAULT /* 3d */ -PGM_CHECK_DEFAULT /* 3e */ +PGM_CHECK(do_secure_storage_access) /* 3d */ +PGM_CHECK(do_non_secure_storage_access) /* 3e */ PGM_CHECK_DEFAULT /* 3f */ PGM_CHECK_DEFAULT /* 40 */ PGM_CHECK_DEFAULT /* 41 */
arch/s390/mm/fault.c +64 -0
73 lines not on this page · raw message
Signature · 1 line
2.20.1
Janosch Frank
maintainerRFC 11/37 DOCUMENTATION: protvirt: Interrupt injection
In reply to Janosch FrankInterrupt injection has changed a lot for protected guests, as KVM can't access the cpus' lowcores. New fields in the state description, like the interrupt injection control, and masked values safeguard the guest from KVM.
Let's add some documentation to the interrupt injection basics for protected guests.
--- Documentation/virtual/kvm/s390-pv.txt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
Documentation/virtual/kvm/s390-pv.txt +27 -0
@@ -21,3 +21,30 @@ normally needed to be able to run a VM, some changes have been made in SIE behavior and fields have different meaning for a PVM. SIE exits are minimized as much as possible to improve speed and reduce exposed guest state. + + +Interrupt injection: + +Interrupt injection is safeguarded by the Ultravisor and, as KVM lost +access to the VCPUs' lowcores, is handled via the format 4 state +description. + +Machine check, external, IO and restart interruptions each can be +injected on SIE entry via a bit in the interrupt injection control +field (offset 0x54). If the guest cpu is not enabled for the interrupt +at the time of injection, a validity interception is recognized. The +interrupt's data is transported via parts of the interception data +block. + +Program and Service Call exceptions have another layer of +safeguarding, they are only injectable, when instructions have +intercepted into KVM and such an exception can be an emulation result. + + +Mask notification interceptions: +As a replacement for the lctl(g) and lpsw(e) interception, two new +interception codes have been introduced. One which tells us that CRs +0, 6 or 14 have been changed and therefore interrupt masking might +have changed. And one for PSW bit 13 changes. The CRs and the PSW in +the state description only contain the mask bits and no further info +like the current instruction address.
Signature · 1 line
2.20.1
Re: [RFC 11/37] DOCUMENTATION: protvirt: Interrupt injection
Quoted 25 lines · On Thu, 24 Oct 2019 07:40:33 -0400 Janosch Frank <[email protected]> wrote:
Interrupt injection has changed a lot for protected guests, as KVM can't access the cpus' lowcores. New fields in the state description, like the interrupt injection control, and masked values safeguard the guest from KVM.
Let's add some documentation to the interrupt injection basics for protected guests.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)Documentation/virtual/kvm/s390-pv.txt +4
-0@@ -21,3 +21,30 @@ normally needed to be able to run a VM, some changes have been made in SIE behavior and fields have different meaning for a PVM. SIE exits are minimized as much as possible to improve speed and reduce exposed guest state. + + +Interrupt injection: +
Documentation/virtual/kvm/s390-pv.txt normally needed to be able to run a VM, some changes have been made in · line 37
Quoted 10 lines
Documentation/virtual/kvm/s390-pv.txt +10
-0+Interrupt injection is safeguarded by the Ultravisor and, as KVM lost +access to the VCPUs' lowcores, is handled via the format 4 state +description. + +Machine check, external, IO and restart interruptions each can be +injected on SIE entry via a bit in the interrupt injection control +field (offset 0x54). If the guest cpu is not enabled for the interrupt +at the time of injection, a validity interception is recognized. The +interrupt's data is transported via parts of the interception data +block.
"Data associated with the interrupt needs to be placed into the respective fields in the interception data block to be injected into the guest."
?
Documentation/virtual/kvm/s390-pv.txt normally needed to be able to run a VM, some changes have been made in · line 41
Quoted 4 lines
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Program and Service Call exceptions have another layer of +safeguarding, they are only injectable, when instructions have +intercepted into KVM and such an exception can be an emulation result.
I find this sentence hard to parse... not sure if I understand it correctly.
"They can only be injected if the exception can be encountered during emulation of instructions that had been intercepted into KVM."
?
Documentation/virtual/kvm/s390-pv.txt normally needed to be able to run a VM, some changes have been made in · line 48
Quoted 7 lines
Documentation/virtual/kvm/s390-pv.txt +7
-0+ + +Mask notification interceptions: +As a replacement for the lctl(g) and lpsw(e) interception, two new +interception codes have been introduced. One which tells us that CRs +0, 6 or 14 have been changed and therefore interrupt masking might +have changed. And one for PSW bit 13 changes. The CRs and the PSW in
Might be helpful to mention that this bit covers machine checks, which do not get a separate bit in the control block :)
Documentation/virtual/kvm/s390-pv.txt normally needed to be able to run a VM, some changes have been made in · line 50
Quoted 2 lines
Documentation/virtual/kvm/s390-pv.txt +2
-0+the state description only contain the mask bits and no further info +like the current instruction address.
"The CRs and the PSW in the state description only contain the bits referring to interrupt masking; other fields like e.g. the current instruction address are zero."
?
Claudio Imbrenda
maintainerRe: [RFC 11/37] DOCUMENTATION: protvirt: Interrupt injection
Quoted 43 lines · On Thu, 14 Nov 2019 14:09:46 +0100 Cornelia Huck <[email protected]> wrote:
Quoted 32 lines · On Thu, 24 Oct 2019 07:40:33 -0400 Janosch Frank <[email protected]> wrote:
Interrupt injection has changed a lot for protected guests, as KVM can't access the cpus' lowcores. New fields in the state description, like the interrupt injection control, and masked values safeguard the guest from KVM.
Let's add some documentation to the interrupt injection basics for protected guests.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 27+++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
(quoted diff) +0
-0
b/Documentation/virtual/kvm/s390-pv.txtindex86ed95f36759..e09f2dc5f164100644 ---a/Documentation/virtual/kvm/s390-pv.txt+++b/Documentation/virtual/kvm/s390-pv.txt@@ -21,3 +21,30 @@ normally needed to be able to run a VM, some changes have been made in SIE behavior and fields have different meaning for a PVM. SIE exits are minimized as much as possible to improve speed and reduce exposed guest state. +Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Interrupt injection: + +Interrupt injection is safeguarded by the Ultravisor and, as KVMlost +access to the VCPUs' lowcores, is handled via the format 4 state +description.
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Machine check, external, IO and restart interruptions each can be +injected on SIE entry via a bit in the interrupt injection control +field (offset 0x54). If the guest cpu is not enabled for theQuoted 3 lines
interrupt +at the time of injection, a validity interception is recognized. The +interrupt's data is transported via parts of the interception data +block.
"Data associated with the interrupt needs to be placed into the respective fields in the interception data block to be injected into the guest."
Quoted 1 line
?
when a normal guest intercepts an exception, depending on the exception type, the parameters are saved in the state description at specified offsets, between 0xC0 amd 0xF8
to perform interrupt injection for secure guests, the same fields are used to specify the interrupt parameters that should be injected into the guest
Quoted 11 lines
Quoted 5 lines
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Program and Service Call exceptions have another layer of +safeguarding, they are only injectable, when instructions have +intercepted into KVM and such an exception can be an emulationresult.
I find this sentence hard to parse... not sure if I understand it correctly.
"They can only be injected if the exception can be encountered during emulation of instructions that had been intercepted into KVM."
yes
Quoted 13 lines
Quoted 9 lines
Documentation/virtual/kvm/s390-pv.txt +5
-0+ + +Mask notification interceptions: +As a replacement for the lctl(g) and lpsw(e) interception, two new +interception codes have been introduced. One which tells us thatCRs +0, 6 or 14 have been changed and therefore interrupt masking might +have changed. And one for PSW bit 13 changes. The CRs and the PSW in
Might be helpful to mention that this bit covers machine checks, which do not get a separate bit in the control block :)
Quoted 6 lines
Quoted 2 lines
+the state description only contain the mask bits and no further info +like the current instruction address.
"The CRs and the PSW in the state description only contain the bits referring to interrupt masking; other fields like e.g. the current instruction address are zero."
wait state is saved too
CC is write only, and is only inspected by hardware/firmware when KVM/qemu is interpreting an instruction that expects a new CC to be set, and then only the expected CCs are allowed (e.g. if an instruction only allows CC 0 or 3, 2 cannot be specified)
Re: [RFC 11/37] DOCUMENTATION: protvirt: Interrupt injection
Quoted 48 lines · On Thu, 14 Nov 2019 14:25:00 +0100 Claudio Imbrenda <[email protected]>…
Quoted 43 lines · On Thu, 14 Nov 2019 14:09:46 +0100 Cornelia Huck <[email protected]> wrote:
Quoted 32 lines · On Thu, 24 Oct 2019 07:40:33 -0400 Janosch Frank <[email protected]> wrote:
Interrupt injection has changed a lot for protected guests, as KVM can't access the cpus' lowcores. New fields in the state description, like the interrupt injection control, and masked values safeguard the guest from KVM.
Let's add some documentation to the interrupt injection basics for protected guests.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 27+++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
(quoted diff) +0
-0
b/Documentation/virtual/kvm/s390-pv.txtindex86ed95f36759..e09f2dc5f164100644 ---a/Documentation/virtual/kvm/s390-pv.txt+++b/Documentation/virtual/kvm/s390-pv.txt@@ -21,3 +21,30 @@ normally needed to be able to run a VM, some changes have been made in SIE behavior and fields have different meaning for a PVM. SIE exits are minimized as much as possible to improve speed and reduce exposed guest state. +Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Interrupt injection: + +Interrupt injection is safeguarded by the Ultravisor and, as KVMlost +access to the VCPUs' lowcores, is handled via the format 4 state +description.
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Machine check, external, IO and restart interruptions each can be +injected on SIE entry via a bit in the interrupt injection control +field (offset 0x54). If the guest cpu is not enabled for theQuoted 3 lines
interrupt +at the time of injection, a validity interception is recognized. The +interrupt's data is transported via parts of the interception data +block.
"Data associated with the interrupt needs to be placed into the respective fields in the interception data block to be injected into the guest."
Quoted 1 line
?
Quoted 7 lines
when a normal guest intercepts an exception, depending on the exception type, the parameters are saved in the state description at specified offsets, between
0xC0amd0xF8to perform interrupt injection for secure guests, the same fields are used to specify the interrupt parameters that should be injected into the guest
Ok, maybe add that as well.
Quoted 35 lines
Quoted 10 lines
Quoted 6 lines
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Program and Service Call exceptions have another layer of +safeguarding, they are only injectable, when instructions have +intercepted into KVM and such an exception can be an emulationresult.
I find this sentence hard to parse... not sure if I understand it correctly.
Quoted 2 lines
"They can only be injected if the exception can be encountered during emulation of instructions that had been intercepted into KVM."
yes
Quoted 13 lines
Quoted 9 lines
Documentation/virtual/kvm/s390-pv.txt +5
-0+ + +Mask notification interceptions: +As a replacement for the lctl(g) and lpsw(e) interception, two new +interception codes have been introduced. One which tells us thatCRs +0, 6 or 14 have been changed and therefore interrupt masking might +have changed. And one for PSW bit 13 changes. The CRs and the PSW in
Might be helpful to mention that this bit covers machine checks, which do not get a separate bit in the control block :)
Quoted 6 lines
Quoted 2 lines
+the state description only contain the mask bits and no further info +like the current instruction address.
"The CRs and the PSW in the state description only contain the bits referring to interrupt masking; other fields like e.g. the current instruction address are zero."
Quoted 6 lines
wait state is saved too
CC is write only, and is only inspected by hardware/firmware when KVM/qemu is interpreting an instruction that expects a new CC to be set, and then only the expected CCs are allowed (e.g. if an instruction only allows CC 0 or 3, 2 cannot be specified)
So I'm wondering how much of that should go into the document... maybe just
"The CRs and the PSW in the state description contain less information than for normal guests: most information that does not refer to interrupt masking is not available to the hypervisor."
?
Janosch Frank
maintainerRe: [RFC 11/37] DOCUMENTATION: protvirt: Interrupt injection
Quoted 103 lines · Cornelia Huck
Quoted 48 lines · On Thu, 14 Nov 2019 14:25:00 +0100 Claudio Imbrenda <[email protected]>…
Quoted 43 lines · On Thu, 14 Nov 2019 14:09:46 +0100 Cornelia Huck <[email protected]> wrote:
Quoted 32 lines · On Thu, 24 Oct 2019 07:40:33 -0400 Janosch Frank <[email protected]> wrote:
Interrupt injection has changed a lot for protected guests, as KVM can't access the cpus' lowcores. New fields in the state description, like the interrupt injection control, and masked values safeguard the guest from KVM.
Let's add some documentation to the interrupt injection basics for protected guests.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 27+++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
(quoted diff) +0
-0
b/Documentation/virtual/kvm/s390-pv.txtindex86ed95f36759..e09f2dc5f164100644 ---a/Documentation/virtual/kvm/s390-pv.txt+++b/Documentation/virtual/kvm/s390-pv.txt@@ -21,3 +21,30 @@ normally needed to be able to run a VM, some changes have been made in SIE behavior and fields have different meaning for a PVM. SIE exits are minimized as much as possible to improve speed and reduce exposed guest state. +Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Interrupt injection: + +Interrupt injection is safeguarded by the Ultravisor and, as KVMlost +access to the VCPUs' lowcores, is handled via the format 4 state +description.
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Machine check, external, IO and restart interruptions each can be +injected on SIE entry via a bit in the interrupt injection control +field (offset 0x54). If the guest cpu is not enabled for theQuoted 3 lines
interrupt +at the time of injection, a validity interception is recognized. The +interrupt's data is transported via parts of the interception data +block.
"Data associated with the interrupt needs to be placed into the respective fields in the interception data block to be injected into the guest."
Quoted 1 line
?
Quoted 7 lines
when a normal guest intercepts an exception, depending on the exception type, the parameters are saved in the state description at specified offsets, between
0xC0amd0xF8to perform interrupt injection for secure guests, the same fields are used to specify the interrupt parameters that should be injected into the guest
Ok, maybe add that as well.
Quoted 35 lines
Quoted 10 lines
Quoted 6 lines
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +Program and Service Call exceptions have another layer of +safeguarding, they are only injectable, when instructions have +intercepted into KVM and such an exception can be an emulationresult.
I find this sentence hard to parse... not sure if I understand it correctly.
Quoted 2 lines
"They can only be injected if the exception can be encountered during emulation of instructions that had been intercepted into KVM."
yes
Quoted 13 lines
Quoted 9 lines
Documentation/virtual/kvm/s390-pv.txt +5
-0+ + +Mask notification interceptions: +As a replacement for the lctl(g) and lpsw(e) interception, two new +interception codes have been introduced. One which tells us thatCRs +0, 6 or 14 have been changed and therefore interrupt masking might +have changed. And one for PSW bit 13 changes. The CRs and the PSW in
Might be helpful to mention that this bit covers machine checks, which do not get a separate bit in the control block :)
Quoted 6 lines
Quoted 2 lines
+the state description only contain the mask bits and no further info +like the current instruction address.
"The CRs and the PSW in the state description only contain the bits referring to interrupt masking; other fields like e.g. the current instruction address are zero."
Quoted 6 lines
wait state is saved too
CC is write only, and is only inspected by hardware/firmware when KVM/qemu is interpreting an instruction that expects a new CC to be set, and then only the expected CCs are allowed (e.g. if an instruction only allows CC 0 or 3, 2 cannot be specified)
Quoted 9 lines
So I'm wondering how much of that should go into the document... maybe just
"The CRs and the PSW in the state description contain less information than for normal guests: most information that does not refer to interrupt masking is not available to the hypervisor."
?
I'm not liking that too much and I'm also asking myself it makes sense to fix documentation via mails. How about an etherpad?
Janosch Frank
maintainerRFC 12/37 KVM: s390: protvirt: Handle SE notification interceptions
In reply to Janosch FrankSince KVM doesn't emulate any form of load control and load psw instructions anymore, we wouldn't get an interception if PSWs or CRs are changed in the guest. That means we can't inject IRQs right after the guest is enabled for them.
The new interception codes solve that problem by being a notification for changes to IRQ enablement relevant bits in CRs 0, 6 and 14, as well a the machine check mask bit in the PSW.
No special handling is needed for these interception codes, the KVM pre-run code will consult all necessary CRs and PSW bits and inject IRQs the guest is enabled for.
--- arch/s390/include/asm/kvm_host.h | 2 ++ arch/s390/kvm/intercept.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+)
arch/s390/include/asm/kvm_host.h +2 -0
@@ -210,6 +210,8 @@ struct kvm_s390_sie_block {#define ICPT_PARTEXEC 0x38#define ICPT_IOINST 0x40#define ICPT_KSS 0x5c +#define ICPT_PV_MCHKR 0x60 +#define ICPT_PV_INT_EN 0x64__u8 icptcode;/* 0x0050 */ __u8 icptstatus;/* 0x0051 */ __u16 ihcpu;/* 0x0052 */
arch/s390/kvm/intercept.c +18 -0
@@ -480,6 +480,24 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)case ICPT_KSS : rc =kvm_s390_skey_check_enable (vcpu);break ; +case ICPT_PV_MCHKR : +/* +* A protected guest changed PSW bit 13 to one and is now +* enabled for interrupts. The pre-run code will check +* the registers and inject pending MCHKs based on the +* PSW and CRs. No additional work to do. +*/ + rc =0 ; +break ; +case ICPT_PV_INT_EN : +/* +* A protected guest changed CR 0,6,14 and may now be +* enabled for interrupts. The pre-run code will check +* the registers and inject pending IRQs based on the +* CRs. No additional work to do. +*/ + rc =0 ; +break ;default :return -EOPNOTSUPP ; }
Signature · 1 line
2.20.1
Re: [RFC 12/37] KVM: s390: protvirt: Handle SE notification interceptions
Quoted 48 lines · Janosch Frank
Since KVM doesn't emulate any form of load control and load psw instructions anymore, we wouldn't get an interception if PSWs or CRs are changed in the guest. That means we can't inject IRQs right after the guest is enabled for them.
The new interception codes solve that problem by being a notification for changes to IRQ enablement relevant bits in CRs 0, 6 and 14, as well a the machine check mask bit in the PSW.
No special handling is needed for these interception codes, the KVM pre-run code will consult all necessary CRs and PSW bits and inject IRQs the guest is enabled for.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 2 ++ arch/s390/kvm/intercept.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+)arch/s390/include/asm/kvm_host.h +2
-0@@ -210,6 +210,8 @@ struct kvm_s390_sie_block {#define ICPT_PARTEXEC 0x38#define ICPT_IOINST 0x40#define ICPT_KSS 0x5c +#define ICPT_PV_MCHKR 0x60 +#define ICPT_PV_INT_EN 0x64__u8 icptcode;/* 0x0050 */ __u8 icptstatus;/* 0x0051 */ __u16 ihcpu;/* 0x0052 */ arch/s390/kvm/intercept.c +8
-0@@ -480,6 +480,24 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)case ICPT_KSS : rc =kvm_s390_skey_check_enable (vcpu);break ; +case ICPT_PV_MCHKR : +/* +* A protected guest changed PSW bit 13 to one and is now +* enabled for interrupts. The pre-run code will check +* the registers and inject pending MCHKs based on the +* PSW and CRs. No additional work to do. +*/ + rc =0 ;
arch/s390/kvm/intercept.c int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) · line 500
Quoted 10 lines
arch/s390/kvm/intercept.c +10
-0+break ; +case ICPT_PV_INT_EN : +/* +* A protected guest changed CR 0,6,14 and may now be +* enabled for interrupts. The pre-run code will check +* the registers and inject pending IRQs based on the +* CRs. No additional work to do. +*/ + rc =0 ; +break ;
Wrong indentation.
Maybe simply
case ICPT_PV_MCHKR:ICPT_PV_INT_EN:
/*
* PSW bit 13 or a CR (0, 6, 14) changed and we might now be
* able to deliver interrupts. pre-run code will take care of
* this.
*/
rc = 0;
break;Signature · 3 lines
Thanks, David / dhildenb
Janosch Frank
maintainerRe: [RFC 12/37] KVM: s390: protvirt: Handle SE notification interceptions
Quoted 66 lines · David Hildenbrand
Quoted 48 lines · Janosch Frank
Since KVM doesn't emulate any form of load control and load psw instructions anymore, we wouldn't get an interception if PSWs or CRs are changed in the guest. That means we can't inject IRQs right after the guest is enabled for them.
The new interception codes solve that problem by being a notification for changes to IRQ enablement relevant bits in CRs 0, 6 and 14, as well a the machine check mask bit in the PSW.
No special handling is needed for these interception codes, the KVM pre-run code will consult all necessary CRs and PSW bits and inject IRQs the guest is enabled for.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 2 ++ arch/s390/kvm/intercept.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+)arch/s390/include/asm/kvm_host.h +2
-0@@ -210,6 +210,8 @@ struct kvm_s390_sie_block {#define ICPT_PARTEXEC 0x38#define ICPT_IOINST 0x40#define ICPT_KSS 0x5c +#define ICPT_PV_MCHKR 0x60 +#define ICPT_PV_INT_EN 0x64__u8 icptcode;/* 0x0050 */ __u8 icptstatus;/* 0x0051 */ __u16 ihcpu;/* 0x0052 */ arch/s390/kvm/intercept.c +8
-0@@ -480,6 +480,24 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)case ICPT_KSS : rc =kvm_s390_skey_check_enable (vcpu);break ; +case ICPT_PV_MCHKR : +/* +* A protected guest changed PSW bit 13 to one and is now +* enabled for interrupts. The pre-run code will check +* the registers and inject pending MCHKs based on the +* PSW and CRs. No additional work to do. +*/ + rc =0 ;arch/s390/kvm/intercept.c int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) · line 500
Quoted 10 lines
arch/s390/kvm/intercept.c +10
-0+break ; +case ICPT_PV_INT_EN : +/* +* A protected guest changed CR 0,6,14 and may now be +* enabled for interrupts. The pre-run code will check +* the registers and inject pending IRQs based on the +* CRs. No additional work to do. +*/ + rc =0 ; +break ;Wrong indentation.
Maybe simply
case
ICPT_PV_MCHKR:ICPT_PV_INT_EN:
Quoted 7 lines
/*
* PSW bit 13 or a CR (0, 6, 14) changed and we might now be
* able to deliver interrupts. pre-run code will take care of
* this.
*/
rc = 0;
break;Sounds good, I'll fix it
Re: [RFC 12/37] KVM: s390: protvirt: Handle SE notification interceptions
In reply to Janosch FrankQuoted 5 lines · On Thu, 24 Oct 2019 07:40:34 -0400 Janosch Frank <[email protected]> wrote:
Since KVM doesn't emulate any form of load control and load psw instructions anymore, we wouldn't get an interception if PSWs or CRs are changed in the guest. That means we can't inject IRQs right after the guest is enabled for them.
Quoted 7 lines
The new interception codes solve that problem by being a notification for changes to IRQ enablement relevant bits in CRs 0, 6 and 14, as well a the machine check mask bit in the PSW.
No special handling is needed for these interception codes, the KVM pre-run code will consult all necessary CRs and PSW bits and inject IRQs the guest is enabled for.
Just to clarify: The hypervisor can still access the relevant bits for pv guests, this is only about the notification, right?
Quoted 6 lines
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 2 ++ arch/s390/kvm/intercept.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+)
Re: [RFC 12/37] KVM: s390: protvirt: Handle SE notification interceptions
Quoted 12 lines · Cornelia Huck
Quoted 9 lines · On Thu, 24 Oct 2019 07:40:34 -0400 Janosch Frank <[email protected]> wrote:
Since KVM doesn't emulate any form of load control and load psw instructions anymore, we wouldn't get an interception if PSWs or CRs are changed in the guest. That means we can't inject IRQs right after the guest is enabled for them.
The new interception codes solve that problem by being a notification for changes to IRQ enablement relevant bits in CRs 0, 6 and 14, as well a the machine check mask bit in the PSW.
Quoted 7 lines
Quoted 3 lines
No special handling is needed for these interception codes, the KVM pre-run code will consult all necessary CRs and PSW bits and inject IRQs the guest is enabled for.
Just to clarify: The hypervisor can still access the relevant bits for pv guests, this is only about the notification, right?
Yes, the hypervisor (KVM) can always read the relevant PSW bits (I,E,M) and CR bits to decide if an interrupt can be delivered. All other bits of PSW and CRx are masked though.
This is a new intercept for notification as we do no longer get an IC4 (instruction to handle) for load control and friends so that we can re-check the bits.
Quoted 7 lines
Quoted 6 lines
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 2 ++ arch/s390/kvm/intercept.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+)
Re: [RFC 12/37] KVM: s390: protvirt: Handle SE notification interceptions
Quoted 21 lines · On Tue, 5 Nov 2019 19:15:19 +0100 Christian Borntraeger…
Quoted 12 lines · Cornelia Huck
Quoted 9 lines · On Thu, 24 Oct 2019 07:40:34 -0400 Janosch Frank <[email protected]> wrote:
Since KVM doesn't emulate any form of load control and load psw instructions anymore, we wouldn't get an interception if PSWs or CRs are changed in the guest. That means we can't inject IRQs right after the guest is enabled for them.
The new interception codes solve that problem by being a notification for changes to IRQ enablement relevant bits in CRs 0, 6 and 14, as well a the machine check mask bit in the PSW.
Quoted 7 lines
Quoted 3 lines
No special handling is needed for these interception codes, the KVM pre-run code will consult all necessary CRs and PSW bits and inject IRQs the guest is enabled for.
Just to clarify: The hypervisor can still access the relevant bits for pv guests, this is only about the notification, right?
Quoted 5 lines
Yes, the hypervisor (KVM) can always read the relevant PSW bits (I,E,M) and CR bits to decide if an interrupt can be delivered. All other bits of PSW and CRx are masked though.
This is a new intercept for notification as we do no longer get an IC4 (instruction to handle) for load control and friends so that we can re-check the bits.
Ok, thanks!
Quoted 8 lines
Quoted 7 lines
Quoted 6 lines
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 2 ++ arch/s390/kvm/intercept.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+)
Janosch Frank
maintainerRFC 13/37 KVM: s390: protvirt: Add interruption injection controls
In reply to Janosch FrankFrom: Michael Mueller <[email protected]>
Define the interruption injection codes and the related fields in the sie control block for PVM interruption injection.
--- arch/s390/include/asm/kvm_host.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
arch/s390/include/asm/kvm_host.h +21 -4
@@ -215,7 +215,15 @@ struct kvm_s390_sie_block {__u8 icptcode;/* 0x0050 */ __u8 icptstatus;/* 0x0051 */ __u16 ihcpu;/* 0x0052 */ -__u8 reserved54[2 ];/* 0x0054 */ +__u8 reserved54;/* 0x0054 */ +#define IICTL_CODE_NONE 0x00 +#define IICTL_CODE_MCHK 0x01 +#define IICTL_CODE_EXT 0x02 +#define IICTL_CODE_IO 0x03 +#define IICTL_CODE_RESTART 0x04 +#define IICTL_CODE_SPECIFICATION 0x10 +#define IICTL_CODE_OPERAND 0x11 +__u8 iictl;/* 0x0055 */ __u16 ipa;/* 0x0056 */ __u32 ipb;/* 0x0058 */ __u32 scaoh;/* 0x005c */
@@ -252,7 +260,8 @@ struct kvm_s390_sie_block {#define HPID_KVM 0x4#define HPID_VSIE 0x5__u8 hpid;/* 0x00b8 */ -__u8 reservedb9[11 ];/* 0x00b9 */ +__u8 reservedb9[7 ];/* 0x00b9 */ +__u32 eiparams;/* 0x00c0 */ __u16 extcpuaddr;/* 0x00c4 */ __u16 eic;/* 0x00c6 */ __u32 reservedc8;/* 0x00c8 */
@@ -268,8 +277,16 @@ struct kvm_s390_sie_block {__u8 oai;/* 0x00e2 */ __u8 armid;/* 0x00e3 */ __u8 reservede4[4 ];/* 0x00e4 */ -__u64 tecmc;/* 0x00e8 */ -__u8 reservedf0[12 ];/* 0x00f0 */ +union { +__u64 tecmc;/* 0x00e8 */ +struct { +__u16 subchannel_id;/* 0x00e8 */ +__u16 subchannel_nr;/* 0x00ea */ +__u32 io_int_parm;/* 0x00ec */ +__u32 io_int_word;/* 0x00f0 */ + }; + } __packed; +__u8 reservedf4[8 ];/* 0x00f4 */ #define CRYCB_FORMAT_MASK 0x00000003#define CRYCB_FORMAT0 0x00000000#define CRYCB_FORMAT1 0x00000001
Signature · 1 line
2.20.1
Re: [RFC 13/37] KVM: s390: protvirt: Add interruption injection controls
Quoted 45 lines · Janosch Frank
From: Michael Mueller <[email protected]>
Define the interruption injection codes and the related fields in the sie control block for PVM interruption injection.
Signed-off-by Michael Mueller <[email protected]>--- arch/s390/include/asm/kvm_host.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)arch/s390/include/asm/kvm_host.h +11
-2@@ -215,7 +215,15 @@ struct kvm_s390_sie_block {__u8 icptcode;/* 0x0050 */ __u8 icptstatus;/* 0x0051 */ __u16 ihcpu;/* 0x0052 */ -__u8 reserved54[2 ];/* 0x0054 */ +__u8 reserved54;/* 0x0054 */ +#define IICTL_CODE_NONE 0x00 +#define IICTL_CODE_MCHK 0x01 +#define IICTL_CODE_EXT 0x02 +#define IICTL_CODE_IO 0x03 +#define IICTL_CODE_RESTART 0x04 +#define IICTL_CODE_SPECIFICATION 0x10 +#define IICTL_CODE_OPERAND 0x11 +__u8 iictl;/* 0x0055 */ __u16 ipa;/* 0x0056 */ __u32 ipb;/* 0x0058 */ __u32 scaoh;/* 0x005c */ @@ -252,7 +260,8 @@ struct kvm_s390_sie_block {#define HPID_KVM 0x4#define HPID_VSIE 0x5__u8 hpid;/* 0x00b8 */ -__u8 reservedb9[11 ];/* 0x00b9 */ +__u8 reservedb9[7 ];/* 0x00b9 */ +__u32 eiparams;/* 0x00c0 */ __u16 extcpuaddr;/* 0x00c4 */ __u16 eic;/* 0x00c6 */ __u32 reservedc8;/* 0x00c8 */ @@ -268,8 +277,16 @@ struct kvm_s390_sie_block {__u8 oai;/* 0x00e2 */ __u8 armid;/* 0x00e3 */ __u8 reservede4[4 ];/* 0x00e4 */
arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 287
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +8
-2-__u64 tecmc;/* 0x00e8 */ -__u8 reservedf0[12 ];/* 0x00f0 */ +union { +__u64 tecmc;/* 0x00e8 */ +struct { +__u16 subchannel_id;/* 0x00e8 */ +__u16 subchannel_nr;/* 0x00ea */ +__u32 io_int_parm;/* 0x00ec */ +__u32 io_int_word;/* 0x00f0 */ + };
I only wonder if we should give this member a fitting name, e.g., "ioparams"
Quoted 6 lines
arch/s390/include/asm/kvm_host.h +2
-0+ } __packed; +__u8 reservedf4[8 ];/* 0x00f4 */ #define CRYCB_FORMAT_MASK 0x00000003#define CRYCB_FORMAT0 0x00000000#define CRYCB_FORMAT1 0x00000001
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 13/37] KVM: s390: protvirt: Add interruption injection controls
Quoted 8 lines · David Hildenbrand
Quoted 8 lines
(quoted diff) +0
-0@@ -268,8 +277,16 @@ struct kvm_s390_sie_block {__u8 oai; /*
0x00e2*/
__u8 armid; /*0x00e3*/
__u8 reservede4[4]; /*0x00e4*/
- __u64 tecmc; /*0x00e8*/
- __u8 reservedf0[12]; /*0x00f0*/
+ union {
+ __u64 tecmc; /*0x00e8*/
Quoted 8 lines
Quoted 6 lines
+ struct {
+ __u16 subchannel_id; /*0x00e8*/ + __u16 subchannel_nr; /*0x00ea*/ + __u32 io_int_parm; /*0x00ec*/ + __u32 io_int_word; /*0x00f0*/ + };I only wonder if we should give this member a fitting name, e.g., "ioparams"
Do you see a real gain for that? We have a lot of other unnamed structs defined here as well.
Quoted 7 lines
Quoted 7 lines
+ }
__packed;
+ __u8 reservedf4[8]; /*0x00f4*/
#defineCRYCB_FORMAT_MASK0x00000003
#defineCRYCB_FORMAT00x00000000
#defineCRYCB_FORMAT10x00000001
Thanks,
Michael
Re: [RFC 13/37] KVM: s390: protvirt: Add interruption injection controls
Quoted 21 lines · Michael Mueller
Quoted 9 lines · David Hildenbrand
Quoted 9 lines
(quoted diff) +0
-0@@ -268,8 +277,16 @@ struct kvm_s390_sie_block {__u8 oai; /*
0x00e2*/
__u8 armid; /*0x00e3*/
__u8 reservede4[4]; /*0x00e4*/
- __u64 tecmc; /*0x00e8*/
- __u8 reservedf0[12]; /*0x00f0*/
+ union {
+ __u64 tecmc; /*0x00e8*/
+ struct {Quoted 8 lines
Quoted 5 lines
+ __u16 subchannel_id; /*
0x00e8*/ + __u16 subchannel_nr; /*0x00ea*/ + __u32 io_int_parm; /*0x00ec*/ + __u32 io_int_word; /*0x00f0*/ + };I only wonder if we should give this member a fitting name, e.g., "ioparams"
Quoted 2 lines
Do you see a real gain for that? We have a lot of other unnamed structs defined here as well.
I was wondering if we could just copy the whole struct when delivering the interrupt.
You could even reuse "struct kvm_s390_io_info" here to make that more clear.
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 13/37] KVM: s390: protvirt: Add interruption injection controls
Quoted 22 lines · David Hildenbrand
Quoted 21 lines · Michael Mueller
Quoted 17 lines · David Hildenbrand
Quoted 4 lines
arch/s390/include/asm/kvm_host.h +0
-0@@ -268,8 +277,16 @@ struct kvm_s390_sie_block { __u8 oai; /* 0x00e2 */ __u8 armid; /* 0x00e3 */ __u8 reservede4[4]; /* 0x00e4 */arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 287
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +8
-2- __u64 tecmc; /* 0x00e8 */ - __u8 reservedf0[12]; /* 0x00f0 */ + union { + __u64 tecmc; /* 0x00e8 */ + struct { + __u16 subchannel_id; /* 0x00e8 */ + __u16 subchannel_nr; /* 0x00ea */ + __u32 io_int_parm; /* 0x00ec */ + __u32 io_int_word; /* 0x00f0 */ + };I only wonder if we should give this member a fitting name, e.g., "ioparams"
Quoted 8 lines
Quoted 2 lines
Do you see a real gain for that? We have a lot of other unnamed structs defined here as well.
I was wondering if we could just copy the whole struct when delivering the interrupt.
You could even reuse "struct
kvm_s390_io_info" here to make that more clear.
I want to keep it the way it is to have the fields in the SCB declaration explicit.
Thanks,
Michael
Re: [RFC 13/37] KVM: s390: protvirt: Add interruption injection controls
In reply to Janosch FrankQuoted 47 lines · On Thu, 24 Oct 2019 07:40:35 -0400 Janosch Frank <[email protected]> wrote:
From: Michael Mueller <[email protected]>
Define the interruption injection codes and the related fields in the sie control block for PVM interruption injection.
Signed-off-by Michael Mueller <[email protected]>--- arch/s390/include/asm/kvm_host.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)arch/s390/include/asm/kvm_host.h +11
-4@@ -215,7 +215,15 @@ struct kvm_s390_sie_block {__u8 icptcode;/* 0x0050 */ __u8 icptstatus;/* 0x0051 */ __u16 ihcpu;/* 0x0052 */ -__u8 reserved54[2 ];/* 0x0054 */ +__u8 reserved54;/* 0x0054 */ +#define IICTL_CODE_NONE 0x00 +#define IICTL_CODE_MCHK 0x01 +#define IICTL_CODE_EXT 0x02 +#define IICTL_CODE_IO 0x03 +#define IICTL_CODE_RESTART 0x04 +#define IICTL_CODE_SPECIFICATION 0x10 +#define IICTL_CODE_OPERAND 0x11 +__u8 iictl;/* 0x0055 */ __u16 ipa;/* 0x0056 */ __u32 ipb;/* 0x0058 */ __u32 scaoh;/* 0x005c */ @@ -252,7 +260,8 @@ struct kvm_s390_sie_block {#define HPID_KVM 0x4#define HPID_VSIE 0x5__u8 hpid;/* 0x00b8 */ -__u8 reservedb9[11 ];/* 0x00b9 */ +__u8 reservedb9[7 ];/* 0x00b9 */ +__u32 eiparams;/* 0x00c0 */ __u16 extcpuaddr;/* 0x00c4 */ __u16 eic;/* 0x00c6 */ __u32 reservedc8;/* 0x00c8 */ @@ -268,8 +277,16 @@ struct kvm_s390_sie_block {__u8 oai;/* 0x00e2 */ __u8 armid;/* 0x00e3 */ __u8 reservede4[4 ];/* 0x00e4 */ -__u64 tecmc;/* 0x00e8 */ -__u8 reservedf0[12 ];/* 0x00f0 */
arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 289
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +10
-0+union { +__u64 tecmc;/* 0x00e8 */ +struct { +__u16 subchannel_id;/* 0x00e8 */ +__u16 subchannel_nr;/* 0x00ea */ +__u32 io_int_parm;/* 0x00ec */ +__u32 io_int_word;/* 0x00f0 */ + }; + } __packed; +__u8 reservedf4[8 ];/* 0x00f4 */
IIUC, for protected guests, you won't get an interception for which tecmc would be valid anymore, but need to put the I/O interruption stuff at the same place, right?
My main issue is that this makes the control block definition a bit ugly, since the f0 value that's unused in the non-protvirt case is not obvious anymore; but I don't know how to express this without making it even uglier :(
Quoted 3 lines
arch/s390/include/asm/kvm_host.h +0
-0#define CRYCB_FORMAT_MASK 0x00000003#define CRYCB_FORMAT0 0x00000000#define CRYCB_FORMAT1 0x00000001
Re: [RFC 13/37] KVM: s390: protvirt: Add interruption injection controls
Quoted 56 lines · Cornelia Huck
Quoted 53 lines · On Thu, 24 Oct 2019 07:40:35 -0400 Janosch Frank <[email protected]> wrote:
From: Michael Mueller <[email protected]>
Define the interruption injection codes and the related fields in the sie control block for PVM interruption injection.
Signed-off-by Michael Mueller <[email protected]>--- arch/s390/include/asm/kvm_host.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)arch/s390/include/asm/kvm_host.h +17
-4@@ -215,7 +215,15 @@ struct kvm_s390_sie_block {__u8 icptcode;/* 0x0050 */ __u8 icptstatus;/* 0x0051 */ __u16 ihcpu;/* 0x0052 */ -__u8 reserved54[2 ];/* 0x0054 */ +__u8 reserved54;/* 0x0054 */ +#define IICTL_CODE_NONE 0x00 +#define IICTL_CODE_MCHK 0x01 +#define IICTL_CODE_EXT 0x02 +#define IICTL_CODE_IO 0x03 +#define IICTL_CODE_RESTART 0x04 +#define IICTL_CODE_SPECIFICATION 0x10 +#define IICTL_CODE_OPERAND 0x11 +__u8 iictl;/* 0x0055 */ __u16 ipa;/* 0x0056 */ __u32 ipb;/* 0x0058 */ __u32 scaoh;/* 0x005c */ @@ -252,7 +260,8 @@ struct kvm_s390_sie_block {#define HPID_KVM 0x4#define HPID_VSIE 0x5__u8 hpid;/* 0x00b8 */ -__u8 reservedb9[11 ];/* 0x00b9 */ +__u8 reservedb9[7 ];/* 0x00b9 */ +__u32 eiparams;/* 0x00c0 */ __u16 extcpuaddr;/* 0x00c4 */ __u16 eic;/* 0x00c6 */ __u32 reservedc8;/* 0x00c8 */ @@ -268,8 +277,16 @@ struct kvm_s390_sie_block {__u8 oai;/* 0x00e2 */ __u8 armid;/* 0x00e3 */ __u8 reservede4[4 ];/* 0x00e4 */ -__u64 tecmc;/* 0x00e8 */ -__u8 reservedf0[12 ];/* 0x00f0 */ +union { +__u64 tecmc;/* 0x00e8 */ +struct { +__u16 subchannel_id;/* 0x00e8 */ +__u16 subchannel_nr;/* 0x00ea */ +__u32 io_int_parm;/* 0x00ec */
Quoted 8 lines
arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 289
Quoted 4 lines
arch/s390/include/asm/kvm_host.h +4
-0+__u32 io_int_word;/* 0x00f0 */ + }; + } __packed; +__u8 reservedf4[8 ];/* 0x00f4 */ IIUC, for protected guests, you won't get an interception for which tecmc would be valid anymore, but need to put the I/O interruption stuff at the same place, right?
Yes, the format 4 architecture defines this.
Quoted 5 lines
My main issue is that this makes the control block definition a bit ugly, since the f0 value that's unused in the non-protvirt case is not obvious anymore; but I don't know how to express this without making it even uglier :(
:)
Quoted 5 lines
arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 292
Quoted 4 lines
arch/s390/include/asm/kvm_host.h +0
-0#define CRYCB_FORMAT_MASK 0x00000003#define CRYCB_FORMAT0 0x00000000#define CRYCB_FORMAT1 0x00000001
Thanks
Michael
Re: [RFC 13/37] KVM: s390: protvirt: Add interruption injection controls
In reply to Janosch FrankQuoted 42 lines · Janosch Frank
From: Michael Mueller <[email protected]>
Define the interruption injection codes and the related fields in the sie control block for PVM interruption injection.
Signed-off-by Michael Mueller <[email protected]>--- arch/s390/include/asm/kvm_host.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)arch/s390/include/asm/kvm_host.h +11
-2@@ -215,7 +215,15 @@ struct kvm_s390_sie_block {__u8 icptcode;/* 0x0050 */ __u8 icptstatus;/* 0x0051 */ __u16 ihcpu;/* 0x0052 */ -__u8 reserved54[2 ];/* 0x0054 */ +__u8 reserved54;/* 0x0054 */ +#define IICTL_CODE_NONE 0x00 +#define IICTL_CODE_MCHK 0x01 +#define IICTL_CODE_EXT 0x02 +#define IICTL_CODE_IO 0x03 +#define IICTL_CODE_RESTART 0x04 +#define IICTL_CODE_SPECIFICATION 0x10 +#define IICTL_CODE_OPERAND 0x11 +__u8 iictl;/* 0x0055 */ __u16 ipa;/* 0x0056 */ __u32 ipb;/* 0x0058 */ __u32 scaoh;/* 0x005c */ @@ -252,7 +260,8 @@ struct kvm_s390_sie_block {#define HPID_KVM 0x4#define HPID_VSIE 0x5__u8 hpid;/* 0x00b8 */ -__u8 reservedb9[11 ];/* 0x00b9 */ +__u8 reservedb9[7 ];/* 0x00b9 */ +__u32 eiparams;/* 0x00c0 */ __u16 extcpuaddr;/* 0x00c4 */ __u16 eic;/* 0x00c6 */ __u32 reservedc8;/* 0x00c8 */
arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 281
Quoted 7 lines
arch/s390/include/asm/kvm_host.h +2
-2@@ -268,8 +277,16 @@ struct kvm_s390_sie_block {__u8 oai;/* 0x00e2 */ __u8 armid;/* 0x00e3 */ __u8 reservede4[4 ];/* 0x00e4 */ -__u64 tecmc;/* 0x00e8 */ -__u8 reservedf0[12 ];/* 0x00f0 */ +union { +__u64 tecmc;/* 0x00e8 */
I have to admit that I always have to think twice where the compiler might put the padding in this case. Maybe you could do that manually to make it obvious and wrap it in a struct, too:
struct {
__u64 tecmc; /* 0x00e8 */
__u8 reservedf0[4]; /* 0x00f0 */};
?
Just my 0.02 €, though.
Thomas
Quoted 12 lines
arch/s390/include/asm/kvm_host.h +8
-0+struct { +__u16 subchannel_id;/* 0x00e8 */ +__u16 subchannel_nr;/* 0x00ea */ +__u32 io_int_parm;/* 0x00ec */ +__u32 io_int_word;/* 0x00f0 */ + }; + } __packed; +__u8 reservedf4[8 ];/* 0x00f4 */ #define CRYCB_FORMAT_MASK 0x00000003#define CRYCB_FORMAT0 0x00000000#define CRYCB_FORMAT1 0x00000001
Janosch Frank
maintainerRFC 14/37 KVM: s390: protvirt: Implement interruption injection
In reply to Janosch FrankFrom: Michael Mueller <[email protected]>
The patch implements interruption injection for the following list of interruption types:
- I/O
__deliver_io (III)
- External
__deliver_cpu_timer (IEI)
__deliver_ckc (IEI)
__deliver_emergency_signal (IEI)
__deliver_external_call (IEI)
__deliver_service (IEI) - cpu restart
__deliver_restart (IRI)
--- arch/s390/include/asm/kvm_host.h | 10 ++ arch/s390/kvm/interrupt.c | 182 +++++++++++++++++++++++-------- 2 files changed, 149 insertions(+), 43 deletions(-)
arch/s390/include/asm/kvm_host.h +10 -0
@@ -496,6 +496,7 @@ enum irq_types {IRQ_PEND_PFAULT_INIT ,IRQ_PEND_EXT_HOST ,IRQ_PEND_EXT_SERVICE , +IRQ_PEND_EXT_SERVICE_EV ,IRQ_PEND_EXT_TIMING ,IRQ_PEND_EXT_CPU_TIMER , IRQ_PEND_EXT_CLOCK_COMP,
@@ -540,6 +541,7 @@ enum irq_types { (1UL <<IRQ_PEND_EXT_TIMING ) | \ (1UL <<IRQ_PEND_EXT_HOST ) | \ (1UL <<IRQ_PEND_EXT_SERVICE ) | \ + (1UL <<IRQ_PEND_EXT_SERVICE_EV ) | \ (1UL <<IRQ_PEND_VIRTIO ) | \ (1UL <<IRQ_PEND_PFAULT_INIT ) | \ (1UL << IRQ_PEND_PFAULT_DONE))
@@ -556,6 +558,13 @@ enum irq_types {#define IRQ_PEND_MCHK_MASK ((1UL << IRQ_PEND_MCHK_REP) | \ (1UL << IRQ_PEND_MCHK_EX)) +#define IRQ_PEND_EXT_II_MASK ((1UL << IRQ_PEND_EXT_CPU_TIMER) | \ + (1UL << IRQ_PEND_EXT_CLOCK_COMP) | \ + (1UL << IRQ_PEND_EXT_EMERGENCY) | \ + (1UL << IRQ_PEND_EXT_EXTERNAL) | \ + (1UL << IRQ_PEND_EXT_SERVICE) | \ + (1UL << IRQ_PEND_EXT_SERVICE_EV)) +struct kvm_s390_interrupt_info {struct list_head list;u64 type;
@@ -614,6 +623,7 @@ struct kvm_s390_local_interrupt {struct kvm_s390_float_interrupt {unsigned long pending_irqs; +unsigned long masked_irqs;spinlock_t lock;struct list_head lists[FIRQ_LIST_COUNT ];int counters[FIRQ_MAX_COUNT ];
arch/s390/kvm/interrupt.c +139 -43
319 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [RFC 14/37] KVM: s390: protvirt: Implement interruption injection
Quoted 9 lines · Janosch Frank
From: Michael Mueller <[email protected]>
The patch implements interruption injection for the following list of interruption types:
- I/O
__deliver_io (III)- External
Quoted 8 lines
__deliver_cpu_timer (IEI) __deliver_ckc (IEI) __deliver_emergency_signal (IEI) __deliver_external_call (IEI) __deliver_service (IEI)- cpu restart
__deliver_restart(IRI)
What exactly is IRQ_PEND_EXT_SERVICE_EV? Can you add some comments whet the new interrupt does and why it is needed in this context? Thanks
Quoted 393 lines
Signed-off-by Michael Mueller <[email protected]>--- arch/s390/include/asm/kvm_host.h | 10 ++ arch/s390/kvm/interrupt.c | 182 +++++++++++++++++++++++-------- 2 files changed, 149 insertions(+), 43 deletions(-)arch/s390/include/asm/kvm_host.h +10
-0@@ -496,6 +496,7 @@ enum irq_types {IRQ_PEND_PFAULT_INIT ,IRQ_PEND_EXT_HOST ,IRQ_PEND_EXT_SERVICE , +IRQ_PEND_EXT_SERVICE_EV ,IRQ_PEND_EXT_TIMING ,IRQ_PEND_EXT_CPU_TIMER , IRQ_PEND_EXT_CLOCK_COMP,@@ -540,6 +541,7 @@ enum irq_types { (1UL <<IRQ_PEND_EXT_TIMING ) | \ (1UL <<IRQ_PEND_EXT_HOST ) | \ (1UL <<IRQ_PEND_EXT_SERVICE ) | \ + (1UL <<IRQ_PEND_EXT_SERVICE_EV ) | \ (1UL <<IRQ_PEND_VIRTIO ) | \ (1UL <<IRQ_PEND_PFAULT_INIT ) | \ (1UL << IRQ_PEND_PFAULT_DONE))@@ -556,6 +558,13 @@ enum irq_types {#define IRQ_PEND_MCHK_MASK ((1UL << IRQ_PEND_MCHK_REP) | \ (1UL << IRQ_PEND_MCHK_EX)) +#define IRQ_PEND_EXT_II_MASK ((1UL << IRQ_PEND_EXT_CPU_TIMER) | \ + (1UL << IRQ_PEND_EXT_CLOCK_COMP) | \ + (1UL << IRQ_PEND_EXT_EMERGENCY) | \ + (1UL << IRQ_PEND_EXT_EXTERNAL) | \ + (1UL << IRQ_PEND_EXT_SERVICE) | \ + (1UL << IRQ_PEND_EXT_SERVICE_EV)) +struct kvm_s390_interrupt_info {struct list_head list;u64 type;@@ -614,6 +623,7 @@ struct kvm_s390_local_interrupt {struct kvm_s390_float_interrupt {unsigned long pending_irqs; +unsigned long masked_irqs;spinlock_t lock;struct list_head lists[FIRQ_LIST_COUNT ];int counters[FIRQ_MAX_COUNT ];arch/s390/kvm/interrupt.c +139
-43@@ -324,8 +324,10 @@ static inline int gisa_tac_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gisc)static inline unsigned long pending_irqs_no_gisa (struct kvm_vcpu *vcpu) { -return vcpu->kvm->arch.float_int.pending_irqs | - vcpu->arch.local_int.pending_irqs; +unsigned long pending = vcpu->kvm->arch.float_int.pending_irqs | vcpu->arch.local_int.pending_irqs; + + pending &= ~vcpu->kvm->arch.float_int.masked_irqs; +return pending; }static inline unsigned long pending_irqs (struct kvm_vcpu *vcpu)@@ -383,10 +385,16 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)__clear_bit (IRQ_PEND_EXT_CLOCK_COMP , &active_mask);if (!(vcpu->arch.sie_block->gcr[0 ] &CR0_CPU_TIMER_SUBMASK ))__clear_bit (IRQ_PEND_EXT_CPU_TIMER , &active_mask); -if (!(vcpu->arch.sie_block->gcr[0 ] &CR0_SERVICE_SIGNAL_SUBMASK )) +if (!(vcpu->arch.sie_block->gcr[0 ] &CR0_SERVICE_SIGNAL_SUBMASK )) {__clear_bit (IRQ_PEND_EXT_SERVICE , &active_mask); +__clear_bit (IRQ_PEND_EXT_SERVICE_EV , &active_mask); + }if (psw_mchk_disabled (vcpu)) active_mask &= ~IRQ_PEND_MCHK_MASK ; +/* PV guest cpus can have a single interruption injected at a time. */ +if (kvm_s390_pv_is_protected (vcpu->kvm) && + vcpu->arch.sie_block->iictl !=IICTL_CODE_NONE ) + active_mask &= ~(IRQ_PEND_EXT_II_MASK |IRQ_PEND_IO_MASK );/* * Check both floating and local interrupt's cr14 because * bit IRQ_PEND_MCHK_REP could be set in both cases. @@ -479,19 +487,23 @@ static void set_intercept_indicators(struct kvm_vcpu *vcpu)static int __must_check __deliver_cpu_timer (struct kvm_vcpu *vcpu) {struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; -int rc; +int rc =0 ; vcpu->stat.deliver_cputm++;trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_INT_CPU_TIMER ,0 ,0 ); - - rc =put_guest_lc (vcpu,EXT_IRQ_CPU_TIMER , - (u16 *)__LC_EXT_INT_CODE); - rc |=put_guest_lc (vcpu,0 , (u16 *)__LC_EXT_CPU_ADDR); - rc |=write_guest_lc (vcpu, __LC_EXT_OLD_PSW, - &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); - rc |=read_guest_lc (vcpu, __LC_EXT_NEW_PSW, - &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_EXT ; + vcpu->arch.sie_block->eic =EXT_IRQ_CPU_TIMER ; + }else { + rc =put_guest_lc (vcpu,EXT_IRQ_CPU_TIMER , + (u16 *)__LC_EXT_INT_CODE); + rc |=put_guest_lc (vcpu,0 , (u16 *)__LC_EXT_CPU_ADDR); + rc |=write_guest_lc (vcpu, __LC_EXT_OLD_PSW, + &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); + rc |=read_guest_lc (vcpu, __LC_EXT_NEW_PSW, + &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); + }clear_bit (IRQ_PEND_EXT_CPU_TIMER , &li->pending_irqs);return rc ? -EFAULT :0 ; }@@ -499,19 +511,23 @@ static int __must_check __deliver_cpu_timer(struct kvm_vcpu *vcpu)static int __must_check __deliver_ckc (struct kvm_vcpu *vcpu) {struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; -int rc; +int rc =0 ; vcpu->stat.deliver_ckc++;trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_INT_CLOCK_COMP ,0 ,0 ); - - rc =put_guest_lc (vcpu,EXT_IRQ_CLK_COMP , - (u16 __user *)__LC_EXT_INT_CODE); - rc |=put_guest_lc (vcpu,0 , (u16 *)__LC_EXT_CPU_ADDR); - rc |=write_guest_lc (vcpu, __LC_EXT_OLD_PSW, - &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); - rc |=read_guest_lc (vcpu, __LC_EXT_NEW_PSW, - &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_EXT ; + vcpu->arch.sie_block->eic =EXT_IRQ_CLK_COMP ; + }else { + rc =put_guest_lc (vcpu,EXT_IRQ_CLK_COMP , + (u16 __user *)__LC_EXT_INT_CODE); + rc |=put_guest_lc (vcpu,0 , (u16 *)__LC_EXT_CPU_ADDR); + rc |=write_guest_lc (vcpu, __LC_EXT_OLD_PSW, + &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); + rc |=read_guest_lc (vcpu, __LC_EXT_NEW_PSW, + &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); + }clear_bit (IRQ_PEND_EXT_CLOCK_COMP , &li->pending_irqs);return rc ? -EFAULT :0 ; }@@ -533,7 +549,6 @@ static int __must_check __deliver_pfault_init(struct kvm_vcpu *vcpu)trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_INT_PFAULT_INIT ,0 , ext.ext_params2); - rc =put_guest_lc (vcpu,EXT_IRQ_CP_SERVICE , (u16 *) __LC_EXT_INT_CODE); rc |=put_guest_lc (vcpu,PFAULT_INIT , (u16 *) __LC_EXT_CPU_ADDR); rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,@@ -696,17 +711,21 @@ static int __must_check __deliver_machine_check(struct kvm_vcpu *vcpu)static int __must_check __deliver_restart (struct kvm_vcpu *vcpu) {struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; -int rc; +int rc =0 ;VCPU_EVENT (vcpu,3 ,"%s" ,"deliver: cpu restart" ); vcpu->stat.deliver_restart_signal++;trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_RESTART ,0 ,0 ); - rc =write_guest_lc (vcpu, - offsetof(struct lowcore , restart_old_psw), - &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); - rc |=read_guest_lc (vcpu, offsetof(struct lowcore , restart_psw), - &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_RESTART ; + }else { + rc =write_guest_lc (vcpu, + offsetof(struct lowcore , restart_old_psw), + &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); + rc |=read_guest_lc (vcpu, offsetof(struct lowcore , restart_psw), + &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); + }clear_bit (IRQ_PEND_RESTART , &li->pending_irqs);return rc ? -EFAULT :0 ; }@@ -748,6 +767,12 @@ static int __must_check __deliver_emergency_signal(struct kvm_vcpu *vcpu) vcpu->stat.deliver_emergency_signal++;trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_INT_EMERGENCY , cpu_addr,0 ); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_EXT ; + vcpu->arch.sie_block->eic =EXT_IRQ_EMERGENCY_SIG ; + vcpu->arch.sie_block->extcpuaddr = cpu_addr; +return 0 ; + } rc =put_guest_lc (vcpu,EXT_IRQ_EMERGENCY_SIG , (u16 *)__LC_EXT_INT_CODE);@@ -776,6 +801,12 @@ static int __must_check __deliver_external_call(struct kvm_vcpu *vcpu)trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_INT_EXTERNAL_CALL , extcall.code,0 ); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_EXT ; + vcpu->arch.sie_block->eic =EXT_IRQ_EXTERNAL_CALL ; + vcpu->arch.sie_block->extcpuaddr = extcall.code; +return 0 ; + } rc =put_guest_lc (vcpu,EXT_IRQ_EXTERNAL_CALL , (u16 *)__LC_EXT_INT_CODE);@@ -902,6 +933,31 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)return rc ? -EFAULT :0 ; } +#define SCCB_MASK 0xFFFFFFF8 +#define SCCB_EVENT_PENDING 0x3 + +static int write_sclp (struct kvm_vcpu *vcpu,u32 parm) +{ +int rc; + +if (kvm_s390_pv_handle_cpu (vcpu)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_EXT ; + vcpu->arch.sie_block->eic =EXT_IRQ_SERVICE_SIG ; + vcpu->arch.sie_block->eiparams = parm; +return 0 ; + } + + rc =put_guest_lc (vcpu,EXT_IRQ_SERVICE_SIG , (u16 *)__LC_EXT_INT_CODE); + rc |=put_guest_lc (vcpu,0 , (u16 *)__LC_EXT_CPU_ADDR); + rc |=write_guest_lc (vcpu, __LC_EXT_OLD_PSW, + &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); + rc |=read_guest_lc (vcpu, __LC_EXT_NEW_PSW, + &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); + rc |=put_guest_lc (vcpu, parm, + (u32 *)__LC_EXT_PARAMS); +return rc; +} +static int __must_check __deliver_service (struct kvm_vcpu *vcpu) {struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;@@ -909,13 +965,17 @@ static int __must_check __deliver_service(struct kvm_vcpu *vcpu)int rc =0 ;spin_lock (&fi->lock); -if (!(test_bit (IRQ_PEND_EXT_SERVICE , &fi->pending_irqs))) { +if (test_bit (IRQ_PEND_EXT_SERVICE , &fi->masked_irqs) || + !(test_bit (IRQ_PEND_EXT_SERVICE , &fi->pending_irqs))) {spin_unlock (&fi->lock);return 0 ; } ext = fi->srv_signal;memset (&fi->srv_signal,0 ,sizeof (ext));clear_bit (IRQ_PEND_EXT_SERVICE , &fi->pending_irqs); +clear_bit (IRQ_PEND_EXT_SERVICE_EV , &fi->pending_irqs); +if (kvm_s390_pv_is_protected (vcpu->kvm)) +set_bit (IRQ_PEND_EXT_SERVICE , &fi->masked_irqs);spin_unlock (&fi->lock); VCPU_EVENT(vcpu, 4, "deliver: sclp parameter 0x%x",@@ -924,15 +984,33 @@ static int __must_check __deliver_service(struct kvm_vcpu *vcpu)trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_INT_SERVICE , ext.ext_params,0 ); - rc =put_guest_lc (vcpu,EXT_IRQ_SERVICE_SIG , (u16 *)__LC_EXT_INT_CODE); - rc |=put_guest_lc (vcpu,0 , (u16 *)__LC_EXT_CPU_ADDR); - rc |=write_guest_lc (vcpu, __LC_EXT_OLD_PSW, - &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); - rc |=read_guest_lc (vcpu, __LC_EXT_NEW_PSW, - &vcpu->arch.sie_block->gpsw,sizeof (psw_t)); - rc |=put_guest_lc (vcpu, ext.ext_params, - (u32 *)__LC_EXT_PARAMS); + rc =write_sclp (vcpu, ext.ext_params); +return rc ? -EFAULT :0 ; +} +static int __must_check __deliver_service_ev (struct kvm_vcpu *vcpu) +{ +struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; +struct kvm_s390_ext_info ext; +int rc =0 ; + +spin_lock (&fi->lock); +if (!(test_bit (IRQ_PEND_EXT_SERVICE_EV , &fi->pending_irqs))) { +spin_unlock (&fi->lock); +return 0 ; + } + ext = fi->srv_signal; +/* only clear the event bit */ + fi->srv_signal.ext_params &= ~SCCB_EVENT_PENDING ; +clear_bit (IRQ_PEND_EXT_SERVICE_EV , &fi->pending_irqs); +spin_unlock (&fi->lock); + +VCPU_EVENT (vcpu,4 ,"%s" ,"deliver: sclp parameter event" ); + vcpu->stat.deliver_service_signal++; +trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_INT_SERVICE , + ext.ext_params,0 ); + + rc =write_sclp (vcpu,SCCB_EVENT_PENDING );return rc ? -EFAULT :0 ; }@@ -1028,6 +1106,15 @@ static int __do_deliver_io(struct kvm_vcpu *vcpu, struct kvm_s390_io_info *io) {int rc; +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_IO ; + vcpu->arch.sie_block->subchannel_id = io->subchannel_id; + vcpu->arch.sie_block->subchannel_nr = io->subchannel_nr; + vcpu->arch.sie_block->io_int_parm = io->io_int_parm; + vcpu->arch.sie_block->io_int_word = io->io_int_word; +return 0 ; + } + rc =put_guest_lc (vcpu, io->subchannel_id, (u16 *)__LC_SUBCHANNEL_ID); rc |=put_guest_lc (vcpu, io->subchannel_nr, (u16 *)__LC_SUBCHANNEL_NR); rc |=put_guest_lc (vcpu, io->io_int_parm, (u32 *)__LC_IO_INT_PARM);@@ -1329,6 +1416,9 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)case IRQ_PEND_EXT_SERVICE : rc =__deliver_service (vcpu);break ; +case IRQ_PEND_EXT_SERVICE_EV : + rc =__deliver_service_ev (vcpu); +break ;case IRQ_PEND_PFAULT_DONE : rc =__deliver_pfault_done (vcpu);break ;@@ -1421,7 +1511,7 @@ static int __inject_extcall(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)if (kvm_get_vcpu_by_id (vcpu->kvm, src_id) ==NULL )return -EINVAL ; -if (sclp.has_sigpif) +if (sclp.has_sigpif && !kvm_s390_pv_handle_cpu (vcpu))return sca_inject_ext_call (vcpu, src_id);if (test_and_set_bit (IRQ_PEND_EXT_EXTERNAL , &li->pending_irqs))@@ -1681,9 +1771,6 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,return inti; } -#define SCCB_MASK 0xFFFFFFF8 -#define SCCB_EVENT_PENDING 0x3 -static int __inject_service (struct kvm *kvm,struct kvm_s390_interrupt_info *inti) {@@ -1692,6 +1779,11 @@ static int __inject_service(struct kvm *kvm, kvm->stat.inject_service_signal++;spin_lock (&fi->lock); fi->srv_signal.ext_params |= inti->ext.ext_params &SCCB_EVENT_PENDING ; + +/* We always allow events, track them separately from the sccb ints */ +if (fi->srv_signal.ext_params &SCCB_EVENT_PENDING ) +set_bit (IRQ_PEND_EXT_SERVICE_EV , &fi->pending_irqs); +/* * Early versions of the QEMU s390 bios will inject several * service interrupts after another without handling a @@ -1834,7 +1926,8 @@ static void __floating_irq_kick(struct kvm *kvm, u64 type)break ; case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:if (!(type &KVM_S390_INT_IO_AI_MASK && - kvm->arch.gisa_int.origin)) + kvm->arch.gisa_int.origin) || +kvm_s390_pv_handle_cpu (dst_vcpu))kvm_s390_set_cpuflags (dst_vcpu,CPUSTAT_IO_INT );break ;default :@@ -2082,6 +2175,8 @@ void kvm_s390_clear_float_irqs(struct kvm *kvm)spin_lock (&fi->lock); fi->pending_irqs =0 ; +if (!kvm_s390_pv_is_protected (kvm)) + fi->masked_irqs =0 ;memset (&fi->srv_signal,0 ,sizeof (fi->srv_signal));memset (&fi->mchk,0 ,sizeof (fi->mchk));for (i =0 ; i <FIRQ_LIST_COUNT ; i++)@@ -2146,7 +2241,8 @@ static int get_all_floating_irqs(struct kvm *kvm, u8 __user *usrbuf, u64 len) n++; } } -if (test_bit (IRQ_PEND_EXT_SERVICE , &fi->pending_irqs)) { +if (test_bit (IRQ_PEND_EXT_SERVICE , &fi->pending_irqs) || +test_bit (IRQ_PEND_EXT_SERVICE_EV , &fi->pending_irqs)) {if (n == max_irqs) {/* signal userspace to try again */ ret = -ENOMEM ;
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 14/37] KVM: s390: protvirt: Implement interruption injection
Quoted 16 lines · David Hildenbrand
Quoted 15 lines · Janosch Frank
From: Michael Mueller <[email protected]>
The patch implements interruption injection for the following list of interruption types:
- I/O
__deliver_io(III)- External
__deliver_cpu_timer(IEI)
__deliver_ckc(IEI)
__deliver_emergency_signal(IEI)
__deliver_external_call(IEI)
__deliver_service(IEI)
Quoted 4 lines
Quoted 2 lines
- cpu restart
__deliver_restart(IRI)What exactly is
IRQ_PEND_EXT_SERVICE_EV? Can you add some comments whet the new interrupt does and why it is needed in this context? Thanks
I did that code. What about the following add-on description.
The ultravisor does several checks on injected interrupts. For example it will check that for an sclp interrupt with an sccb address we had an servc exit and exit with a validity intercept.
As the hypervisor must avoid valitity intercepts we now mask invalid interrupts.
There are also sclp interrupts that only inject an event (e.g. an input event on the sclp consoles) those interrupts must not be masked.
Let us split out these "event interupts" from the normal sccb interrupts into IRQ_PEND_EXT_SERVICE_EV.
Re: [RFC 14/37] KVM: s390: protvirt: Implement interruption injection
Quoted 22 lines · Christian Borntraeger
Quoted 19 lines · David Hildenbrand
Quoted 17 lines · Janosch Frank
From: Michael Mueller <[email protected]>
The patch implements interruption injection for the following list of interruption types:
- I/O
__deliver_io(III)- External
__deliver_cpu_timer(IEI)
__deliver_ckc(IEI)
__deliver_emergency_signal(IEI)
__deliver_external_call(IEI)
__deliver_service(IEI)- cpu restart
__deliver_restart(IRI)
Quoted 8 lines
Quoted 1 line
What exactly is
IRQ_PEND_EXT_SERVICE_EV? Can you add some comments whet the new interrupt does and why it is needed in this context? ThanksI did that code. What about the following add-on description.
The ultravisor does several checks on injected interrupts. For example it will check that for an sclp interrupt with an sccb address we had an servc exit and exit with a validity intercept.
As the hypervisor must avoid valitity intercepts we now mask invalid interrupts.
s/valitity/validity/
Quoted 6 lines
There are also sclp interrupts that only inject an event (e.g. an input event on the sclp consoles) those interrupts must not be masked.
Let us split out these "event interupts" from the normal sccb interrupts intoIRQ_PEND_EXT_SERVICE_EV.
Thanks for the clarification. From what I see, this is transparent from user space - we only track these interrupts separately internally.
Signature · 3 lines
Thanks, David / dhildenb
Re: [RFC 14/37] KVM: s390: protvirt: Implement interruption injection
In reply to Janosch FrankQuoted 21 lines · Janosch Frank
From: Michael Mueller <[email protected]>
The patch implements interruption injection for the following list of interruption types:
- I/O
__deliver_io (III)- External
__deliver_cpu_timer (IEI) __deliver_ckc (IEI) __deliver_emergency_signal (IEI) __deliver_external_call (IEI) __deliver_service (IEI)- cpu restart
__deliver_restart(IRI)Signed-off-by Michael Mueller <[email protected]>---
[...]
arch/s390/kvm/interrupt.c static inline int gisa_tac_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gisc) · line 327
Quoted 11 lines
arch/s390/kvm/interrupt.c +1
-2@@ -324,8 +324,10 @@ static inline int gisa_tac_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gisc)static inline unsigned long pending_irqs_no_gisa (struct kvm_vcpu *vcpu) { -return vcpu->kvm->arch.float_int.pending_irqs | - vcpu->arch.local_int.pending_irqs; +unsigned long pending = vcpu->kvm->arch.float_int.pending_irqs | vcpu->arch.local_int.pending_irqs;
The line is now pretty long, way more than 80 columns ... maybe keep it on two lines?
Quoted 4 lines
arch/s390/kvm/interrupt.c +3
-0+ + pending &= ~vcpu->kvm->arch.float_int.masked_irqs; +return pending; }
[...]
arch/s390/kvm/interrupt.c static int __must_check __deliver_pfault_init(struct kvm_vcpu *vcpu) · line 554
Quoted 8 lines
arch/s390/kvm/interrupt.c +0
-1@@ -533,7 +549,6 @@ static int __must_check __deliver_pfault_init(struct kvm_vcpu *vcpu)trace_kvm_s390_deliver_interrupt (vcpu->vcpu_id,KVM_S390_INT_PFAULT_INIT ,0 , ext.ext_params2); - rc =put_guest_lc (vcpu,EXT_IRQ_CP_SERVICE , (u16 *) __LC_EXT_INT_CODE); rc |=put_guest_lc (vcpu,PFAULT_INIT , (u16 *) __LC_EXT_CPU_ADDR); rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
I think you can drop this hunk.
Thomas
Janosch Frank
maintainerRFC 15/37 KVM: s390: protvirt: Add machine-check interruption injection controls
In reply to Janosch FrankFrom: Michael Mueller <[email protected]>
The following fields are added to the sie control block type 4:
- Machine Check Interruption Code (mcic)
- External Damage Code (edc)
- Failing Storage Address (faddr)
--- arch/s390/include/asm/kvm_host.h | 33 +++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)
arch/s390/include/asm/kvm_host.h +24 -9
@@ -261,16 +261,31 @@ struct kvm_s390_sie_block {#define HPID_VSIE 0x5__u8 hpid;/* 0x00b8 */ __u8 reservedb9[7 ];/* 0x00b9 */ -__u32 eiparams;/* 0x00c0 */ -__u16 extcpuaddr;/* 0x00c4 */ -__u16 eic;/* 0x00c6 */ +union { +struct { +__u32 eiparams;/* 0x00c0 */ +__u16 extcpuaddr;/* 0x00c4 */ +__u16 eic;/* 0x00c6 */ + }; +__u64 mcic;/* 0x00c0 */ + } __packed;__u32 reservedc8;/* 0x00c8 */ -__u16 pgmilc;/* 0x00cc */ -__u16 iprcc;/* 0x00ce */ -__u32 dxc;/* 0x00d0 */ -__u16 mcn;/* 0x00d4 */ -__u8 perc;/* 0x00d6 */ -__u8 peratmid;/* 0x00d7 */ +union { +struct { +__u16 pgmilc;/* 0x00cc */ +__u16 iprcc;/* 0x00ce */ + }; +__u32 edc;/* 0x00cc */ + } __packed; +union { +struct { +__u32 dxc;/* 0x00d0 */ +__u16 mcn;/* 0x00d4 */ +__u8 perc;/* 0x00d6 */ +__u8 peratmid;/* 0x00d7 */ + }; +__u64 faddr;/* 0x00d0 */ + } __packed;__u64 peraddr;/* 0x00d8 */ __u8 eai;/* 0x00e0 */ __u8 peraid;/* 0x00e1 */
Signature · 1 line
2.20.1
Re: [RFC 15/37] KVM: s390: protvirt: Add machine-check interruption injection controls
Quoted 44 lines · Janosch Frank
From: Michael Mueller <[email protected]>
The following fields are added to the sie control block type 4:
- Machine Check Interruption Code (mcic)
- External Damage Code (edc)
- Failing Storage Address (faddr)Signed-off-by Michael Mueller <[email protected]>--- arch/s390/include/asm/kvm_host.h | 33 +++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)arch/s390/include/asm/kvm_host.h +14
-9@@ -261,16 +261,31 @@ struct kvm_s390_sie_block {#define HPID_VSIE 0x5__u8 hpid;/* 0x00b8 */ __u8 reservedb9[7 ];/* 0x00b9 */ -__u32 eiparams;/* 0x00c0 */ -__u16 extcpuaddr;/* 0x00c4 */ -__u16 eic;/* 0x00c6 */ +union { +struct { +__u32 eiparams;/* 0x00c0 */ +__u16 extcpuaddr;/* 0x00c4 */ +__u16 eic;/* 0x00c6 */ + }; +__u64 mcic;/* 0x00c0 */ + } __packed;__u32 reservedc8;/* 0x00c8 */ -__u16 pgmilc;/* 0x00cc */ -__u16 iprcc;/* 0x00ce */ -__u32 dxc;/* 0x00d0 */ -__u16 mcn;/* 0x00d4 */ -__u8 perc;/* 0x00d6 */ -__u8 peratmid;/* 0x00d7 */ +union { +struct { +__u16 pgmilc;/* 0x00cc */ +__u16 iprcc;/* 0x00ce */ + }; +__u32 edc;/* 0x00cc */
arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 288
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +10
-0+ } __packed; +union { +struct { +__u32 dxc;/* 0x00d0 */ +__u16 mcn;/* 0x00d4 */ +__u8 perc;/* 0x00d6 */ +__u8 peratmid;/* 0x00d7 */ + }; +__u64 faddr;/* 0x00d0 */ + } __packed;
Maybe drop the __packed keywords since the struct members are naturally aligned anyway?
Thomas
Re: [RFC 15/37] KVM: s390: protvirt: Add machine-check interruption injection controls
Quoted 59 lines · Thomas Huth
Quoted 44 lines · Janosch Frank
From: Michael Mueller <[email protected]>
The following fields are added to the sie control block type 4:
- Machine Check Interruption Code (mcic)
- External Damage Code (edc)
- Failing Storage Address (faddr)Signed-off-by Michael Mueller <[email protected]>--- arch/s390/include/asm/kvm_host.h | 33 +++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)arch/s390/include/asm/kvm_host.h +14
-9@@ -261,16 +261,31 @@ struct kvm_s390_sie_block {#define HPID_VSIE 0x5__u8 hpid;/* 0x00b8 */ __u8 reservedb9[7 ];/* 0x00b9 */ -__u32 eiparams;/* 0x00c0 */ -__u16 extcpuaddr;/* 0x00c4 */ -__u16 eic;/* 0x00c6 */ +union { +struct { +__u32 eiparams;/* 0x00c0 */ +__u16 extcpuaddr;/* 0x00c4 */ +__u16 eic;/* 0x00c6 */ + }; +__u64 mcic;/* 0x00c0 */ + } __packed;__u32 reservedc8;/* 0x00c8 */ -__u16 pgmilc;/* 0x00cc */ -__u16 iprcc;/* 0x00ce */ -__u32 dxc;/* 0x00d0 */ -__u16 mcn;/* 0x00d4 */ -__u8 perc;/* 0x00d6 */ -__u8 peratmid;/* 0x00d7 */ +union { +struct { +__u16 pgmilc;/* 0x00cc */ +__u16 iprcc;/* 0x00ce */ + }; +__u32 edc;/* 0x00cc */ arch/s390/include/asm/kvm_host.h struct kvm_s390_sie_block { · line 288
Quoted 10 lines
arch/s390/include/asm/kvm_host.h +10
-0+ } __packed; +union { +struct { +__u32 dxc;/* 0x00d0 */ +__u16 mcn;/* 0x00d4 */ +__u8 perc;/* 0x00d6 */ +__u8 peratmid;/* 0x00d7 */ + }; +__u64 faddr;/* 0x00d0 */ + } __packed;Maybe drop the
__packedkeywords since the struct members are naturally aligned anyway?
Quoted 2 lines
Thomas
Thanks, I will give it a try.
Michael
Janosch Frank
maintainerRFC 16/37 KVM: s390: protvirt: Implement machine-check interruption injection
In reply to Janosch FrankFrom: Michael Mueller <[email protected]>
Similar to external interrupts, the hypervisor can inject machine checks by providing the right data in the interrupt injection controls.
--- arch/s390/kvm/interrupt.c | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/s390/kvm/interrupt.c +8 -0
@@ -568,6 +568,14 @@ static int __write_machine_check(struct kvm_vcpu *vcpu,union mci mci;int rc; +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_MCHK ; + vcpu->arch.sie_block->mcic = mchk->mcic; + vcpu->arch.sie_block->faddr = mchk->failing_storage_address; + vcpu->arch.sie_block->edc = mchk->ext_damage_code; +return 0 ; + } + mci.val = mchk->mcic;/* take care of lazy register loading */ save_fpu_regs ();
Signature · 1 line
2.20.1
Re: [RFC 16/37] KVM: s390: protvirt: Implement machine-check interruption injection
Quoted 16 lines · On Thu, 24 Oct 2019 07:40:38 -0400 Janosch Frank <[email protected]> wrote:
From: Michael Mueller <[email protected]>
Similar to external interrupts, the hypervisor can inject machine checks by providing the right data in the interrupt injection controls.
Signed-off-by Michael Mueller <[email protected]>--- arch/s390/kvm/interrupt.c | 8 ++++++++ 1 file changed, 8 insertions(+)arch/s390/kvm/interrupt.c +0
-0@@ -568,6 +568,14 @@ static int __write_machine_check(struct kvm_vcpu *vcpu,union mci mci;
arch/s390/kvm/interrupt.c static int __write_machine_check(struct kvm_vcpu *vcpu, · line 578
Quoted 10 lines
arch/s390/kvm/interrupt.c +8
-0int rc; +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + vcpu->arch.sie_block->iictl =IICTL_CODE_MCHK ; + vcpu->arch.sie_block->mcic = mchk->mcic; + vcpu->arch.sie_block->faddr = mchk->failing_storage_address; + vcpu->arch.sie_block->edc = mchk->ext_damage_code; +return 0 ; + } +
The other stuff this function injects in the !pv case is inaccessible to the hypervisor in the pv case, right? (Registers, extended save area, ...) Maybe add a comment?
Quoted 3 lines
arch/s390/kvm/interrupt.c +0
-0mci.val = mchk->mcic;/* take care of lazy register loading */ save_fpu_regs ();
Janosch Frank
maintainerRFC 17/37 DOCUMENTATION: protvirt: Instruction emulation
In reply to Janosch FrankAs guest memory is inaccessible and information about the guest's state is very limited, new ways for instruction emulation have been introduced.
With a bounce area for guest GRs and instruction data, guest state leaks can be limited by the Ultravisor. KVM now has to move instruction input and output through these areas.
--- Documentation/virtual/kvm/s390-pv.txt | 47 +++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
Documentation/virtual/kvm/s390-pv.txt +47 -0
@@ -48,3 +48,50 @@ interception codes have been introduced. One which tells us that CRs have changed. And one for PSW bit 13 changes. The CRs and the PSW in the state description only contain the mask bits and no further info like the current instruction address. + + +Instruction emulation: +With the format 4 state description the SIE instruction already +interprets more instructions than it does with format 2. As it is not +able to interpret all instruction, the SIE and the UV safeguard KVM's +emulation inputs and outputs. + +Guest GRs and most of the instruction data, like IO data structures +are filtered. Instruction data is copied to and from the Secure +Instruction Data Area. Guest GRs are put into / retrieved from the +Interception-Data block. + +The Interception-Data block from the state description's offset 0x380 +contains GRs 0 - 16. Only GR values needed to emulate an instruction +will be copied into this area. + +The Interception Parameters state description field still contains the +the bytes of the instruction text but with pre-set register +values. I.e. each instruction always uses the same instruction text, +to not leak guest instruction text. + +The Secure Instruction Data Area contains instruction storage +data. Data for diag 500 is exempt from that and has to be moved +through shared buffers to KVM. + +When SIE intercepts an instruction, it will only allow data and +program interrupts for this instruction to be moved to the guest via +the two data areas discussed before. Other data is ignored or results +in validity interceptions. + + +Instruction emulation interceptions: +There are two types of SIE secure instruction intercepts. The normal +and the notification type. Normal secure instruction intercepts will +make the guest pending for instruction completion of the intercepted +instruction type, i.e. on SIE entry it is attempted to complete +emulation of the instruction with the data provided by KVM. That might +be a program exception or instruction completion. + +The notification type intercepts inform KVM about guest environment +changes due to guest instruction interpretation. Such an interception +is recognized for the store prefix instruction and provides the new +lowcore location for mapping change notification arming. Any KVM data +in the data areas is ignored, program exceptions are not injected and +execution continues on next SIE entry, as if no intercept had +happened.
Signature · 1 line
2.20.1
Re: [RFC 17/37] DOCUMENTATION: protvirt: Instruction emulation
Quoted 18 lines · On Thu, 24 Oct 2019 07:40:39 -0400 Janosch Frank <[email protected]> wrote:
As guest memory is inaccessible and information about the guest's state is very limited, new ways for instruction emulation have been introduced.
With a bounce area for guest GRs and instruction data, guest state leaks can be limited by the Ultravisor. KVM now has to move instruction input and output through these areas.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 47 +++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)Documentation/virtual/kvm/s390-pv.txt +0
-0
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 54
Quoted 7 lines
Documentation/virtual/kvm/s390-pv.txt +4
-0@@ -48,3 +48,50 @@ interception codes have been introduced. One which tells us that CRs have changed. And one for PSW bit 13 changes. The CRs and the PSW in the state description only contain the mask bits and no further info like the current instruction address. + + +Instruction emulation: +With the format 4 state description the SIE instruction already
s/description/description,/
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 56
Quoted 2 lines
Documentation/virtual/kvm/s390-pv.txt +2
-0+interprets more instructions than it does with format 2. As it is not +able to interpret all instruction, the SIE and the UV safeguard KVM's
s/instruction/instructions/
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 59
Quoted 3 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+emulation inputs and outputs. + +Guest GRs and most of the instruction data, like IO data structures
Hm, what 'IO data structures'?
Quoted 6 lines
Documentation/virtual/kvm/s390-pv.txt +6
-0+are filtered. Instruction data is copied to and from the Secure +Instruction Data Area. Guest GRs are put into / retrieved from the +Interception-Data block. + +The Interception-Data block from the state description's offset 0x380 +contains GRs 0 - 16. Only GR values needed to emulate an instruction
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 75
Quoted 10 lines
Documentation/virtual/kvm/s390-pv.txt +10
-0+will be copied into this area. + +The Interception Parameters state description field still contains the +the bytes of the instruction text but with pre-set register +values. I.e. each instruction always uses the same instruction text, +to not leak guest instruction text. + +The Secure Instruction Data Area contains instruction storage +data. Data for diag 500 is exempt from that and has to be moved +through shared buffers to KVM.
I find this paragraph a bit confusing. What does that imply for diag 500 interception? Data is still present in gprs 1-4?
(Also, why only diag 500? Because it is the 'reserved for kvm' diagnose call?)
Quoted 7 lines
Documentation/virtual/kvm/s390-pv.txt +7
-0+ +When SIE intercepts an instruction, it will only allow data and +program interrupts for this instruction to be moved to the guest via +the two data areas discussed before. Other data is ignored or results +in validity interceptions. + +
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 92
Quoted 10 lines
Documentation/virtual/kvm/s390-pv.txt +10
-0+Instruction emulation interceptions: +There are two types of SIE secure instruction intercepts. The normal +and the notification type. Normal secure instruction intercepts will +make the guest pending for instruction completion of the intercepted +instruction type, i.e. on SIE entry it is attempted to complete +emulation of the instruction with the data provided by KVM. That might +be a program exception or instruction completion. + +The notification type intercepts inform KVM about guest environment +changes due to guest instruction interpretation. Such an interception
'interpretation by SIE' ?
Quoted 5 lines
Documentation/virtual/kvm/s390-pv.txt +5
-0+is recognized for the store prefix instruction and provides the new +lowcore location for mapping change notification arming. Any KVM data +in the data areas is ignored, program exceptions are not injected and +execution continues on next SIE entry, as if no intercept had +happened.
Claudio Imbrenda
maintainerRe: [RFC 17/37] DOCUMENTATION: protvirt: Instruction emulation
Quoted 35 lines · On Thu, 14 Nov 2019 16:15:26 +0100 Cornelia Huck <[email protected]> wrote:
Quoted 22 lines · On Thu, 24 Oct 2019 07:40:39 -0400 Janosch Frank <[email protected]> wrote:
As guest memory is inaccessible and information about the guest's state is very limited, new ways for instruction emulation have been introduced.
With a bounce area for guest GRs and instruction data, guest state leaks can be limited by the Ultravisor. KVM now has to move instruction input and output through these areas.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 47+++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
(quoted diff) +0
-0
b/Documentation/virtual/kvm/s390-pv.txtindexe09f2dc5f164..cb08d78a7922100644 ---a/Documentation/virtual/kvm/s390-pv.txt+++b/Documentation/virtual/kvm/s390-pv.txt@@ -48,3 +48,50 @@ interception codes have been introduced. One which tells us that CRs have changed. And one for PSW bit 13 changes. The CRs and the PSW in the state description only contain the mask bits and no further info like the current instruction address. +Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 54
Quoted 3 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+ +Instruction emulation: +With the format 4 state description the SIE instruction alreadys/description/description,/
Quoted 3 lines
+interprets more instructions than it does with format 2. As it is not +able to interpret all instruction, the SIE and the UV safeguard KVM's
Quoted 8 lines
s/instruction/instructions/
Quoted 4 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+emulation inputs and outputs. + +Guest GRs and most of the instruction data, like IO datastructures
Hm, what 'IO data structures'?
the various IRB and ORB of I/O instructions
Quoted 11 lines
Quoted 11 lines
Documentation/virtual/kvm/s390-pv.txt +5
-0+are filtered. Instruction data is copied to and from the Secure +Instruction Data Area. Guest GRs are put into / retrieved from the +Interception-Data block. + +The Interception-Data block from the state description's offset
0x380+contains GRs 0 - 16. Only GR values needed to emulate an instruction +will be copied into this area.(quoted diff) +2
-0+ +The Interception Parameters state description field still containsthe +the bytes of the instruction text but with pre-set register +values. I.e. each instruction always uses the same instruction
Quoted 8 lines
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 75
Quoted 5 lines
text, +to not leak guest instruction text.
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +The Secure Instruction Data Area contains instruction storage +data. Data for diag 500 is exempt from that and has to be moved +through shared buffers to KVM.I find this paragraph a bit confusing. What does that imply for diag 500 interception? Data is still present in gprs 1-4?
no registers are leaked in the registers. registers are always only exposed through the state description.
Quoted 30 lines
(Also, why only diag 500? Because it is the 'reserved for kvm' diagnose call?)
Quoted 17 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+ +When SIE intercepts an instruction, it will only allow data and +program interrupts for this instruction to be moved to the guestvia +the two data areas discussed before. Other data is ignored or results +in validity interceptions.
Documentation/virtual/kvm/s390-pv.txt +4
-0+ + +Instruction emulation interceptions: +There are two types of SIE secure instruction intercepts. Thenormal +and the notification type. Normal secure instruction intercepts will +make the guest pending for instruction completion of the intercepted +instruction type, i.e. on SIE entry it is attempted to complete +emulation of the instruction with the data provided by KVM. That might +be a program exception or instruction completion. +
(quoted diff) +2
-0+The notification type intercepts inform KVM about guest environment +changes due to guest instruction interpretation. Such anQuoted 1 line
interception
'interpretation by SIE' ?
Quoted 5 lines
(quoted diff) +2
-0+is recognized for the store prefix instruction and provides the new +lowcore location for mapping change notification arming. Any KVMdata +in the data areas is ignored, program exceptions are not injected and +execution continues on next SIE entry, as if no intercept had +happened.
Re: [RFC 17/37] DOCUMENTATION: protvirt: Instruction emulation
Quoted 40 lines · On Thu, 14 Nov 2019 16:20:24 +0100 Claudio Imbrenda <[email protected]>…
Quoted 37 lines · On Thu, 14 Nov 2019 16:15:26 +0100 Cornelia Huck <[email protected]> wrote:
Quoted 22 lines · On Thu, 24 Oct 2019 07:40:39 -0400 Janosch Frank <[email protected]> wrote:
As guest memory is inaccessible and information about the guest's state is very limited, new ways for instruction emulation have been introduced.
With a bounce area for guest GRs and instruction data, guest state leaks can be limited by the Ultravisor. KVM now has to move instruction input and output through these areas.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 47+++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
(quoted diff) +0
-0
b/Documentation/virtual/kvm/s390-pv.txtindexe09f2dc5f164..cb08d78a7922100644 ---a/Documentation/virtual/kvm/s390-pv.txt+++b/Documentation/virtual/kvm/s390-pv.txt@@ -48,3 +48,50 @@ interception codes have been introduced. One which tells us that CRs have changed. And one for PSW bit 13 changes. The CRs and the PSW in the state description only contain the mask bits and no further info like the current instruction address. +Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 54
Quoted 3 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+ +Instruction emulation: +With the format 4 state description the SIE instruction alreadys/description/description,/
Quoted 3 lines
+interprets more instructions than it does with format 2. As it is not +able to interpret all instruction, the SIE and the UV safeguard KVM's
s/instruction/instructions/
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+emulation inputs and outputs. + +Guest GRs and most of the instruction data, like IO datastructures
Hm, what 'IO data structures'?
the various IRB and ORB of I/O instructions
Would be good to mention them as examples :)
Quoted 21 lines
Quoted 12 lines
Quoted 12 lines
Documentation/virtual/kvm/s390-pv.txt +5
-0+are filtered. Instruction data is copied to and from the Secure +Instruction Data Area. Guest GRs are put into / retrieved from the +Interception-Data block. + +The Interception-Data block from the state description's offset
0x380+contains GRs 0 - 16. Only GR values needed to emulate an instruction +will be copied into this area.(quoted diff) +2
-0+ +The Interception Parameters state description field still containsthe +the bytes of the instruction text but with pre-set register +values. I.e. each instruction always uses the same instruction
Quoted 8 lines
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 75
Quoted 5 lines
text, +to not leak guest instruction text.
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +The Secure Instruction Data Area contains instruction storage +data. Data for diag 500 is exempt from that and has to be moved +through shared buffers to KVM.I find this paragraph a bit confusing. What does that imply for diag 500 interception? Data is still present in gprs 1-4?
Quoted 2 lines
no registers are leaked in the registers. registers are always only exposed through the state description.
So, what is so special about diag 500, then?
Quoted 32 lines
Quoted 31 lines
(Also, why only diag 500? Because it is the 'reserved for kvm' diagnose call?)
Quoted 17 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+ +When SIE intercepts an instruction, it will only allow data and +program interrupts for this instruction to be moved to the guestvia +the two data areas discussed before. Other data is ignored or results +in validity interceptions.
Documentation/virtual/kvm/s390-pv.txt +4
-0+ + +Instruction emulation interceptions: +There are two types of SIE secure instruction intercepts. Thenormal +and the notification type. Normal secure instruction intercepts will +make the guest pending for instruction completion of the intercepted +instruction type, i.e. on SIE entry it is attempted to complete +emulation of the instruction with the data provided by KVM. That might +be a program exception or instruction completion. +
(quoted diff) +2
-0+The notification type intercepts inform KVM about guest environment +changes due to guest instruction interpretation. Such anQuoted 1 line
interception
'interpretation by SIE' ?
Quoted 5 lines
(quoted diff) +2
-0+is recognized for the store prefix instruction and provides the new +lowcore location for mapping change notification arming. Any KVMdata +in the data areas is ignored, program exceptions are not injected and +execution continues on next SIE entry, as if no intercept had +happened.
Janosch Frank
maintainerRe: [RFC 17/37] DOCUMENTATION: protvirt: Instruction emulation
Quoted 75 lines · Cornelia Huck
Quoted 40 lines · On Thu, 14 Nov 2019 16:20:24 +0100 Claudio Imbrenda <[email protected]>…
Quoted 37 lines · On Thu, 14 Nov 2019 16:15:26 +0100 Cornelia Huck <[email protected]> wrote:
Quoted 22 lines · On Thu, 24 Oct 2019 07:40:39 -0400 Janosch Frank <[email protected]> wrote:
As guest memory is inaccessible and information about the guest's state is very limited, new ways for instruction emulation have been introduced.
With a bounce area for guest GRs and instruction data, guest state leaks can be limited by the Ultravisor. KVM now has to move instruction input and output through these areas.
Signed-off-by Janosch Frank <[email protected]>--- Documentation/virtual/kvm/s390-pv.txt | 47+++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
(quoted diff) +0
-0
b/Documentation/virtual/kvm/s390-pv.txtindexe09f2dc5f164..cb08d78a7922100644 ---a/Documentation/virtual/kvm/s390-pv.txt+++b/Documentation/virtual/kvm/s390-pv.txt@@ -48,3 +48,50 @@ interception codes have been introduced. One which tells us that CRs have changed. And one for PSW bit 13 changes. The CRs and the PSW in the state description only contain the mask bits and no further info like the current instruction address. +Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 54
Quoted 3 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+ +Instruction emulation: +With the format 4 state description the SIE instruction alreadys/description/description,/
Quoted 3 lines
+interprets more instructions than it does with format 2. As it is not +able to interpret all instruction, the SIE and the UV safeguard KVM's
s/instruction/instructions/
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+emulation inputs and outputs. + +Guest GRs and most of the instruction data, like IO datastructures
Hm, what 'IO data structures'?
the various IRB and ORB of I/O instructions
Would be good to mention them as examples :)
Quoted 21 lines
Quoted 20 lines
Quoted 13 lines
Documentation/virtual/kvm/s390-pv.txt +5
-0+are filtered. Instruction data is copied to and from the Secure +Instruction Data Area. Guest GRs are put into / retrieved from the +Interception-Data block. + +The Interception-Data block from the state description's offset
0x380+contains GRs 0 - 16. Only GR values needed to emulate an instruction +will be copied into this area.(quoted diff) +2
-0+ +The Interception Parameters state description field still containsthe +the bytes of the instruction text but with pre-set register +values. I.e. each instruction always uses the same instruction text, +to not leak guest instruction text.
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 75
Quoted 4 lines
Documentation/virtual/kvm/s390-pv.txt +4
-0+ +The Secure Instruction Data Area contains instruction storage +data. Data for diag 500 is exempt from that and has to be moved +through shared buffers to KVM.I find this paragraph a bit confusing. What does that imply for diag 500 interception? Data is still present in gprs 1-4?
Quoted 4 lines
Quoted 2 lines
no registers are leaked in the registers. registers are always only exposed through the state description.
So, what is so special about diag 500, then?
That's mostly a confusion on my side.
The SIDAD is 4k max, so we can only move IO "management" data over it like ORBs and stuff. My intention was to point out, that the data which is to be transferred (disk contents, etc.) can't go over the SIDAD but needs to be in a shared page.
diag500 was mostly a notification mechanism without a lot of data, right?
Quoted 34 lines
Quoted 33 lines
Quoted 32 lines
(Also, why only diag 500? Because it is the 'reserved for kvm' diagnose call?)
Quoted 17 lines
Documentation/virtual/kvm/s390-pv.txt +3
-0+ +When SIE intercepts an instruction, it will only allow data and +program interrupts for this instruction to be moved to the guestvia +the two data areas discussed before. Other data is ignored or results +in validity interceptions.
Documentation/virtual/kvm/s390-pv.txt +4
-0+ + +Instruction emulation interceptions: +There are two types of SIE secure instruction intercepts. Thenormal +and the notification type. Normal secure instruction intercepts will +make the guest pending for instruction completion of the intercepted +instruction type, i.e. on SIE entry it is attempted to complete +emulation of the instruction with the data provided by KVM. That might +be a program exception or instruction completion. +
(quoted diff) +2
-0+The notification type intercepts inform KVM about guest environment +changes due to guest instruction interpretation. Such anQuoted 1 line
interception
'interpretation by SIE' ?
Quoted 5 lines
(quoted diff) +2
-0+is recognized for the store prefix instruction and provides the new +lowcore location for mapping change notification arming. Any KVMdata +in the data areas is ignored, program exceptions are not injected and +execution continues on next SIE entry, as if no intercept had +happened.
Re: [RFC 17/37] DOCUMENTATION: protvirt: Instruction emulation
Quoted 22 lines · On Thu, 14 Nov 2019 16:55:46 +0100 Janosch Frank <[email protected]> wrote:
Quoted 16 lines · Cornelia Huck
Quoted 13 lines · On Thu, 14 Nov 2019 16:20:24 +0100 Claudio Imbrenda <[email protected]>…
Quoted 9 lines · On Thu, 14 Nov 2019 16:15:26 +0100 Cornelia Huck <[email protected]> wrote:
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 75
Quoted 3 lines · On Thu, 24 Oct 2019 07:40:39 -0400 Janosch Frank <[email protected]> wrote:
Documentation/virtual/kvm/s390-pv.txt +3
-0+The Secure Instruction Data Area contains instruction storage +data. Data for diag 500 is exempt from that and has to be moved +through shared buffers to KVM.I find this paragraph a bit confusing. What does that imply for diag 500 interception? Data is still present in gprs 1-4?
Quoted 4 lines
Quoted 2 lines
no registers are leaked in the registers. registers are always only exposed through the state description.
So, what is so special about diag 500, then?
Quoted 7 lines
That's mostly a confusion on my side.
The SIDAD is 4k max, so we can only move IO "management" data over it like ORBs and stuff. My intention was to point out, that the data which is to be transferred (disk contents, etc.) can't go over the SIDAD but needs to be in a shared page.diag500 was mostly a notification mechanism without a lot of data, right?
Yes; the main information in there are the schid identifying the subchannel, the virtqueue number, and a cookie value, all of which fit into the registers.
So this goes via the sidad as well?
Janosch Frank
maintainerRe: [RFC 17/37] DOCUMENTATION: protvirt: Instruction emulation
Quoted 31 lines · Cornelia Huck
Quoted 28 lines · On Thu, 14 Nov 2019 16:55:46 +0100 Janosch Frank <[email protected]> wrote:
Quoted 16 lines · Cornelia Huck
Quoted 13 lines · On Thu, 14 Nov 2019 16:20:24 +0100 Claudio Imbrenda <[email protected]>…
Quoted 9 lines · On Thu, 14 Nov 2019 16:15:26 +0100 Cornelia Huck <[email protected]> wrote:
Documentation/virtual/kvm/s390-pv.txt interception codes have been introduced. One which tells us that CRs · line 75
Quoted 3 lines · On Thu, 24 Oct 2019 07:40:39 -0400 Janosch Frank <[email protected]> wrote:
Documentation/virtual/kvm/s390-pv.txt +3
-0+The Secure Instruction Data Area contains instruction storage +data. Data for diag 500 is exempt from that and has to be moved +through shared buffers to KVM.I find this paragraph a bit confusing. What does that imply for diag 500 interception? Data is still present in gprs 1-4?
Quoted 4 lines
Quoted 2 lines
no registers are leaked in the registers. registers are always only exposed through the state description.
So, what is so special about diag 500, then?
That's mostly a confusion on my side.
The SIDAD is 4k max, so we can only move IO "management" data over it like ORBs and stuff. My intention was to point out, that the data which is to be transferred (disk contents, etc.) can't go over the SIDAD but needs to be in a shared page.
Quoted 8 lines
Quoted 1 line
diag500 was mostly a notification mechanism without a lot of data, right?
Yes; the main information in there are the schid identifying the subchannel, the virtqueue number, and a cookie value, all of which fit into the registers.
So this goes via the sidad as well?
Only referenced data goes over the SIDA, register values go into offset 0x380 of the SIE state description.
If an instruction has an address in a register, we will receive a bogus address and the referenced data in the SIDA.
SCLP has a code and an address as register values. We will get the code and a bogus address in the register area. The SCCB will be in the SIDA.
Janosch Frank
maintainerRFC 18/37 KVM: s390: protvirt: Handle spec exception loops
In reply to Janosch FrankSIE intercept code 8 is used only on exception loops for protected guests. That means we need stop the guest when we see it.
--- arch/s390/kvm/intercept.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/s390/kvm/intercept.c +7 -0
@@ -231,6 +231,13 @@ static int handle_prog(struct kvm_vcpu *vcpu) vcpu->stat.exit_program_interruption++; +/* +* Intercept 8 indicates a loop of specification exceptions +* for protected guests +*/ +if (kvm_s390_pv_is_protected (vcpu->kvm)) +return -EOPNOTSUPP ; +if (guestdbg_enabled (vcpu) &&per_event (vcpu)) { rc =kvm_s390_handle_per_event (vcpu);if (rc)
Signature · 1 line
2.20.1
Re: [RFC 18/37] KVM: s390: protvirt: Handle spec exception loops
Quoted 16 lines · Janosch Frank
SIE intercept code 8 is used only on exception loops for protected guests. That means we need stop the guest when we see it.
Signed-off-by Janosch Frank <[email protected]>--- arch/s390/kvm/intercept.c | 7 +++++++ 1 file changed, 7 insertions(+)arch/s390/kvm/intercept.c +0
-0@@ -231,6 +231,13 @@ static int handle_prog(struct kvm_vcpu *vcpu) vcpu->stat.exit_program_interruption++;
arch/s390/kvm/intercept.c static int handle_prog(struct kvm_vcpu *vcpu) · line 243
Quoted 10 lines
arch/s390/kvm/intercept.c +7
-0+/* +* Intercept 8 indicates a loop of specification exceptions +* for protected guests +*/ +if (kvm_s390_pv_is_protected (vcpu->kvm)) +return -EOPNOTSUPP ; +if (guestdbg_enabled (vcpu) &&per_event (vcpu)) { rc =kvm_s390_handle_per_event (vcpu);if (rc)
Janosch Frank
maintainerRFC 19/37 KVM: s390: protvirt: Add new gprs location handling
In reply to Janosch FrankGuest registers for protected guests are stored at offset 0x380.
--- arch/s390/include/asm/kvm_host.h | 4 +++- arch/s390/kvm/kvm-s390.c | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-)
arch/s390/include/asm/kvm_host.h +3 -1
@@ -336,7 +336,9 @@ struct kvm_s390_itdb {struct sie_page {struct kvm_s390_sie_block sie_block;struct mcck_volatile_info mcck_info;/* 0x0200 */ -__u8 reserved218[1000 ];/* 0x0218 */ +__u8 reserved218[360 ];/* 0x0218 */ +__u64 pv_grregs[16 ];/* 0x380 */ +__u8 reserved400[512 ];struct kvm_s390_itdb itdb;/* 0x0600 */ __u8 reserved700[2304 ];/* 0x0700 */ };
arch/s390/kvm/kvm-s390.c +11 -0
@@ -3965,6 +3965,7 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)static int __vcpu_run (struct kvm_vcpu *vcpu) {int rc, exit_reason; +struct sie_page *sie_page = (struct sie_page *)vcpu->arch.sie_block;/* * We try to hold kvm->srcu during most of vcpu_run (except when run-
@@ -3986,8 +3987,18 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)guest_enter_irqoff ();__disable_cpu_timer_accounting (vcpu);local_irq_enable (); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { +memcpy (sie_page->pv_grregs, + vcpu->run->s.regs.gprs, +sizeof (sie_page->pv_grregs)); + } exit_reason =sie64a (vcpu->arch.sie_block, vcpu->run->s.regs.gprs); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { +memcpy (vcpu->run->s.regs.gprs, + sie_page->pv_grregs, +sizeof (sie_page->pv_grregs)); + }local_irq_disable ();__enable_cpu_timer_accounting (vcpu);guest_exit_irqoff ();
Signature · 1 line
2.20.1
Re: [RFC 19/37] KVM: s390: protvirt: Add new gprs location handling
Quoted 41 lines · Janosch Frank
Guest registers for protected guests are stored at offset
0x380.Signed-off-by Janosch Frank <[email protected]>--- arch/s390/include/asm/kvm_host.h | 4 +++- arch/s390/kvm/kvm-s390.c | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-)arch/s390/include/asm/kvm_host.h +3
-1@@ -336,7 +336,9 @@ struct kvm_s390_itdb {struct sie_page {struct kvm_s390_sie_block sie_block;struct mcck_volatile_info mcck_info;/* 0x0200 */ -__u8 reserved218[1000 ];/* 0x0218 */ +__u8 reserved218[360 ];/* 0x0218 */ +__u64 pv_grregs[16 ];/* 0x380 */ +__u8 reserved400[512 ];struct kvm_s390_itdb itdb;/* 0x0600 */ __u8 reserved700[2304 ];/* 0x0700 */ };arch/s390/kvm/kvm-s390.c +3
-0@@ -3965,6 +3965,7 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)static int __vcpu_run (struct kvm_vcpu *vcpu) {int rc, exit_reason; +struct sie_page *sie_page = (struct sie_page *)vcpu->arch.sie_block;/* * We try to hold kvm->srcu during most of vcpu_run (except when run- @@ -3986,8 +3987,18 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)guest_enter_irqoff ();__disable_cpu_timer_accounting (vcpu);local_irq_enable (); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { + memcpy(sie_page->pv_grregs,
arch/s390/kvm/kvm-s390.c static int __vcpu_run(struct kvm_vcpu *vcpu) · line 4001
Quoted 10 lines
arch/s390/kvm/kvm-s390.c +8
-0+ vcpu->run->s.regs.gprs, + sizeof(sie_page->pv_grregs)); + } exit_reason =sie64a (vcpu->arch.sie_block, vcpu->run->s.regs.gprs); +if (kvm_s390_pv_is_protected (vcpu->kvm)) { +memcpy (vcpu->run->s.regs.gprs, + sie_page->pv_grregs, +sizeof (sie_page->pv_grregs)); + }
sie64a will load/save gprs 0-13 from to vcpu->run->s.regs.gprs.
I would have assume that this is not required for prot virt, because the HW has direct access via the sie block?
1. Would it make sense to have a specialized sie64a() (or a parameter, e.g., if you pass in NULL in r3), that optimizes this loading/saving? Eventually we can also optimize which host registers to save/restore then.
2. Avoid this copying here. We have to store the state to vcpu->run->s.regs.gprs when returning to user space and restore the state when coming from user space.
Also, we access the GPRS from interception handlers, there we might use wrappers like
kvm_s390_set_gprs()kvm_s390_get_gprs()
to route to the right location. There are multiple options to optimize this.
Signature · 3 lines
Thanks, David / dhildenb