Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: s390: expose no-DAT to guest and migration support

The STFLE bit 147 indicates whether the ESSA no-DAT operation code is
valid, the bit is not normally provided to the host; the host is
instead provided with an SCLP bit that indicates whether guests can
support the feature.

This patch:
* enables the STFLE bit in the guest if the corresponding SCLP bit is
present in the host.
* adds support for migrating the no-DAT bit in the PGSTEs
* fixes the software interpretation of the ESSA instruction that is
used when migrating, both for the new operation code and for the old
"set stable", as per specifications.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>

authored by

Claudio Imbrenda and committed by
Christian Borntraeger
1bab1c02 631aebfe

+17 -5
+1 -1
arch/s390/include/asm/page-states.h
··· 15 15 #define ESSA_SET_STABLE_IF_RESIDENT 6 16 16 #define ESSA_SET_STABLE_NODAT 7 17 17 18 - #define ESSA_MAX ESSA_SET_STABLE_IF_RESIDENT 18 + #define ESSA_MAX ESSA_SET_STABLE_NODAT 19 19 20 20 #endif
+6 -2
arch/s390/kvm/kvm-s390.c
··· 1574 1574 if (r < 0) 1575 1575 pgstev = 0; 1576 1576 /* save the value */ 1577 - res[i++] = (pgstev >> 24) & 0x3; 1577 + res[i++] = (pgstev >> 24) & 0x43; 1578 1578 /* 1579 1579 * if the next bit is too far away, stop. 1580 1580 * if we reached the previous "next", find the next one ··· 1652 1652 1653 1653 pgstev = bits[i]; 1654 1654 pgstev = pgstev << 24; 1655 - mask &= _PGSTE_GPS_USAGE_MASK; 1655 + mask &= _PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT; 1656 1656 set_pgste_bits(kvm->mm, hva, mask, pgstev); 1657 1657 } 1658 1658 srcu_read_unlock(&kvm->srcu, srcu_idx); ··· 1929 1929 1930 1930 set_kvm_facility(kvm->arch.model.fac_mask, 74); 1931 1931 set_kvm_facility(kvm->arch.model.fac_list, 74); 1932 + if (MACHINE_HAS_TLB_GUEST) { 1933 + set_kvm_facility(kvm->arch.model.fac_mask, 147); 1934 + set_kvm_facility(kvm->arch.model.fac_list, 147); 1935 + } 1932 1936 1933 1937 kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid(); 1934 1938 kvm->arch.model.ibc = sclp.ibc & 0x0fff;
+5 -1
arch/s390/kvm/priv.c
··· 988 988 if (pgstev & _PGSTE_GPS_ZERO) 989 989 res |= 1; 990 990 } 991 + if (pgstev & _PGSTE_GPS_NODAT) 992 + res |= 0x20; 991 993 vcpu->run->s.regs.gprs[r1] = res; 992 994 /* 993 995 * It is possible that all the normal 511 slots were full, in which case ··· 1029 1027 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); 1030 1028 /* Check for invalid operation request code */ 1031 1029 orc = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28; 1032 - if (orc > ESSA_MAX) 1030 + /* ORCs 0-6 are always valid */ 1031 + if (orc > (test_kvm_facility(vcpu->kvm, 147) ? ESSA_SET_STABLE_NODAT 1032 + : ESSA_SET_STABLE_IF_RESIDENT)) 1033 1033 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 1034 1034 1035 1035 if (likely(!vcpu->kvm->arch.migration_state)) {
+5 -1
arch/s390/mm/pgtable.c
··· 919 919 case ESSA_GET_STATE: 920 920 break; 921 921 case ESSA_SET_STABLE: 922 - pgstev &= ~_PGSTE_GPS_USAGE_MASK; 922 + pgstev &= ~(_PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT); 923 923 pgstev |= _PGSTE_GPS_USAGE_STABLE; 924 924 break; 925 925 case ESSA_SET_UNUSED: ··· 964 964 pgstev &= ~_PGSTE_GPS_USAGE_MASK; 965 965 pgstev |= _PGSTE_GPS_USAGE_STABLE; 966 966 } 967 + break; 968 + case ESSA_SET_STABLE_NODAT: 969 + pgstev &= ~_PGSTE_GPS_USAGE_MASK; 970 + pgstev |= _PGSTE_GPS_USAGE_STABLE | _PGSTE_GPS_NODAT; 967 971 break; 968 972 default: 969 973 /* we should never get here! */