2017-11-24 15:00:33 +01:00
// SPDX-License-Identifier: GPL-2.0
2015-07-08 13:19:48 +02:00
/*
* kvm nested virtualization support for s390x
*
2018-03-08 16:08:49 +00:00
* Copyright IBM Corp . 2016 , 2018
2015-07-08 13:19:48 +02:00
*
* Author ( s ) : David Hildenbrand < dahi @ linux . vnet . ibm . com >
*/
# include <linux/vmalloc.h>
# include <linux/kvm_host.h>
# include <linux/bug.h>
# include <linux/list.h>
# include <linux/bitmap.h>
2017-02-02 19:15:33 +01:00
# include <linux/sched/signal.h>
2015-07-08 13:19:48 +02:00
# include <asm/gmap.h>
# include <asm/mmu_context.h>
# include <asm/sclp.h>
# include <asm/nmi.h>
2015-11-26 14:11:19 +01:00
# include <asm/dis.h>
2015-07-08 13:19:48 +02:00
# include "kvm-s390.h"
# include "gaccess.h"
struct vsie_page {
struct kvm_s390_sie_block scb_s ; /* 0x0000 */
2017-06-07 12:11:18 +02:00
/*
* the backup info for machine check . ensure it ' s at
* the same offset as that in struct sie_page !
*/
struct mcck_volatile_info mcck_info ; /* 0x0200 */
2018-01-16 18:15:25 +01:00
/*
* The pinned original scb . Be aware that other VCPUs can modify
* it while we read from it . Values that are used for conditions or
* are reused conditionally , should be accessed via READ_ONCE .
*/
2017-06-07 12:11:18 +02:00
struct kvm_s390_sie_block * scb_o ; /* 0x0218 */
2015-07-08 13:19:48 +02:00
/* the shadow gmap in use by the vsie_page */
2017-06-07 12:11:18 +02:00
struct gmap * gmap ; /* 0x0220 */
2015-07-08 13:25:31 +02:00
/* address of the last reported fault to guest2 */
2017-06-07 12:11:18 +02:00
unsigned long fault_addr ; /* 0x0228 */
2018-01-16 18:15:26 +01:00
/* calculated guest addresses of satellite control blocks */
gpa_t sca_gpa ; /* 0x0230 */
gpa_t itdba_gpa ; /* 0x0238 */
gpa_t gvrd_gpa ; /* 0x0240 */
gpa_t riccbd_gpa ; /* 0x0248 */
gpa_t sdnx_gpa ; /* 0x0250 */
__u8 reserved [ 0x0700 - 0x0258 ] ; /* 0x0258 */
2015-11-26 13:11:42 +01:00
struct kvm_s390_crypto_cb crycb ; /* 0x0700 */
2015-11-26 14:11:19 +01:00
__u8 fac [ S390_ARCH_FAC_LIST_SIZE_BYTE ] ; /* 0x0800 */
2017-06-21 16:49:15 +02:00
} ;
2015-07-08 13:19:48 +02:00
/* trigger a validity icpt for the given scb */
static int set_validity_icpt ( struct kvm_s390_sie_block * scb ,
__u16 reason_code )
{
scb - > ipa = 0x1000 ;
scb - > ipb = ( ( __u32 ) reason_code ) < < 16 ;
scb - > icptcode = ICPT_VALIDITY ;
return 1 ;
}
/* mark the prefix as unmapped, this will block the VSIE */
static void prefix_unmapped ( struct vsie_page * vsie_page )
{
atomic_or ( PROG_REQUEST , & vsie_page - > scb_s . prog20 ) ;
}
/* mark the prefix as unmapped and wait until the VSIE has been left */
static void prefix_unmapped_sync ( struct vsie_page * vsie_page )
{
prefix_unmapped ( vsie_page ) ;
if ( vsie_page - > scb_s . prog0c & PROG_IN_SIE )
atomic_or ( CPUSTAT_STOP_INT , & vsie_page - > scb_s . cpuflags ) ;
while ( vsie_page - > scb_s . prog0c & PROG_IN_SIE )
cpu_relax ( ) ;
}
/* mark the prefix as mapped, this will allow the VSIE to run */
static void prefix_mapped ( struct vsie_page * vsie_page )
{
atomic_andnot ( PROG_REQUEST , & vsie_page - > scb_s . prog20 ) ;
}
2016-04-22 13:50:09 +02:00
/* test if the prefix is mapped into the gmap shadow */
static int prefix_is_mapped ( struct vsie_page * vsie_page )
{
return ! ( atomic_read ( & vsie_page - > scb_s . prog20 ) & PROG_REQUEST ) ;
}
2015-07-08 13:19:48 +02:00
/* copy the updated intervention request bits into the shadow scb */
static void update_intervention_requests ( struct vsie_page * vsie_page )
{
const int bits = CPUSTAT_STOP_INT | CPUSTAT_IO_INT | CPUSTAT_EXT_INT ;
int cpuflags ;
cpuflags = atomic_read ( & vsie_page - > scb_o - > cpuflags ) ;
atomic_andnot ( bits , & vsie_page - > scb_s . cpuflags ) ;
atomic_or ( cpuflags & bits , & vsie_page - > scb_s . cpuflags ) ;
}
/* shadow (filter and validate) the cpuflags */
static int prepare_cpuflags ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
struct kvm_s390_sie_block * scb_o = vsie_page - > scb_o ;
int newflags , cpuflags = atomic_read ( & scb_o - > cpuflags ) ;
/* we don't allow ESA/390 guests */
if ( ! ( cpuflags & CPUSTAT_ZARCH ) )
return set_validity_icpt ( scb_s , 0x0001U ) ;
if ( cpuflags & ( CPUSTAT_RRF | CPUSTAT_MCDS ) )
return set_validity_icpt ( scb_s , 0x0001U ) ;
else if ( cpuflags & ( CPUSTAT_SLSV | CPUSTAT_SLSR ) )
return set_validity_icpt ( scb_s , 0x0007U ) ;
/* intervention requests will be set later */
newflags = CPUSTAT_ZARCH ;
2016-02-12 12:24:20 +01:00
if ( cpuflags & CPUSTAT_GED & & test_kvm_facility ( vcpu - > kvm , 8 ) )
newflags | = CPUSTAT_GED ;
if ( cpuflags & CPUSTAT_GED2 & & test_kvm_facility ( vcpu - > kvm , 78 ) ) {
if ( cpuflags & CPUSTAT_GED )
return set_validity_icpt ( scb_s , 0x0001U ) ;
newflags | = CPUSTAT_GED2 ;
}
2015-11-24 16:32:35 +01:00
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_GPERE ) )
newflags | = cpuflags & CPUSTAT_P ;
2015-11-24 16:41:33 +01:00
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_GSLS ) )
newflags | = cpuflags & CPUSTAT_SM ;
2015-11-24 16:56:23 +01:00
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_IBS ) )
newflags | = cpuflags & CPUSTAT_IBS ;
2017-02-24 16:12:56 -05:00
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_KSS ) )
newflags | = cpuflags & CPUSTAT_KSS ;
2015-07-08 13:19:48 +02:00
atomic_set ( & scb_s - > cpuflags , newflags ) ;
return 0 ;
}
2018-09-25 19:16:37 -04:00
/* Copy to APCB FORMAT1 from APCB FORMAT0 */
static int setup_apcb10 ( struct kvm_vcpu * vcpu , struct kvm_s390_apcb1 * apcb_s ,
unsigned long apcb_o , struct kvm_s390_apcb1 * apcb_h )
{
struct kvm_s390_apcb0 tmp ;
2015-07-08 13:19:48 +02:00
2018-09-25 19:16:37 -04:00
if ( read_guest_real ( vcpu , apcb_o , & tmp , sizeof ( struct kvm_s390_apcb0 ) ) )
return - EFAULT ;
apcb_s - > apm [ 0 ] = apcb_h - > apm [ 0 ] & tmp . apm [ 0 ] ;
apcb_s - > aqm [ 0 ] = apcb_h - > aqm [ 0 ] & tmp . aqm [ 0 ] & 0xffff000000000000UL ;
apcb_s - > adm [ 0 ] = apcb_h - > adm [ 0 ] & tmp . adm [ 0 ] & 0xffff000000000000UL ;
return 0 ;
}
2015-07-08 13:19:48 +02:00
2018-09-25 19:16:35 -04:00
/**
* setup_apcb00 - Copy to APCB FORMAT0 from APCB FORMAT0
* @ vcpu : pointer to the virtual CPU
* @ apcb_s : pointer to start of apcb in the shadow crycb
* @ apcb_o : pointer to start of original apcb in the guest2
* @ apcb_h : pointer to start of apcb in the guest1
*
* Returns 0 and - EFAULT on error reading guest apcb
*/
2018-09-25 19:16:34 -04:00
static int setup_apcb00 ( struct kvm_vcpu * vcpu , unsigned long * apcb_s ,
unsigned long apcb_o , unsigned long * apcb_h )
{
if ( read_guest_real ( vcpu , apcb_o , apcb_s ,
sizeof ( struct kvm_s390_apcb0 ) ) )
return - EFAULT ;
bitmap_and ( apcb_s , apcb_s , apcb_h , sizeof ( struct kvm_s390_apcb0 ) ) ;
return 0 ;
}
2018-09-25 19:16:33 -04:00
/**
* setup_apcb11 - Copy the FORMAT1 APCB from the guest to the shadow CRYCB
* @ vcpu : pointer to the virtual CPU
* @ apcb_s : pointer to start of apcb in the shadow crycb
* @ apcb_o : pointer to start of original guest apcb
* @ apcb_h : pointer to start of apcb in the host
*
* Returns 0 and - EFAULT on error reading guest apcb
*/
static int setup_apcb11 ( struct kvm_vcpu * vcpu , unsigned long * apcb_s ,
unsigned long apcb_o ,
unsigned long * apcb_h )
{
if ( read_guest_real ( vcpu , apcb_o , apcb_s ,
sizeof ( struct kvm_s390_apcb1 ) ) )
return - EFAULT ;
bitmap_and ( apcb_s , apcb_s , apcb_h , sizeof ( struct kvm_s390_apcb1 ) ) ;
return 0 ;
}
/**
* setup_apcb - Create a shadow copy of the apcb .
* @ vcpu : pointer to the virtual CPU
* @ crycb_s : pointer to shadow crycb
* @ crycb_o : pointer to original guest crycb
* @ crycb_h : pointer to the host crycb
* @ fmt_o : format of the original guest crycb .
* @ fmt_h : format of the host crycb .
*
* Checks the compatibility between the guest and host crycb and calls the
* appropriate copy function .
*
* Return 0 or an error number if the guest and host crycb are incompatible .
*/
static int setup_apcb ( struct kvm_vcpu * vcpu , struct kvm_s390_crypto_cb * crycb_s ,
const u32 crycb_o ,
struct kvm_s390_crypto_cb * crycb_h ,
int fmt_o , int fmt_h )
{
struct kvm_s390_crypto_cb * crycb ;
crycb = ( struct kvm_s390_crypto_cb * ) ( unsigned long ) crycb_o ;
switch ( fmt_o ) {
case CRYCB_FORMAT2 :
if ( ( crycb_o & PAGE_MASK ) ! = ( ( crycb_o + 256 ) & PAGE_MASK ) )
return - EACCES ;
if ( fmt_h ! = CRYCB_FORMAT2 )
return - EINVAL ;
return setup_apcb11 ( vcpu , ( unsigned long * ) & crycb_s - > apcb1 ,
( unsigned long ) & crycb - > apcb1 ,
( unsigned long * ) & crycb_h - > apcb1 ) ;
2018-09-25 19:16:34 -04:00
case CRYCB_FORMAT1 :
2018-09-25 19:16:37 -04:00
switch ( fmt_h ) {
case CRYCB_FORMAT2 :
return setup_apcb10 ( vcpu , & crycb_s - > apcb1 ,
( unsigned long ) & crycb - > apcb0 ,
& crycb_h - > apcb1 ) ;
case CRYCB_FORMAT1 :
return setup_apcb00 ( vcpu ,
( unsigned long * ) & crycb_s - > apcb0 ,
( unsigned long ) & crycb - > apcb0 ,
( unsigned long * ) & crycb_h - > apcb0 ) ;
}
break ;
2018-09-25 19:16:35 -04:00
case CRYCB_FORMAT0 :
if ( ( crycb_o & PAGE_MASK ) ! = ( ( crycb_o + 32 ) & PAGE_MASK ) )
return - EACCES ;
2018-09-25 19:16:36 -04:00
switch ( fmt_h ) {
case CRYCB_FORMAT2 :
2018-09-25 19:16:38 -04:00
return setup_apcb10 ( vcpu , & crycb_s - > apcb1 ,
( unsigned long ) & crycb - > apcb0 ,
& crycb_h - > apcb1 ) ;
2018-09-25 19:16:36 -04:00
case CRYCB_FORMAT1 :
case CRYCB_FORMAT0 :
return setup_apcb00 ( vcpu ,
( unsigned long * ) & crycb_s - > apcb0 ,
( unsigned long ) & crycb - > apcb0 ,
( unsigned long * ) & crycb_h - > apcb0 ) ;
}
2018-09-25 19:16:33 -04:00
}
return - EINVAL ;
}
/**
* shadow_crycb - Create a shadow copy of the crycb block
* @ vcpu : a pointer to the virtual CPU
* @ vsie_page : a pointer to internal date used for the vSIE
*
2015-11-26 13:11:42 +01:00
* Create a shadow copy of the crycb block and setup key wrapping , if
* requested for guest 3 and enabled for guest 2.
*
2018-09-25 19:16:33 -04:00
* We accept format - 1 or format - 2 , but we convert format - 1 into format - 2
* in the shadow CRYCB .
* Using format - 2 enables the firmware to choose the right format when
* scheduling the SIE .
2015-11-26 13:11:42 +01:00
* There is nothing to do for format - 0.
*
2018-09-25 19:16:33 -04:00
* This function centralize the issuing of set_validity_icpt ( ) for all
* the subfunctions working on the crycb .
*
2015-11-26 13:11:42 +01:00
* Returns : - 0 if shadowed or nothing to do
* - > 0 if control has to be given to guest 2
*/
static int shadow_crycb ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
struct kvm_s390_sie_block * scb_o = vsie_page - > scb_o ;
2018-01-16 18:15:25 +01:00
const uint32_t crycbd_o = READ_ONCE ( scb_o - > crycbd ) ;
const u32 crycb_addr = crycbd_o & 0x7ffffff8U ;
2015-11-26 13:11:42 +01:00
unsigned long * b1 , * b2 ;
u8 ecb3_flags ;
2019-04-03 03:00:35 -04:00
u32 ecd_flags ;
2018-09-25 19:16:33 -04:00
int apie_h ;
2019-04-26 10:56:50 +02:00
int apie_s ;
2018-09-25 19:16:33 -04:00
int key_msk = test_kvm_facility ( vcpu - > kvm , 76 ) ;
int fmt_o = crycbd_o & CRYCB_FORMAT_MASK ;
int fmt_h = vcpu - > arch . sie_block - > crycbd & CRYCB_FORMAT_MASK ;
int ret = 0 ;
2015-11-26 13:11:42 +01:00
scb_s - > crycbd = 0 ;
2018-09-25 19:16:33 -04:00
apie_h = vcpu - > arch . sie_block - > eca & ECA_APIE ;
2019-04-26 10:56:50 +02:00
apie_s = apie_h & scb_o - > eca ;
if ( ! apie_s & & ( ! key_msk | | ( fmt_o = = CRYCB_FORMAT0 ) ) )
2015-11-26 13:11:42 +01:00
return 0 ;
2018-09-25 19:16:33 -04:00
if ( ! crycb_addr )
2015-11-26 13:11:42 +01:00
return set_validity_icpt ( scb_s , 0x0039U ) ;
2018-09-25 19:16:33 -04:00
if ( fmt_o = = CRYCB_FORMAT1 )
if ( ( crycb_addr & PAGE_MASK ) ! =
( ( crycb_addr + 128 ) & PAGE_MASK ) )
return set_validity_icpt ( scb_s , 0x003CU ) ;
2019-04-26 10:56:50 +02:00
if ( apie_s ) {
2018-09-25 19:16:33 -04:00
ret = setup_apcb ( vcpu , & vsie_page - > crycb , crycb_addr ,
vcpu - > kvm - > arch . crypto . crycb ,
fmt_o , fmt_h ) ;
if ( ret )
goto end ;
scb_s - > eca | = scb_o - > eca & ECA_APIE ;
}
2015-11-26 13:11:42 +01:00
/* we may only allow it if enabled for guest 2 */
ecb3_flags = scb_o - > ecb3 & vcpu - > arch . sie_block - > ecb3 &
( ECB3_AES | ECB3_DEA ) ;
2019-04-03 03:00:35 -04:00
ecd_flags = scb_o - > ecd & vcpu - > arch . sie_block - > ecd & ECD_ECC ;
if ( ! ecb3_flags & & ! ecd_flags )
2018-09-25 19:16:33 -04:00
goto end ;
2015-11-26 13:11:42 +01:00
/* copy only the wrapping keys */
2018-08-23 12:25:54 +02:00
if ( read_guest_real ( vcpu , crycb_addr + 72 ,
vsie_page - > crycb . dea_wrapping_key_mask , 56 ) )
2015-11-26 13:11:42 +01:00
return set_validity_icpt ( scb_s , 0x0035U ) ;
scb_s - > ecb3 | = ecb3_flags ;
2019-04-03 03:00:35 -04:00
scb_s - > ecd | = ecd_flags ;
2015-11-26 13:11:42 +01:00
/* xor both blocks in one run */
b1 = ( unsigned long * ) vsie_page - > crycb . dea_wrapping_key_mask ;
b2 = ( unsigned long * )
vcpu - > kvm - > arch . crypto . crycb - > dea_wrapping_key_mask ;
/* as 56%8 == 0, bitmap_xor won't overwrite any data */
bitmap_xor ( b1 , b1 , b2 , BITS_PER_BYTE * 56 ) ;
2018-09-25 19:16:33 -04:00
end :
switch ( ret ) {
case - EINVAL :
2019-04-26 11:00:01 +02:00
return set_validity_icpt ( scb_s , 0x0022U ) ;
2018-09-25 19:16:33 -04:00
case - EFAULT :
return set_validity_icpt ( scb_s , 0x0035U ) ;
case - EACCES :
return set_validity_icpt ( scb_s , 0x003CU ) ;
}
scb_s - > crycbd = ( ( __u32 ) ( __u64 ) & vsie_page - > crycb ) | CRYCB_FORMAT2 ;
2015-11-26 13:11:42 +01:00
return 0 ;
}
2016-02-19 10:11:24 +01:00
/* shadow (round up/down) the ibc to avoid validity icpt */
static void prepare_ibc ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
struct kvm_s390_sie_block * scb_o = vsie_page - > scb_o ;
2018-01-16 18:15:25 +01:00
/* READ_ONCE does not work on bitfields - use a temporary variable */
const uint32_t __new_ibc = scb_o - > ibc ;
const uint32_t new_ibc = READ_ONCE ( __new_ibc ) & 0x0fffU ;
2016-02-19 10:11:24 +01:00
__u64 min_ibc = ( sclp . ibc > > 16 ) & 0x0fffU ;
scb_s - > ibc = 0 ;
/* ibc installed in g2 and requested for g3 */
2018-01-16 18:15:25 +01:00
if ( vcpu - > kvm - > arch . model . ibc & & new_ibc ) {
scb_s - > ibc = new_ibc ;
2016-02-19 10:11:24 +01:00
/* takte care of the minimum ibc level of the machine */
if ( scb_s - > ibc < min_ibc )
scb_s - > ibc = min_ibc ;
/* take care of the maximum ibc level set for the guest */
if ( scb_s - > ibc > vcpu - > kvm - > arch . model . ibc )
scb_s - > ibc = vcpu - > kvm - > arch . model . ibc ;
}
}
2015-07-08 13:19:48 +02:00
/* unshadow the scb, copying parameters back to the real scb */
static void unshadow_scb ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
struct kvm_s390_sie_block * scb_o = vsie_page - > scb_o ;
/* interception */
scb_o - > icptcode = scb_s - > icptcode ;
scb_o - > icptstatus = scb_s - > icptstatus ;
scb_o - > ipa = scb_s - > ipa ;
scb_o - > ipb = scb_s - > ipb ;
scb_o - > gbea = scb_s - > gbea ;
/* timer */
scb_o - > cputm = scb_s - > cputm ;
scb_o - > ckc = scb_s - > ckc ;
scb_o - > todpr = scb_s - > todpr ;
/* guest state */
scb_o - > gpsw = scb_s - > gpsw ;
scb_o - > gg14 = scb_s - > gg14 ;
scb_o - > gg15 = scb_s - > gg15 ;
memcpy ( scb_o - > gcr , scb_s - > gcr , 128 ) ;
scb_o - > pp = scb_s - > pp ;
2018-01-17 14:44:34 +01:00
/* branch prediction */
if ( test_kvm_facility ( vcpu - > kvm , 82 ) ) {
scb_o - > fpf & = ~ FPF_BPBC ;
scb_o - > fpf | = scb_s - > fpf & FPF_BPBC ;
}
2015-07-08 13:19:48 +02:00
/* interrupt intercept */
switch ( scb_s - > icptcode ) {
case ICPT_PROGI :
case ICPT_INSTPROGI :
case ICPT_EXTINT :
memcpy ( ( void * ) ( ( u64 ) scb_o + 0xc0 ) ,
( void * ) ( ( u64 ) scb_s + 0xc0 ) , 0xf0 - 0xc0 ) ;
break ;
case ICPT_PARTEXEC :
/* MVPG only */
memcpy ( ( void * ) ( ( u64 ) scb_o + 0xc0 ) ,
( void * ) ( ( u64 ) scb_s + 0xc0 ) , 0xd0 - 0xc0 ) ;
break ;
}
if ( scb_s - > ihcpu ! = 0xffffU )
scb_o - > ihcpu = scb_s - > ihcpu ;
}
/*
* Setup the shadow scb by copying and checking the relevant parts of the g2
* provided scb .
*
* Returns : - 0 if the scb has been shadowed
* - > 0 if control has to be given to guest 2
*/
static int shadow_scb ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_o = vsie_page - > scb_o ;
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
2018-01-16 18:15:25 +01:00
/* READ_ONCE does not work on bitfields - use a temporary variable */
const uint32_t __new_prefix = scb_o - > prefix ;
const uint32_t new_prefix = READ_ONCE ( __new_prefix ) ;
const bool wants_tx = READ_ONCE ( scb_o - > ecb ) & ECB_TE ;
2017-03-13 11:48:28 +01:00
bool had_tx = scb_s - > ecb & ECB_TE ;
2015-11-24 16:41:33 +01:00
unsigned long new_mso = 0 ;
2015-07-08 13:19:48 +02:00
int rc ;
/* make sure we don't have any leftovers when reusing the scb */
scb_s - > icptcode = 0 ;
scb_s - > eca = 0 ;
scb_s - > ecb = 0 ;
scb_s - > ecb2 = 0 ;
scb_s - > ecb3 = 0 ;
scb_s - > ecd = 0 ;
2015-11-26 14:11:19 +01:00
scb_s - > fac = 0 ;
2018-01-17 14:44:34 +01:00
scb_s - > fpf = 0 ;
2015-07-08 13:19:48 +02:00
rc = prepare_cpuflags ( vcpu , vsie_page ) ;
if ( rc )
goto out ;
/* timer */
scb_s - > cputm = scb_o - > cputm ;
scb_s - > ckc = scb_o - > ckc ;
scb_s - > todpr = scb_o - > todpr ;
scb_s - > epoch = scb_o - > epoch ;
/* guest state */
scb_s - > gpsw = scb_o - > gpsw ;
scb_s - > gg14 = scb_o - > gg14 ;
scb_s - > gg15 = scb_o - > gg15 ;
memcpy ( scb_s - > gcr , scb_o - > gcr , 128 ) ;
scb_s - > pp = scb_o - > pp ;
/* interception / execution handling */
scb_s - > gbea = scb_o - > gbea ;
scb_s - > lctl = scb_o - > lctl ;
scb_s - > svcc = scb_o - > svcc ;
scb_s - > ictl = scb_o - > ictl ;
/*
* SKEY handling functions can ' t deal with false setting of PTE invalid
* bits . Therefore we cannot provide interpretation and would later
* have to provide own emulation handlers .
*/
2017-02-24 16:12:56 -05:00
if ( ! ( atomic_read ( & scb_s - > cpuflags ) & CPUSTAT_KSS ) )
scb_s - > ictl | = ICTL_ISKE | ICTL_SSKE | ICTL_RRBE ;
2015-07-08 13:19:48 +02:00
scb_s - > icpua = scb_o - > icpua ;
2015-11-24 16:41:33 +01:00
if ( ! ( atomic_read ( & scb_s - > cpuflags ) & CPUSTAT_SM ) )
2018-01-16 18:15:25 +01:00
new_mso = READ_ONCE ( scb_o - > mso ) & 0xfffffffffff00000UL ;
2016-04-22 13:50:09 +02:00
/* if the hva of the prefix changes, we have to remap the prefix */
2018-01-16 18:15:25 +01:00
if ( scb_s - > mso ! = new_mso | | scb_s - > prefix ! = new_prefix )
2016-04-22 13:50:09 +02:00
prefix_unmapped ( vsie_page ) ;
2015-07-08 13:19:48 +02:00
/* SIE will do mso/msl validity and exception checks for us */
scb_s - > msl = scb_o - > msl & 0xfffffffffff00000UL ;
2016-04-22 13:50:09 +02:00
scb_s - > mso = new_mso ;
2018-01-16 18:15:25 +01:00
scb_s - > prefix = new_prefix ;
2015-07-08 13:19:48 +02:00
/* We have to definetly flush the tlb if this scb never ran */
if ( scb_s - > ihcpu ! = 0xffffU )
scb_s - > ihcpu = scb_o - > ihcpu ;
/* MVPG and Protection Exception Interpretation are always available */
2017-03-13 11:48:28 +01:00
scb_s - > eca | = scb_o - > eca & ( ECA_MVPGI | ECA_PROTEXCI ) ;
2015-11-27 12:34:28 +01:00
/* Host-protection-interruption introduced with ESOP */
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_ESOP ) )
2017-03-13 11:48:28 +01:00
scb_s - > ecb | = scb_o - > ecb & ECB_HOSTPROTINT ;
2015-11-25 11:13:32 +01:00
/* transactional execution */
2018-01-16 18:15:25 +01:00
if ( test_kvm_facility ( vcpu - > kvm , 73 ) & & wants_tx ) {
2015-11-25 11:13:32 +01:00
/* remap the prefix is tx is toggled on */
2018-01-16 18:15:25 +01:00
if ( ! had_tx )
2015-11-25 11:13:32 +01:00
prefix_unmapped ( vsie_page ) ;
2018-01-16 18:15:25 +01:00
scb_s - > ecb | = ECB_TE ;
2015-11-25 11:13:32 +01:00
}
2018-01-17 14:44:34 +01:00
/* branch prediction */
if ( test_kvm_facility ( vcpu - > kvm , 82 ) )
scb_s - > fpf | = scb_o - > fpf & FPF_BPBC ;
2015-11-25 11:08:32 +01:00
/* SIMD */
if ( test_kvm_facility ( vcpu - > kvm , 129 ) ) {
2017-03-13 11:48:28 +01:00
scb_s - > eca | = scb_o - > eca & ECA_VX ;
scb_s - > ecd | = scb_o - > ecd & ECD_HOSTREGMGMT ;
2015-11-25 11:08:32 +01:00
}
2016-01-26 12:51:06 +01:00
/* Run-time-Instrumentation */
if ( test_kvm_facility ( vcpu - > kvm , 64 ) )
2017-03-13 11:48:28 +01:00
scb_s - > ecb3 | = scb_o - > ecb3 & ECB3_RI ;
2016-08-04 09:57:36 +02:00
/* Instruction Execution Prevention */
if ( test_kvm_facility ( vcpu - > kvm , 130 ) )
2017-03-13 11:48:28 +01:00
scb_s - > ecb2 | = scb_o - > ecb2 & ECB2_IEP ;
2016-11-29 07:17:55 +01:00
/* Guarded Storage */
if ( test_kvm_facility ( vcpu - > kvm , 133 ) ) {
scb_s - > ecb | = scb_o - > ecb & ECB_GS ;
scb_s - > ecd | = scb_o - > ecd & ECD_HOSTREGMGMT ;
}
2015-11-25 09:59:49 +01:00
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_SIIF ) )
2017-03-13 11:48:28 +01:00
scb_s - > eca | = scb_o - > eca & ECA_SII ;
2015-11-24 16:53:51 +01:00
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_IB ) )
2017-03-13 11:48:28 +01:00
scb_s - > eca | = scb_o - > eca & ECA_IB ;
2015-11-24 16:54:37 +01:00
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_CEI ) )
2017-03-13 11:48:28 +01:00
scb_s - > eca | = scb_o - > eca & ECA_CEI ;
2016-07-26 15:29:44 -04:00
/* Epoch Extension */
if ( test_kvm_facility ( vcpu - > kvm , 139 ) )
scb_s - > ecd | = scb_o - > ecd & ECD_MEF ;
2015-07-08 13:19:48 +02:00
2018-03-08 16:08:49 +00:00
/* etoken */
if ( test_kvm_facility ( vcpu - > kvm , 156 ) )
scb_s - > ecd | = scb_o - > ecd & ECD_ETOKENF ;
2018-08-31 12:51:19 -04:00
scb_s - > hpid = HPID_VSIE ;
2020-06-22 11:46:36 -04:00
scb_s - > cpnc = scb_o - > cpnc ;
2018-08-31 12:51:19 -04:00
2016-02-19 10:11:24 +01:00
prepare_ibc ( vcpu , vsie_page ) ;
2015-11-26 13:11:42 +01:00
rc = shadow_crycb ( vcpu , vsie_page ) ;
2015-07-08 13:19:48 +02:00
out :
if ( rc )
unshadow_scb ( vcpu , vsie_page ) ;
return rc ;
}
void kvm_s390_vsie_gmap_notifier ( struct gmap * gmap , unsigned long start ,
unsigned long end )
{
struct kvm * kvm = gmap - > private ;
struct vsie_page * cur ;
unsigned long prefix ;
struct page * page ;
int i ;
if ( ! gmap_is_shadow ( gmap ) )
return ;
if ( start > = 1UL < < 31 )
/* We are only interested in prefix pages */
return ;
/*
* Only new shadow blocks are added to the list during runtime ,
* therefore we can safely reference them all the time .
*/
for ( i = 0 ; i < kvm - > arch . vsie . page_count ; i + + ) {
page = READ_ONCE ( kvm - > arch . vsie . pages [ i ] ) ;
if ( ! page )
continue ;
cur = page_to_virt ( page ) ;
if ( READ_ONCE ( cur - > gmap ) ! = gmap )
continue ;
prefix = cur - > scb_s . prefix < < GUEST_PREFIX_SHIFT ;
/* with mso/msl, the prefix lies at an offset */
prefix + = cur - > scb_s . mso ;
2015-11-25 11:13:32 +01:00
if ( prefix < = end & & start < = prefix + 2 * PAGE_SIZE - 1 )
2015-07-08 13:19:48 +02:00
prefix_unmapped_sync ( cur ) ;
}
}
/*
2015-11-25 11:13:32 +01:00
* Map the first prefix page and if tx is enabled also the second prefix page .
2015-07-08 13:19:48 +02:00
*
* The prefix will be protected , a gmap notifier will inform about unmaps .
* The shadow scb must not be executed until the prefix is remapped , this is
* guaranteed by properly handling PROG_REQUEST .
*
* Returns : - 0 on if successfully mapped or already mapped
* - > 0 if control has to be given to guest 2
* - - EAGAIN if the caller can retry immediately
* - - ENOMEM if out of memory
*/
static int map_prefix ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
u64 prefix = scb_s - > prefix < < GUEST_PREFIX_SHIFT ;
int rc ;
2016-04-22 13:50:09 +02:00
if ( prefix_is_mapped ( vsie_page ) )
return 0 ;
2015-07-08 13:19:48 +02:00
/* mark it as mapped so we can catch any concurrent unmappers */
prefix_mapped ( vsie_page ) ;
/* with mso/msl, the prefix lies at offset *mso* */
prefix + = scb_s - > mso ;
rc = kvm_s390_shadow_fault ( vcpu , vsie_page - > gmap , prefix ) ;
2017-03-13 11:48:28 +01:00
if ( ! rc & & ( scb_s - > ecb & ECB_TE ) )
2015-11-25 11:13:32 +01:00
rc = kvm_s390_shadow_fault ( vcpu , vsie_page - > gmap ,
prefix + PAGE_SIZE ) ;
2015-07-08 13:19:48 +02:00
/*
* We don ' t have to mprotect , we will be called for all unshadows .
* SIE will detect if protection applies and trigger a validity .
*/
if ( rc )
prefix_unmapped ( vsie_page ) ;
if ( rc > 0 | | rc = = - EFAULT )
rc = set_validity_icpt ( scb_s , 0x0037U ) ;
return rc ;
}
/*
* Pin the guest page given by gpa and set hpa to the pinned host address .
* Will always be pinned writable .
*
* Returns : - 0 on success
* - - EINVAL if the gpa is not valid guest storage
*/
static int pin_guest_page ( struct kvm * kvm , gpa_t gpa , hpa_t * hpa )
{
struct page * page ;
2017-09-01 17:11:43 +02:00
page = gfn_to_page ( kvm , gpa_to_gfn ( gpa ) ) ;
if ( is_error_page ( page ) )
2015-07-08 13:19:48 +02:00
return - EINVAL ;
* hpa = ( hpa_t ) page_to_virt ( page ) + ( gpa & ~ PAGE_MASK ) ;
return 0 ;
}
/* Unpins a page previously pinned via pin_guest_page, marking it as dirty. */
static void unpin_guest_page ( struct kvm * kvm , gpa_t gpa , hpa_t hpa )
{
2017-09-01 17:11:43 +02:00
kvm_release_pfn_dirty ( hpa > > PAGE_SHIFT ) ;
2015-07-08 13:19:48 +02:00
/* mark the page always as dirty for migration */
mark_page_dirty ( kvm , gpa_to_gfn ( gpa ) ) ;
}
/* unpin all blocks previously pinned by pin_blocks(), marking them dirty */
static void unpin_blocks ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
hpa_t hpa ;
hpa = ( u64 ) scb_s - > scaoh < < 32 | scb_s - > scaol ;
if ( hpa ) {
2018-01-16 18:15:26 +01:00
unpin_guest_page ( vcpu - > kvm , vsie_page - > sca_gpa , hpa ) ;
vsie_page - > sca_gpa = 0 ;
2015-07-08 13:19:48 +02:00
scb_s - > scaol = 0 ;
scb_s - > scaoh = 0 ;
}
2015-11-25 11:13:32 +01:00
hpa = scb_s - > itdba ;
if ( hpa ) {
2018-01-16 18:15:26 +01:00
unpin_guest_page ( vcpu - > kvm , vsie_page - > itdba_gpa , hpa ) ;
vsie_page - > itdba_gpa = 0 ;
2015-11-25 11:13:32 +01:00
scb_s - > itdba = 0 ;
}
2015-11-25 11:08:32 +01:00
hpa = scb_s - > gvrd ;
if ( hpa ) {
2018-01-16 18:15:26 +01:00
unpin_guest_page ( vcpu - > kvm , vsie_page - > gvrd_gpa , hpa ) ;
vsie_page - > gvrd_gpa = 0 ;
2015-11-25 11:08:32 +01:00
scb_s - > gvrd = 0 ;
}
2016-01-26 12:51:06 +01:00
hpa = scb_s - > riccbd ;
if ( hpa ) {
2018-01-16 18:15:26 +01:00
unpin_guest_page ( vcpu - > kvm , vsie_page - > riccbd_gpa , hpa ) ;
vsie_page - > riccbd_gpa = 0 ;
2016-01-26 12:51:06 +01:00
scb_s - > riccbd = 0 ;
}
2016-11-29 07:17:55 +01:00
hpa = scb_s - > sdnxo ;
if ( hpa ) {
2018-01-16 18:15:26 +01:00
unpin_guest_page ( vcpu - > kvm , vsie_page - > sdnx_gpa , hpa ) ;
vsie_page - > sdnx_gpa = 0 ;
2016-11-29 07:17:55 +01:00
scb_s - > sdnxo = 0 ;
}
2015-07-08 13:19:48 +02:00
}
/*
* Instead of shadowing some blocks , we can simply forward them because the
* addresses in the scb are 64 bit long .
*
* This works as long as the data lies in one page . If blocks ever exceed one
* page , we have to fall back to shadowing .
*
* As we reuse the sca , the vcpu pointers contained in it are invalid . We must
* therefore not enable any facilities that access these pointers ( e . g . SIGPIF ) .
*
* Returns : - 0 if all blocks were pinned .
* - > 0 if control has to be given to guest 2
* - - ENOMEM if out of memory
*/
static int pin_blocks ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_o = vsie_page - > scb_o ;
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
hpa_t hpa ;
gpa_t gpa ;
int rc = 0 ;
2018-01-16 18:15:25 +01:00
gpa = READ_ONCE ( scb_o - > scaol ) & ~ 0xfUL ;
2015-11-25 11:02:26 +01:00
if ( test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_64BSCAO ) )
2018-01-16 18:15:25 +01:00
gpa | = ( u64 ) READ_ONCE ( scb_o - > scaoh ) < < 32 ;
2015-07-08 13:19:48 +02:00
if ( gpa ) {
2018-05-09 16:12:18 +02:00
if ( gpa < 2 * PAGE_SIZE )
2015-07-08 13:19:48 +02:00
rc = set_validity_icpt ( scb_s , 0x0038U ) ;
else if ( ( gpa & ~ 0x1fffUL ) = = kvm_s390_get_prefix ( vcpu ) )
rc = set_validity_icpt ( scb_s , 0x0011U ) ;
else if ( ( gpa & PAGE_MASK ) ! =
( ( gpa + sizeof ( struct bsca_block ) - 1 ) & PAGE_MASK ) )
rc = set_validity_icpt ( scb_s , 0x003bU ) ;
if ( ! rc ) {
rc = pin_guest_page ( vcpu - > kvm , gpa , & hpa ) ;
2017-09-01 17:11:43 +02:00
if ( rc )
2015-07-08 13:19:48 +02:00
rc = set_validity_icpt ( scb_s , 0x0034U ) ;
}
if ( rc )
goto unpin ;
2018-01-16 18:15:26 +01:00
vsie_page - > sca_gpa = gpa ;
2015-07-08 13:19:48 +02:00
scb_s - > scaoh = ( u32 ) ( ( u64 ) hpa > > 32 ) ;
scb_s - > scaol = ( u32 ) ( u64 ) hpa ;
}
2015-11-25 11:13:32 +01:00
2018-01-16 18:15:25 +01:00
gpa = READ_ONCE ( scb_o - > itdba ) & ~ 0xffUL ;
2017-03-13 11:48:28 +01:00
if ( gpa & & ( scb_s - > ecb & ECB_TE ) ) {
2018-05-09 16:12:18 +02:00
if ( gpa < 2 * PAGE_SIZE ) {
2015-11-25 11:13:32 +01:00
rc = set_validity_icpt ( scb_s , 0x0080U ) ;
goto unpin ;
}
/* 256 bytes cannot cross page boundaries */
rc = pin_guest_page ( vcpu - > kvm , gpa , & hpa ) ;
2017-09-01 17:11:43 +02:00
if ( rc ) {
2015-11-25 11:13:32 +01:00
rc = set_validity_icpt ( scb_s , 0x0080U ) ;
goto unpin ;
2017-09-01 17:11:43 +02:00
}
2018-01-16 18:15:26 +01:00
vsie_page - > itdba_gpa = gpa ;
2015-11-25 11:13:32 +01:00
scb_s - > itdba = hpa ;
}
2015-11-25 11:08:32 +01:00
2018-01-16 18:15:25 +01:00
gpa = READ_ONCE ( scb_o - > gvrd ) & ~ 0x1ffUL ;
2017-03-13 11:48:28 +01:00
if ( gpa & & ( scb_s - > eca & ECA_VX ) & & ! ( scb_s - > ecd & ECD_HOSTREGMGMT ) ) {
2018-05-09 16:12:18 +02:00
if ( gpa < 2 * PAGE_SIZE ) {
2015-11-25 11:08:32 +01:00
rc = set_validity_icpt ( scb_s , 0x1310U ) ;
goto unpin ;
}
/*
* 512 bytes vector registers cannot cross page boundaries
* if this block gets bigger , we have to shadow it .
*/
rc = pin_guest_page ( vcpu - > kvm , gpa , & hpa ) ;
2017-09-01 17:11:43 +02:00
if ( rc ) {
2015-11-25 11:08:32 +01:00
rc = set_validity_icpt ( scb_s , 0x1310U ) ;
goto unpin ;
2017-09-01 17:11:43 +02:00
}
2018-01-16 18:15:26 +01:00
vsie_page - > gvrd_gpa = gpa ;
2015-11-25 11:08:32 +01:00
scb_s - > gvrd = hpa ;
}
2016-01-26 12:51:06 +01:00
2018-01-16 18:15:25 +01:00
gpa = READ_ONCE ( scb_o - > riccbd ) & ~ 0x3fUL ;
2017-03-13 11:48:28 +01:00
if ( gpa & & ( scb_s - > ecb3 & ECB3_RI ) ) {
2018-05-09 16:12:18 +02:00
if ( gpa < 2 * PAGE_SIZE ) {
2016-01-26 12:51:06 +01:00
rc = set_validity_icpt ( scb_s , 0x0043U ) ;
goto unpin ;
}
/* 64 bytes cannot cross page boundaries */
rc = pin_guest_page ( vcpu - > kvm , gpa , & hpa ) ;
2017-09-01 17:11:43 +02:00
if ( rc ) {
2016-01-26 12:51:06 +01:00
rc = set_validity_icpt ( scb_s , 0x0043U ) ;
goto unpin ;
2017-09-01 17:11:43 +02:00
}
/* Validity 0x0044 will be checked by SIE */
2018-01-16 18:15:26 +01:00
vsie_page - > riccbd_gpa = gpa ;
2016-09-02 12:33:49 +02:00
scb_s - > riccbd = hpa ;
2016-01-26 12:51:06 +01:00
}
2018-03-08 16:08:49 +00:00
if ( ( ( scb_s - > ecb & ECB_GS ) & & ! ( scb_s - > ecd & ECD_HOSTREGMGMT ) ) | |
( scb_s - > ecd & ECD_ETOKENF ) ) {
2016-11-29 07:17:55 +01:00
unsigned long sdnxc ;
2018-01-16 18:15:25 +01:00
gpa = READ_ONCE ( scb_o - > sdnxo ) & ~ 0xfUL ;
sdnxc = READ_ONCE ( scb_o - > sdnxo ) & 0xfUL ;
2018-05-09 16:12:18 +02:00
if ( ! gpa | | gpa < 2 * PAGE_SIZE ) {
2016-11-29 07:17:55 +01:00
rc = set_validity_icpt ( scb_s , 0x10b0U ) ;
goto unpin ;
}
if ( sdnxc < 6 | | sdnxc > 12 ) {
rc = set_validity_icpt ( scb_s , 0x10b1U ) ;
goto unpin ;
}
if ( gpa & ( ( 1 < < sdnxc ) - 1 ) ) {
rc = set_validity_icpt ( scb_s , 0x10b2U ) ;
goto unpin ;
}
/* Due to alignment rules (checked above) this cannot
* cross page boundaries
*/
rc = pin_guest_page ( vcpu - > kvm , gpa , & hpa ) ;
2017-09-01 17:11:43 +02:00
if ( rc ) {
2016-11-29 07:17:55 +01:00
rc = set_validity_icpt ( scb_s , 0x10b0U ) ;
goto unpin ;
2017-09-01 17:11:43 +02:00
}
2018-01-16 18:15:26 +01:00
vsie_page - > sdnx_gpa = gpa ;
2017-04-07 14:23:13 +02:00
scb_s - > sdnxo = hpa | sdnxc ;
2016-11-29 07:17:55 +01:00
}
2015-07-08 13:19:48 +02:00
return 0 ;
unpin :
unpin_blocks ( vcpu , vsie_page ) ;
return rc ;
}
/* unpin the scb provided by guest 2, marking it as dirty */
static void unpin_scb ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page ,
gpa_t gpa )
{
hpa_t hpa = ( hpa_t ) vsie_page - > scb_o ;
if ( hpa )
unpin_guest_page ( vcpu - > kvm , gpa , hpa ) ;
vsie_page - > scb_o = NULL ;
}
/*
* Pin the scb at gpa provided by guest 2 at vsie_page - > scb_o .
*
* Returns : - 0 if the scb was pinned .
* - > 0 if control has to be given to guest 2
*/
static int pin_scb ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page ,
gpa_t gpa )
{
hpa_t hpa ;
int rc ;
rc = pin_guest_page ( vcpu - > kvm , gpa , & hpa ) ;
2017-09-01 17:11:43 +02:00
if ( rc ) {
2015-07-08 13:19:48 +02:00
rc = kvm_s390_inject_program_int ( vcpu , PGM_ADDRESSING ) ;
2017-09-01 17:11:43 +02:00
WARN_ON_ONCE ( rc ) ;
return 1 ;
2015-07-08 13:19:48 +02:00
}
2017-09-01 17:11:43 +02:00
vsie_page - > scb_o = ( struct kvm_s390_sie_block * ) hpa ;
return 0 ;
2015-07-08 13:19:48 +02:00
}
/*
* Inject a fault into guest 2.
*
* Returns : - > 0 if control has to be given to guest 2
* < 0 if an error occurred during injection .
*/
static int inject_fault ( struct kvm_vcpu * vcpu , __u16 code , __u64 vaddr ,
bool write_flag )
{
struct kvm_s390_pgm_info pgm = {
. code = code ,
. trans_exc_code =
/* 0-51: virtual address */
( vaddr & 0xfffffffffffff000UL ) |
/* 52-53: store / fetch */
( ( ( unsigned int ) ! write_flag ) + 1 ) < < 10 ,
/* 62-63: asce id (alway primary == 0) */
. exc_access_id = 0 , /* always primary */
. op_access_id = 0 , /* not MVPG */
} ;
int rc ;
if ( code = = PGM_PROTECTION )
pgm . trans_exc_code | = 0x4UL ;
rc = kvm_s390_inject_prog_irq ( vcpu , & pgm ) ;
return rc ? rc : 1 ;
}
/*
* Handle a fault during vsie execution on a gmap shadow .
*
* Returns : - 0 if the fault was resolved
* - > 0 if control has to be given to guest 2
* - < 0 if an error occurred
*/
static int handle_fault ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
int rc ;
if ( current - > thread . gmap_int_code = = PGM_PROTECTION )
/* we can directly forward all protection exceptions */
return inject_fault ( vcpu , PGM_PROTECTION ,
current - > thread . gmap_addr , 1 ) ;
rc = kvm_s390_shadow_fault ( vcpu , vsie_page - > gmap ,
current - > thread . gmap_addr ) ;
if ( rc > 0 ) {
rc = inject_fault ( vcpu , rc ,
current - > thread . gmap_addr ,
current - > thread . gmap_write_flag ) ;
2015-07-08 13:25:31 +02:00
if ( rc > = 0 )
vsie_page - > fault_addr = current - > thread . gmap_addr ;
2015-07-08 13:19:48 +02:00
}
return rc ;
}
2015-07-08 13:25:31 +02:00
/*
* Retry the previous fault that required guest 2 intervention . This avoids
* one superfluous SIE re - entry and direct exit .
*
* Will ignore any errors . The next SIE fault will do proper fault handling .
*/
static void handle_last_fault ( struct kvm_vcpu * vcpu ,
struct vsie_page * vsie_page )
{
if ( vsie_page - > fault_addr )
kvm_s390_shadow_fault ( vcpu , vsie_page - > gmap ,
vsie_page - > fault_addr ) ;
vsie_page - > fault_addr = 0 ;
}
2015-07-08 13:19:48 +02:00
static inline void clear_vsie_icpt ( struct vsie_page * vsie_page )
{
vsie_page - > scb_s . icptcode = 0 ;
}
2015-11-26 14:11:19 +01:00
/* rewind the psw and clear the vsie icpt, so we can retry execution */
static void retry_vsie_icpt ( struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
int ilen = insn_length ( scb_s - > ipa > > 8 ) ;
/* take care of EXECUTE instructions */
if ( scb_s - > icptstatus & 1 ) {
ilen = ( scb_s - > icptstatus > > 4 ) & 0x6 ;
if ( ! ilen )
ilen = 4 ;
}
scb_s - > gpsw . addr = __rewind_psw ( scb_s - > gpsw , ilen ) ;
clear_vsie_icpt ( vsie_page ) ;
}
/*
* Try to shadow + enable the guest 2 provided facility list .
* Retry instruction execution if enabled for and provided by guest 2.
*
* Returns : - 0 if handled ( retry or guest 2 icpt )
* - > 0 if control has to be given to guest 2
*/
static int handle_stfle ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
2018-01-16 18:15:25 +01:00
__u32 fac = READ_ONCE ( vsie_page - > scb_o - > fac ) & 0x7ffffff8U ;
2015-11-26 14:11:19 +01:00
if ( fac & & test_kvm_facility ( vcpu - > kvm , 7 ) ) {
retry_vsie_icpt ( vsie_page ) ;
if ( read_guest_real ( vcpu , fac , & vsie_page - > fac ,
sizeof ( vsie_page - > fac ) ) )
return set_validity_icpt ( scb_s , 0x1090U ) ;
scb_s - > fac = ( __u32 ) ( __u64 ) & vsie_page - > fac ;
}
return 0 ;
}
2015-07-08 13:19:48 +02:00
/*
* Run the vsie on a shadow scb and a shadow gmap , without any further
* sanity checks , handling SIE faults .
*
* Returns : - 0 everything went fine
* - > 0 if control has to be given to guest 2
* - < 0 if an error occurred
*/
static int do_vsie_run ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
2018-07-16 10:34:28 +02:00
__releases ( vcpu - > kvm - > srcu )
__acquires ( vcpu - > kvm - > srcu )
2015-07-08 13:19:48 +02:00
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
struct kvm_s390_sie_block * scb_o = vsie_page - > scb_o ;
2018-02-13 13:55:49 +00:00
int guest_bp_isolation ;
2018-09-25 19:16:16 -04:00
int rc = 0 ;
2015-07-08 13:19:48 +02:00
2015-07-08 13:25:31 +02:00
handle_last_fault ( vcpu , vsie_page ) ;
2015-07-08 13:19:48 +02:00
srcu_read_unlock ( & vcpu - > kvm - > srcu , vcpu - > srcu_idx ) ;
2018-02-13 13:55:49 +00:00
/* save current guest state of bp isolation override */
guest_bp_isolation = test_thread_flag ( TIF_ISOLATE_BP_GUEST ) ;
/*
* The guest is running with BPBC , so we have to force it on for our
* nested guest . This is done by enabling BPBC globally , so the BPBC
* control in the SCB ( which the nested guest can modify ) is simply
* ignored .
*/
if ( test_kvm_facility ( vcpu - > kvm , 82 ) & &
vcpu - > arch . sie_block - > fpf & FPF_BPBC )
set_thread_flag ( TIF_ISOLATE_BP_GUEST ) ;
2015-07-08 13:19:48 +02:00
local_irq_disable ( ) ;
2016-06-15 15:18:26 +02:00
guest_enter_irqoff ( ) ;
2015-07-08 13:19:48 +02:00
local_irq_enable ( ) ;
2018-09-25 19:16:16 -04:00
/*
* Simulate a SIE entry of the VCPU ( see sie64a ) , so VCPU blocking
* and VCPU requests also hinder the vSIE from running and lead
* to an immediate exit . kvm_s390_vsie_kick ( ) has to be used to
* also kick the vSIE .
*/
vcpu - > arch . sie_block - > prog0c | = PROG_IN_SIE ;
barrier ( ) ;
if ( ! kvm_s390_vcpu_sie_inhibited ( vcpu ) )
rc = sie64a ( scb_s , vcpu - > run - > s . regs . gprs ) ;
barrier ( ) ;
vcpu - > arch . sie_block - > prog0c & = ~ PROG_IN_SIE ;
2015-07-08 13:19:48 +02:00
local_irq_disable ( ) ;
2016-06-15 15:18:26 +02:00
guest_exit_irqoff ( ) ;
2015-07-08 13:19:48 +02:00
local_irq_enable ( ) ;
2018-02-13 13:55:49 +00:00
/* restore guest state for bp isolation override */
if ( ! guest_bp_isolation )
clear_thread_flag ( TIF_ISOLATE_BP_GUEST ) ;
2015-07-08 13:19:48 +02:00
vcpu - > srcu_idx = srcu_read_lock ( & vcpu - > kvm - > srcu ) ;
2017-06-07 12:11:18 +02:00
if ( rc = = - EINTR ) {
VCPU_EVENT ( vcpu , 3 , " %s " , " machine check " ) ;
2017-08-30 18:06:02 +02:00
kvm_s390_reinject_machine_check ( vcpu , & vsie_page - > mcck_info ) ;
2017-06-07 12:11:18 +02:00
return 0 ;
}
2015-07-08 13:19:48 +02:00
if ( rc > 0 )
rc = 0 ; /* we could still have an icpt */
else if ( rc = = - EFAULT )
return handle_fault ( vcpu , vsie_page ) ;
switch ( scb_s - > icptcode ) {
2015-11-26 14:11:19 +01:00
case ICPT_INST :
if ( scb_s - > ipa = = 0xb2b0 )
rc = handle_stfle ( vcpu , vsie_page ) ;
break ;
2015-07-08 13:19:48 +02:00
case ICPT_STOP :
/* stop not requested by g2 - must have been a kick */
if ( ! ( atomic_read ( & scb_o - > cpuflags ) & CPUSTAT_STOP_INT ) )
clear_vsie_icpt ( vsie_page ) ;
break ;
case ICPT_VALIDITY :
if ( ( scb_s - > ipa & 0xf000 ) ! = 0xf000 )
scb_s - > ipa + = 0x1000 ;
break ;
}
return rc ;
}
static void release_gmap_shadow ( struct vsie_page * vsie_page )
{
if ( vsie_page - > gmap )
gmap_put ( vsie_page - > gmap ) ;
WRITE_ONCE ( vsie_page - > gmap , NULL ) ;
2016-04-22 13:50:09 +02:00
prefix_unmapped ( vsie_page ) ;
2015-07-08 13:19:48 +02:00
}
static int acquire_gmap_shadow ( struct kvm_vcpu * vcpu ,
struct vsie_page * vsie_page )
{
unsigned long asce ;
union ctlreg0 cr0 ;
struct gmap * gmap ;
int edat ;
asce = vcpu - > arch . sie_block - > gcr [ 1 ] ;
cr0 . val = vcpu - > arch . sie_block - > gcr [ 0 ] ;
edat = cr0 . edat & & test_kvm_facility ( vcpu - > kvm , 8 ) ;
edat + = edat & & test_kvm_facility ( vcpu - > kvm , 78 ) ;
2016-04-22 13:50:09 +02:00
/*
* ASCE or EDAT could have changed since last icpt , or the gmap
* we ' re holding has been unshadowed . If the gmap is still valid ,
* we can safely reuse it .
*/
if ( vsie_page - > gmap & & gmap_shadow_valid ( vsie_page - > gmap , asce , edat ) )
return 0 ;
/* release the old shadow - if any, and mark the prefix as unmapped */
release_gmap_shadow ( vsie_page ) ;
2015-07-08 13:19:48 +02:00
gmap = gmap_shadow ( vcpu - > arch . gmap , asce , edat ) ;
if ( IS_ERR ( gmap ) )
return PTR_ERR ( gmap ) ;
gmap - > private = vcpu - > kvm ;
WRITE_ONCE ( vsie_page - > gmap , gmap ) ;
return 0 ;
}
2016-05-27 22:03:52 +02:00
/*
* Register the shadow scb at the VCPU , e . g . for kicking out of vsie .
*/
static void register_shadow_scb ( struct kvm_vcpu * vcpu ,
struct vsie_page * vsie_page )
{
2015-10-29 10:30:36 +01:00
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
2016-05-27 22:03:52 +02:00
WRITE_ONCE ( vcpu - > arch . vsie_block , & vsie_page - > scb_s ) ;
2015-07-07 20:39:35 +02:00
/*
* External calls have to lead to a kick of the vcpu and
* therefore the vsie - > Simulate Wait state .
*/
2018-01-23 18:05:29 +01:00
kvm_s390_set_cpuflags ( vcpu , CPUSTAT_WAIT ) ;
2015-10-29 10:30:36 +01:00
/*
* We have to adjust the g3 epoch by the g2 epoch . The epoch will
* automatically be adjusted on tod clock changes via kvm_sync_clock .
*/
preempt_disable ( ) ;
scb_s - > epoch + = vcpu - > kvm - > arch . epoch ;
2016-07-26 15:29:44 -04:00
if ( scb_s - > ecd & ECD_MEF ) {
scb_s - > epdx + = vcpu - > kvm - > arch . epdx ;
if ( scb_s - > epoch < vcpu - > kvm - > arch . epoch )
scb_s - > epdx + = 1 ;
}
2015-10-29 10:30:36 +01:00
preempt_enable ( ) ;
2016-05-27 22:03:52 +02:00
}
/*
* Unregister a shadow scb from a VCPU .
*/
static void unregister_shadow_scb ( struct kvm_vcpu * vcpu )
{
2018-01-23 18:05:30 +01:00
kvm_s390_clear_cpuflags ( vcpu , CPUSTAT_WAIT ) ;
2016-05-27 22:03:52 +02:00
WRITE_ONCE ( vcpu - > arch . vsie_block , NULL ) ;
}
2015-07-08 13:19:48 +02:00
/*
* Run the vsie on a shadowed scb , managing the gmap shadow , handling
* prefix pages and faults .
*
* Returns : - 0 if no errors occurred
* - > 0 if control has to be given to guest 2
* - - ENOMEM if out of memory
*/
static int vsie_run ( struct kvm_vcpu * vcpu , struct vsie_page * vsie_page )
{
struct kvm_s390_sie_block * scb_s = & vsie_page - > scb_s ;
int rc = 0 ;
while ( 1 ) {
rc = acquire_gmap_shadow ( vcpu , vsie_page ) ;
if ( ! rc )
rc = map_prefix ( vcpu , vsie_page ) ;
if ( ! rc ) {
gmap_enable ( vsie_page - > gmap ) ;
update_intervention_requests ( vsie_page ) ;
rc = do_vsie_run ( vcpu , vsie_page ) ;
gmap_enable ( vcpu - > arch . gmap ) ;
}
2016-05-27 22:03:52 +02:00
atomic_andnot ( PROG_BLOCK_SIE , & scb_s - > prog20 ) ;
2015-07-08 13:19:48 +02:00
if ( rc = = - EAGAIN )
rc = 0 ;
if ( rc | | scb_s - > icptcode | | signal_pending ( current ) | |
2018-09-25 19:16:16 -04:00
kvm_s390_vcpu_has_irq ( vcpu , 0 ) | |
kvm_s390_vcpu_sie_inhibited ( vcpu ) )
2015-07-08 13:19:48 +02:00
break ;
2020-04-03 17:30:49 +02:00
cond_resched ( ) ;
2017-01-02 08:51:02 +01:00
}
2015-07-08 13:19:48 +02:00
if ( rc = = - EFAULT ) {
/*
* Addressing exceptions are always presentes as intercepts .
* As addressing exceptions are suppressing and our guest 3 PSW
* points at the responsible instruction , we have to
* forward the PSW and set the ilc . If we can ' t read guest 3
* instruction , we can use an arbitrary ilc . Let ' s always use
* ilen = 4 for now , so we can avoid reading in guest 3 virtual
* memory . ( we could also fake the shadow so the hardware
* handles it ) .
*/
scb_s - > icptcode = ICPT_PROGI ;
scb_s - > iprcc = PGM_ADDRESSING ;
scb_s - > pgmilc = 4 ;
scb_s - > gpsw . addr = __rewind_psw ( scb_s - > gpsw , 4 ) ;
2020-04-03 17:30:47 +02:00
rc = 1 ;
2015-07-08 13:19:48 +02:00
}
return rc ;
}
/*
* Get or create a vsie page for a scb address .
*
* Returns : - address of a vsie page ( cached or new one )
* - NULL if the same scb address is already used by another VCPU
* - ERR_PTR ( - ENOMEM ) if out of memory
*/
static struct vsie_page * get_vsie_page ( struct kvm * kvm , unsigned long addr )
{
struct vsie_page * vsie_page ;
struct page * page ;
int nr_vcpus ;
rcu_read_lock ( ) ;
page = radix_tree_lookup ( & kvm - > arch . vsie . addr_to_page , addr > > 9 ) ;
rcu_read_unlock ( ) ;
if ( page ) {
if ( page_ref_inc_return ( page ) = = 2 )
return page_to_virt ( page ) ;
page_ref_dec ( page ) ;
}
/*
* We want at least # online_vcpus shadows , so every VCPU can execute
* the VSIE in parallel .
*/
nr_vcpus = atomic_read ( & kvm - > online_vcpus ) ;
mutex_lock ( & kvm - > arch . vsie . mutex ) ;
if ( kvm - > arch . vsie . page_count < nr_vcpus ) {
2015-11-26 14:11:19 +01:00
page = alloc_page ( GFP_KERNEL | __GFP_ZERO | GFP_DMA ) ;
2015-07-08 13:19:48 +02:00
if ( ! page ) {
mutex_unlock ( & kvm - > arch . vsie . mutex ) ;
return ERR_PTR ( - ENOMEM ) ;
}
page_ref_inc ( page ) ;
kvm - > arch . vsie . pages [ kvm - > arch . vsie . page_count ] = page ;
kvm - > arch . vsie . page_count + + ;
} else {
/* reuse an existing entry that belongs to nobody */
while ( true ) {
page = kvm - > arch . vsie . pages [ kvm - > arch . vsie . next ] ;
if ( page_ref_inc_return ( page ) = = 2 )
break ;
page_ref_dec ( page ) ;
kvm - > arch . vsie . next + + ;
kvm - > arch . vsie . next % = nr_vcpus ;
}
radix_tree_delete ( & kvm - > arch . vsie . addr_to_page , page - > index > > 9 ) ;
}
page - > index = addr ;
/* double use of the same address */
if ( radix_tree_insert ( & kvm - > arch . vsie . addr_to_page , addr > > 9 , page ) ) {
page_ref_dec ( page ) ;
mutex_unlock ( & kvm - > arch . vsie . mutex ) ;
return NULL ;
}
mutex_unlock ( & kvm - > arch . vsie . mutex ) ;
vsie_page = page_to_virt ( page ) ;
memset ( & vsie_page - > scb_s , 0 , sizeof ( struct kvm_s390_sie_block ) ) ;
2016-04-22 13:50:09 +02:00
release_gmap_shadow ( vsie_page ) ;
2015-07-08 13:25:31 +02:00
vsie_page - > fault_addr = 0 ;
2015-07-08 13:19:48 +02:00
vsie_page - > scb_s . ihcpu = 0xffffU ;
return vsie_page ;
}
/* put a vsie page acquired via get_vsie_page */
static void put_vsie_page ( struct kvm * kvm , struct vsie_page * vsie_page )
{
struct page * page = pfn_to_page ( __pa ( vsie_page ) > > PAGE_SHIFT ) ;
page_ref_dec ( page ) ;
}
int kvm_s390_handle_vsie ( struct kvm_vcpu * vcpu )
{
struct vsie_page * vsie_page ;
unsigned long scb_addr ;
int rc ;
vcpu - > stat . instruction_sie + + ;
if ( ! test_kvm_cpu_feat ( vcpu - > kvm , KVM_S390_VM_CPU_FEAT_SIEF2 ) )
return - EOPNOTSUPP ;
if ( vcpu - > arch . sie_block - > gpsw . mask & PSW_MASK_PSTATE )
return kvm_s390_inject_program_int ( vcpu , PGM_PRIVILEGED_OP ) ;
2017-07-05 07:37:14 +02:00
BUILD_BUG_ON ( sizeof ( struct vsie_page ) ! = PAGE_SIZE ) ;
2015-07-08 13:19:48 +02:00
scb_addr = kvm_s390_get_base_disp_s ( vcpu , NULL ) ;
/* 512 byte alignment */
if ( unlikely ( scb_addr & 0x1ffUL ) )
return kvm_s390_inject_program_int ( vcpu , PGM_SPECIFICATION ) ;
2018-09-25 19:16:16 -04:00
if ( signal_pending ( current ) | | kvm_s390_vcpu_has_irq ( vcpu , 0 ) | |
kvm_s390_vcpu_sie_inhibited ( vcpu ) )
2015-07-08 13:19:48 +02:00
return 0 ;
vsie_page = get_vsie_page ( vcpu - > kvm , scb_addr ) ;
if ( IS_ERR ( vsie_page ) )
return PTR_ERR ( vsie_page ) ;
else if ( ! vsie_page )
/* double use of sie control block - simply do nothing */
return 0 ;
rc = pin_scb ( vcpu , vsie_page , scb_addr ) ;
if ( rc )
goto out_put ;
rc = shadow_scb ( vcpu , vsie_page ) ;
if ( rc )
goto out_unpin_scb ;
rc = pin_blocks ( vcpu , vsie_page ) ;
if ( rc )
goto out_unshadow ;
2016-05-27 22:03:52 +02:00
register_shadow_scb ( vcpu , vsie_page ) ;
2015-07-08 13:19:48 +02:00
rc = vsie_run ( vcpu , vsie_page ) ;
2016-05-27 22:03:52 +02:00
unregister_shadow_scb ( vcpu ) ;
2015-07-08 13:19:48 +02:00
unpin_blocks ( vcpu , vsie_page ) ;
out_unshadow :
unshadow_scb ( vcpu , vsie_page ) ;
out_unpin_scb :
unpin_scb ( vcpu , vsie_page , scb_addr ) ;
out_put :
put_vsie_page ( vcpu - > kvm , vsie_page ) ;
return rc < 0 ? rc : 0 ;
}
/* Init the vsie data structures. To be called when a vm is initialized. */
void kvm_s390_vsie_init ( struct kvm * kvm )
{
mutex_init ( & kvm - > arch . vsie . mutex ) ;
INIT_RADIX_TREE ( & kvm - > arch . vsie . addr_to_page , GFP_KERNEL ) ;
}
/* Destroy the vsie data structures. To be called when a vm is destroyed. */
void kvm_s390_vsie_destroy ( struct kvm * kvm )
{
2016-04-22 13:50:09 +02:00
struct vsie_page * vsie_page ;
2015-07-08 13:19:48 +02:00
struct page * page ;
int i ;
mutex_lock ( & kvm - > arch . vsie . mutex ) ;
for ( i = 0 ; i < kvm - > arch . vsie . page_count ; i + + ) {
page = kvm - > arch . vsie . pages [ i ] ;
kvm - > arch . vsie . pages [ i ] = NULL ;
2016-04-22 13:50:09 +02:00
vsie_page = page_to_virt ( page ) ;
release_gmap_shadow ( vsie_page ) ;
2015-07-08 13:19:48 +02:00
/* free the radix tree entry */
radix_tree_delete ( & kvm - > arch . vsie . addr_to_page , page - > index > > 9 ) ;
__free_page ( page ) ;
}
kvm - > arch . vsie . page_count = 0 ;
mutex_unlock ( & kvm - > arch . vsie . mutex ) ;
}
2016-05-27 22:03:52 +02:00
void kvm_s390_vsie_kick ( struct kvm_vcpu * vcpu )
{
struct kvm_s390_sie_block * scb = READ_ONCE ( vcpu - > arch . vsie_block ) ;
/*
* Even if the VCPU lets go of the shadow sie block reference , it is
* still valid in the cache . So we can safely kick it .
*/
if ( scb ) {
atomic_or ( PROG_BLOCK_SIE , & scb - > prog20 ) ;
if ( scb - > prog0c & PROG_IN_SIE )
atomic_or ( CPUSTAT_STOP_INT , & scb - > cpuflags ) ;
}
}