xref: /linux/arch/s390/kvm/gmap/dat.h (revision 67f8bc848ee31831336bd478e57d2f993551902e)
11b09c13cSSteffen Eiden /* SPDX-License-Identifier: GPL-2.0 */
21b09c13cSSteffen Eiden /*
31b09c13cSSteffen Eiden  *  KVM guest address space mapping code
41b09c13cSSteffen Eiden  *
51b09c13cSSteffen Eiden  *    Copyright IBM Corp. 2024, 2025
61b09c13cSSteffen Eiden  *    Author(s): Claudio Imbrenda <imbrenda@linux.ibm.com>
71b09c13cSSteffen Eiden  */
81b09c13cSSteffen Eiden 
91b09c13cSSteffen Eiden #ifndef ARCH_KVM_GMAP_DAT_H
101b09c13cSSteffen Eiden #define ARCH_KVM_GMAP_DAT_H
111b09c13cSSteffen Eiden 
12a07276d5SSteffen Eiden #include <linux/kvm_host.h>
131b09c13cSSteffen Eiden #include <linux/radix-tree.h>
141b09c13cSSteffen Eiden #include <linux/refcount.h>
151b09c13cSSteffen Eiden #include <linux/io.h>
161b09c13cSSteffen Eiden #include <linux/kvm_types.h>
171b09c13cSSteffen Eiden #include <linux/pgalloc.h>
181b09c13cSSteffen Eiden #include <asm/tlbflush.h>
191b09c13cSSteffen Eiden #include <asm/dat-bits.h>
201b09c13cSSteffen Eiden 
211b09c13cSSteffen Eiden /*
221b09c13cSSteffen Eiden  * Base address and length must be sent at the start of each block, therefore
231b09c13cSSteffen Eiden  * it's cheaper to send some clean data, as long as it's less than the size of
241b09c13cSSteffen Eiden  * two longs.
251b09c13cSSteffen Eiden  */
261b09c13cSSteffen Eiden #define KVM_S390_MAX_BIT_DISTANCE (2 * sizeof(void *))
271b09c13cSSteffen Eiden /* For consistency */
281b09c13cSSteffen Eiden #define KVM_S390_CMMA_SIZE_MAX ((u32)KVM_S390_SKEYS_MAX)
291b09c13cSSteffen Eiden 
301b09c13cSSteffen Eiden #define _ASCE(x) ((union asce) { .val = (x), })
311b09c13cSSteffen Eiden #define NULL_ASCE _ASCE(0)
321b09c13cSSteffen Eiden 
331b09c13cSSteffen Eiden enum {
341b09c13cSSteffen Eiden 	_DAT_TOKEN_NONE = 0,
351b09c13cSSteffen Eiden 	_DAT_TOKEN_PIC,
361b09c13cSSteffen Eiden };
371b09c13cSSteffen Eiden 
381b09c13cSSteffen Eiden #define _CRSTE_TOK(l, t, p) ((union crste) {	\
391b09c13cSSteffen Eiden 		.tok.i = 1,			\
401b09c13cSSteffen Eiden 		.tok.tt = (l),			\
411b09c13cSSteffen Eiden 		.tok.type = (t),		\
421b09c13cSSteffen Eiden 		.tok.par = (p)			\
431b09c13cSSteffen Eiden 	})
441b09c13cSSteffen Eiden #define _CRSTE_PIC(l, p) _CRSTE_TOK(l, _DAT_TOKEN_PIC, p)
451b09c13cSSteffen Eiden 
461b09c13cSSteffen Eiden #define _CRSTE_HOLE(l) _CRSTE_PIC(l, PGM_ADDRESSING)
471b09c13cSSteffen Eiden #define _CRSTE_EMPTY(l) _CRSTE_TOK(l, _DAT_TOKEN_NONE, 0)
481b09c13cSSteffen Eiden 
491b09c13cSSteffen Eiden #define _PMD_EMPTY _CRSTE_EMPTY(TABLE_TYPE_SEGMENT)
501b09c13cSSteffen Eiden 
511b09c13cSSteffen Eiden #define _PTE_TOK(t, p) ((union pte) { .tok.i = 1, .tok.type = (t), .tok.par = (p) })
521b09c13cSSteffen Eiden #define _PTE_EMPTY _PTE_TOK(_DAT_TOKEN_NONE, 0)
531b09c13cSSteffen Eiden 
541b09c13cSSteffen Eiden /* This fake table type is used for page table walks (both for normal page tables and vSIE) */
551b09c13cSSteffen Eiden #define TABLE_TYPE_PAGE_TABLE -1
561b09c13cSSteffen Eiden 
571b09c13cSSteffen Eiden enum dat_walk_flags {
581b09c13cSSteffen Eiden 	DAT_WALK_USES_SKEYS	= 0x40,
591b09c13cSSteffen Eiden 	DAT_WALK_CONTINUE	= 0x20,
601b09c13cSSteffen Eiden 	DAT_WALK_IGN_HOLES	= 0x10,
611b09c13cSSteffen Eiden 	DAT_WALK_SPLIT		= 0x08,
621b09c13cSSteffen Eiden 	DAT_WALK_ALLOC		= 0x04,
631b09c13cSSteffen Eiden 	DAT_WALK_ANY		= 0x02,
641b09c13cSSteffen Eiden 	DAT_WALK_LEAF		= 0x01,
651b09c13cSSteffen Eiden 	DAT_WALK_DEFAULT	= 0
661b09c13cSSteffen Eiden };
671b09c13cSSteffen Eiden 
681b09c13cSSteffen Eiden #define DAT_WALK_SPLIT_ALLOC (DAT_WALK_SPLIT | DAT_WALK_ALLOC)
691b09c13cSSteffen Eiden #define DAT_WALK_ALLOC_CONTINUE (DAT_WALK_CONTINUE | DAT_WALK_ALLOC)
701b09c13cSSteffen Eiden #define DAT_WALK_LEAF_ALLOC (DAT_WALK_LEAF | DAT_WALK_ALLOC)
711b09c13cSSteffen Eiden 
721b09c13cSSteffen Eiden union pte {
731b09c13cSSteffen Eiden 	unsigned long val;
741b09c13cSSteffen Eiden 	union page_table_entry h;
751b09c13cSSteffen Eiden 	struct {
761b09c13cSSteffen Eiden 		unsigned long   :56; /* Hardware bits */
771b09c13cSSteffen Eiden 		unsigned long u : 1; /* Page unused */
781b09c13cSSteffen Eiden 		unsigned long s : 1; /* Special */
791b09c13cSSteffen Eiden 		unsigned long w : 1; /* Writable */
801b09c13cSSteffen Eiden 		unsigned long r : 1; /* Readable */
811b09c13cSSteffen Eiden 		unsigned long d : 1; /* Dirty */
821b09c13cSSteffen Eiden 		unsigned long y : 1; /* Young */
831b09c13cSSteffen Eiden 		unsigned long sd: 1; /* Soft dirty */
841b09c13cSSteffen Eiden 		unsigned long pr: 1; /* Present */
851b09c13cSSteffen Eiden 	} s;
861b09c13cSSteffen Eiden 	struct {
871b09c13cSSteffen Eiden 		unsigned char hwbytes[7];
881b09c13cSSteffen Eiden 		unsigned char swbyte;
891b09c13cSSteffen Eiden 	};
901b09c13cSSteffen Eiden 	union {
911b09c13cSSteffen Eiden 		struct {
921b09c13cSSteffen Eiden 			unsigned long type :16; /* Token type */
931b09c13cSSteffen Eiden 			unsigned long par  :16; /* Token parameter */
941b09c13cSSteffen Eiden 			unsigned long      :20;
951b09c13cSSteffen Eiden 			unsigned long      : 1; /* Must be 0 */
961b09c13cSSteffen Eiden 			unsigned long i    : 1; /* Must be 1 */
971b09c13cSSteffen Eiden 			unsigned long      : 2;
981b09c13cSSteffen Eiden 			unsigned long      : 7;
991b09c13cSSteffen Eiden 			unsigned long pr   : 1; /* Must be 0 */
1001b09c13cSSteffen Eiden 		};
1011b09c13cSSteffen Eiden 		struct {
1021b09c13cSSteffen Eiden 			unsigned long token:32; /* Token and parameter */
1031b09c13cSSteffen Eiden 			unsigned long      :32;
1041b09c13cSSteffen Eiden 		};
1051b09c13cSSteffen Eiden 	} tok;
1061b09c13cSSteffen Eiden };
1071b09c13cSSteffen Eiden 
1081b09c13cSSteffen Eiden #define _SEGMENT_FR_MASK	(_SEGMENT_MASK >> PAGE_SHIFT)
1091b09c13cSSteffen Eiden #define _REGION3_FR_MASK	(_REGION3_MASK >> PAGE_SHIFT)
1101b09c13cSSteffen Eiden #define _PAGES_PER_SEGMENT	_PAGE_ENTRIES
1111b09c13cSSteffen Eiden #define _PAGES_PER_REGION3	(_PAGES_PER_SEGMENT * _CRST_ENTRIES)
1121b09c13cSSteffen Eiden 
1131b09c13cSSteffen Eiden /* Soft dirty, needed as macro for atomic operations on ptes */
1141b09c13cSSteffen Eiden #define _PAGE_SD 0x002
1151b09c13cSSteffen Eiden 
1161b09c13cSSteffen Eiden /* Needed as macro to perform atomic operations */
1171b09c13cSSteffen Eiden #define PGSTE_PCL_BIT		0x0080000000000000UL	/* PCL lock, HW bit */
1181b09c13cSSteffen Eiden #define PGSTE_CMMA_D_BIT	0x0000000000008000UL	/* CMMA dirty soft-bit */
1191b09c13cSSteffen Eiden 
1201b09c13cSSteffen Eiden enum pgste_gps_usage {
1211b09c13cSSteffen Eiden 	PGSTE_GPS_USAGE_STABLE = 0,
1221b09c13cSSteffen Eiden 	PGSTE_GPS_USAGE_UNUSED,
1231b09c13cSSteffen Eiden 	PGSTE_GPS_USAGE_POT_VOLATILE,
1241b09c13cSSteffen Eiden 	PGSTE_GPS_USAGE_VOLATILE,
1251b09c13cSSteffen Eiden };
1261b09c13cSSteffen Eiden 
1271b09c13cSSteffen Eiden union pgste {
1281b09c13cSSteffen Eiden 	unsigned long val;
1291b09c13cSSteffen Eiden 	struct {
1301b09c13cSSteffen Eiden 		unsigned long acc          : 4;
1311b09c13cSSteffen Eiden 		unsigned long fp           : 1;
1321b09c13cSSteffen Eiden 		unsigned long              : 3;
1331b09c13cSSteffen Eiden 		unsigned long pcl          : 1;
1341b09c13cSSteffen Eiden 		unsigned long hr           : 1;
1351b09c13cSSteffen Eiden 		unsigned long hc           : 1;
1361b09c13cSSteffen Eiden 		unsigned long              : 2;
1371b09c13cSSteffen Eiden 		unsigned long gr           : 1;
1381b09c13cSSteffen Eiden 		unsigned long gc           : 1;
1391b09c13cSSteffen Eiden 		unsigned long              : 1;
1401b09c13cSSteffen Eiden 		unsigned long              :16; /* val16 */
1411b09c13cSSteffen Eiden 		unsigned long zero         : 1;
1421b09c13cSSteffen Eiden 		unsigned long nodat        : 1;
1431b09c13cSSteffen Eiden 		unsigned long              : 4;
1441b09c13cSSteffen Eiden 		unsigned long usage        : 2;
1451b09c13cSSteffen Eiden 		unsigned long              : 8;
1461b09c13cSSteffen Eiden 		unsigned long cmma_d       : 1; /* Dirty flag for CMMA bits */
1471b09c13cSSteffen Eiden 		unsigned long prefix_notif : 1; /* Guest prefix invalidation notification */
1481b09c13cSSteffen Eiden 		unsigned long vsie_notif   : 1; /* Referenced in a shadow table */
1491b09c13cSSteffen Eiden 		unsigned long vsie_gmem    : 1; /* Contains nested guest memory */
1501b09c13cSSteffen Eiden 		unsigned long              : 4;
1511b09c13cSSteffen Eiden 		unsigned long              : 8;
1521b09c13cSSteffen Eiden 	};
1531b09c13cSSteffen Eiden 	struct {
1541b09c13cSSteffen Eiden 		unsigned short hwbytes0;
1551b09c13cSSteffen Eiden 		unsigned short val16;	/* Used to store chunked values, see dat_{s,g}et_ptval() */
1561b09c13cSSteffen Eiden 		unsigned short hwbytes4;
1571b09c13cSSteffen Eiden 		unsigned char flags;	/* Maps to the software bits */
1581b09c13cSSteffen Eiden 		unsigned char hwbyte7;
1591b09c13cSSteffen Eiden 	} __packed;
1601b09c13cSSteffen Eiden };
1611b09c13cSSteffen Eiden 
1621b09c13cSSteffen Eiden union pmd {
1631b09c13cSSteffen Eiden 	unsigned long val;
1641b09c13cSSteffen Eiden 	union segment_table_entry h;
1651b09c13cSSteffen Eiden 	struct {
1661b09c13cSSteffen Eiden 		struct {
1671b09c13cSSteffen Eiden 			unsigned long              :44; /* HW */
1681b09c13cSSteffen Eiden 			unsigned long              : 3; /* Unused */
1691b09c13cSSteffen Eiden 			unsigned long              : 1; /* HW */
1701b09c13cSSteffen Eiden 			unsigned long s            : 1; /* Special */
1711b09c13cSSteffen Eiden 			unsigned long w            : 1; /* Writable soft-bit */
1721b09c13cSSteffen Eiden 			unsigned long r            : 1; /* Readable soft-bit */
1731b09c13cSSteffen Eiden 			unsigned long d            : 1; /* Dirty */
1741b09c13cSSteffen Eiden 			unsigned long y            : 1; /* Young */
1751b09c13cSSteffen Eiden 			unsigned long              : 3; /* HW */
1761b09c13cSSteffen Eiden 			unsigned long prefix_notif : 1; /* Guest prefix invalidation notification */
1771b09c13cSSteffen Eiden 			unsigned long vsie_notif   : 1; /* Referenced in a shadow table */
1781b09c13cSSteffen Eiden 			unsigned long              : 4; /* HW */
1791b09c13cSSteffen Eiden 			unsigned long sd           : 1; /* Soft-Dirty */
1801b09c13cSSteffen Eiden 			unsigned long pr           : 1; /* Present */
1811b09c13cSSteffen Eiden 		} fc1;
1821b09c13cSSteffen Eiden 	} s;
1831b09c13cSSteffen Eiden };
1841b09c13cSSteffen Eiden 
1851b09c13cSSteffen Eiden union pud {
1861b09c13cSSteffen Eiden 	unsigned long val;
1871b09c13cSSteffen Eiden 	union region3_table_entry h;
1881b09c13cSSteffen Eiden 	struct {
1891b09c13cSSteffen Eiden 		struct {
1901b09c13cSSteffen Eiden 			unsigned long              :33; /* HW */
1911b09c13cSSteffen Eiden 			unsigned long              :14; /* Unused */
1921b09c13cSSteffen Eiden 			unsigned long              : 1; /* HW */
1931b09c13cSSteffen Eiden 			unsigned long s            : 1; /* Special */
1941b09c13cSSteffen Eiden 			unsigned long w            : 1; /* Writable soft-bit */
1951b09c13cSSteffen Eiden 			unsigned long r            : 1; /* Readable soft-bit */
1961b09c13cSSteffen Eiden 			unsigned long d            : 1; /* Dirty */
1971b09c13cSSteffen Eiden 			unsigned long y            : 1; /* Young */
1981b09c13cSSteffen Eiden 			unsigned long              : 3; /* HW */
1991b09c13cSSteffen Eiden 			unsigned long prefix_notif : 1; /* Guest prefix invalidation notification */
2001b09c13cSSteffen Eiden 			unsigned long vsie_notif   : 1; /* Referenced in a shadow table */
2011b09c13cSSteffen Eiden 			unsigned long              : 4; /* HW */
2021b09c13cSSteffen Eiden 			unsigned long sd           : 1; /* Soft-Dirty */
2031b09c13cSSteffen Eiden 			unsigned long pr           : 1; /* Present */
2041b09c13cSSteffen Eiden 		} fc1;
2051b09c13cSSteffen Eiden 	} s;
2061b09c13cSSteffen Eiden };
2071b09c13cSSteffen Eiden 
2081b09c13cSSteffen Eiden union p4d {
2091b09c13cSSteffen Eiden 	unsigned long val;
2101b09c13cSSteffen Eiden 	union region2_table_entry h;
2111b09c13cSSteffen Eiden };
2121b09c13cSSteffen Eiden 
2131b09c13cSSteffen Eiden union pgd {
2141b09c13cSSteffen Eiden 	unsigned long val;
2151b09c13cSSteffen Eiden 	union region1_table_entry h;
2161b09c13cSSteffen Eiden };
2171b09c13cSSteffen Eiden 
2181b09c13cSSteffen Eiden union crste {
2191b09c13cSSteffen Eiden 	unsigned long val;
2201b09c13cSSteffen Eiden 	union {
2211b09c13cSSteffen Eiden 		struct {
2221b09c13cSSteffen Eiden 			unsigned long   :52;
2231b09c13cSSteffen Eiden 			unsigned long   : 1;
2241b09c13cSSteffen Eiden 			unsigned long fc: 1;
2251b09c13cSSteffen Eiden 			unsigned long p : 1;
2261b09c13cSSteffen Eiden 			unsigned long   : 1;
2271b09c13cSSteffen Eiden 			unsigned long   : 2;
2281b09c13cSSteffen Eiden 			unsigned long i : 1;
2291b09c13cSSteffen Eiden 			unsigned long   : 1;
2301b09c13cSSteffen Eiden 			unsigned long tt: 2;
2311b09c13cSSteffen Eiden 			unsigned long   : 2;
2321b09c13cSSteffen Eiden 		};
2331b09c13cSSteffen Eiden 		struct {
2341b09c13cSSteffen Eiden 			unsigned long to:52;
2351b09c13cSSteffen Eiden 			unsigned long   : 1;
2361b09c13cSSteffen Eiden 			unsigned long fc: 1;
2371b09c13cSSteffen Eiden 			unsigned long p : 1;
2381b09c13cSSteffen Eiden 			unsigned long   : 1;
2391b09c13cSSteffen Eiden 			unsigned long tf: 2;
2401b09c13cSSteffen Eiden 			unsigned long i : 1;
2411b09c13cSSteffen Eiden 			unsigned long   : 1;
2421b09c13cSSteffen Eiden 			unsigned long tt: 2;
2431b09c13cSSteffen Eiden 			unsigned long tl: 2;
2441b09c13cSSteffen Eiden 		} fc0;
2451b09c13cSSteffen Eiden 		struct {
2461b09c13cSSteffen Eiden 			unsigned long    :47;
2471b09c13cSSteffen Eiden 			unsigned long av : 1; /* ACCF-Validity Control */
2481b09c13cSSteffen Eiden 			unsigned long acc: 4; /* Access-Control Bits */
2491b09c13cSSteffen Eiden 			unsigned long f  : 1; /* Fetch-Protection Bit */
2501b09c13cSSteffen Eiden 			unsigned long fc : 1; /* Format-Control */
2511b09c13cSSteffen Eiden 			unsigned long p  : 1; /* DAT-Protection Bit */
2521b09c13cSSteffen Eiden 			unsigned long iep: 1; /* Instruction-Execution-Protection */
2531b09c13cSSteffen Eiden 			unsigned long    : 2;
2541b09c13cSSteffen Eiden 			unsigned long i  : 1; /* Segment-Invalid Bit */
2551b09c13cSSteffen Eiden 			unsigned long cs : 1; /* Common-Segment Bit */
2561b09c13cSSteffen Eiden 			unsigned long tt : 2; /* Table-Type Bits */
2571b09c13cSSteffen Eiden 			unsigned long    : 2;
2581b09c13cSSteffen Eiden 		} fc1;
2591b09c13cSSteffen Eiden 	} h;
2601b09c13cSSteffen Eiden 	struct {
2611b09c13cSSteffen Eiden 		struct {
2621b09c13cSSteffen Eiden 			unsigned long              :47;
2631b09c13cSSteffen Eiden 			unsigned long              : 1; /* HW (should be 0) */
2641b09c13cSSteffen Eiden 			unsigned long s            : 1; /* Special */
2651b09c13cSSteffen Eiden 			unsigned long w            : 1; /* Writable */
2661b09c13cSSteffen Eiden 			unsigned long r            : 1; /* Readable */
2671b09c13cSSteffen Eiden 			unsigned long d            : 1; /* Dirty */
2681b09c13cSSteffen Eiden 			unsigned long y            : 1; /* Young */
2691b09c13cSSteffen Eiden 			unsigned long              : 3; /* HW */
2701b09c13cSSteffen Eiden 			unsigned long prefix_notif : 1; /* Guest prefix invalidation notification */
2711b09c13cSSteffen Eiden 			unsigned long vsie_notif   : 1; /* Referenced in a shadow table */
2721b09c13cSSteffen Eiden 			unsigned long              : 4; /* HW */
2731b09c13cSSteffen Eiden 			unsigned long sd           : 1; /* Soft-Dirty */
2741b09c13cSSteffen Eiden 			unsigned long pr           : 1; /* Present */
2751b09c13cSSteffen Eiden 		} fc1;
2761b09c13cSSteffen Eiden 	} s;
2771b09c13cSSteffen Eiden 	union {
2781b09c13cSSteffen Eiden 		struct {
2791b09c13cSSteffen Eiden 			unsigned long type :16; /* Token type */
2801b09c13cSSteffen Eiden 			unsigned long par  :16; /* Token parameter */
2811b09c13cSSteffen Eiden 			unsigned long      :26;
2821b09c13cSSteffen Eiden 			unsigned long i    : 1; /* Must be 1 */
2831b09c13cSSteffen Eiden 			unsigned long      : 1;
2841b09c13cSSteffen Eiden 			unsigned long tt   : 2;
2851b09c13cSSteffen Eiden 			unsigned long      : 1;
2861b09c13cSSteffen Eiden 			unsigned long pr   : 1; /* Must be 0 */
2871b09c13cSSteffen Eiden 		};
2881b09c13cSSteffen Eiden 		struct {
2891b09c13cSSteffen Eiden 			unsigned long token:32; /* Token and parameter */
2901b09c13cSSteffen Eiden 			unsigned long      :32;
2911b09c13cSSteffen Eiden 		};
2921b09c13cSSteffen Eiden 	} tok;
2931b09c13cSSteffen Eiden 	union pmd pmd;
2941b09c13cSSteffen Eiden 	union pud pud;
2951b09c13cSSteffen Eiden 	union p4d p4d;
2961b09c13cSSteffen Eiden 	union pgd pgd;
2971b09c13cSSteffen Eiden };
2981b09c13cSSteffen Eiden 
2991b09c13cSSteffen Eiden union skey {
3001b09c13cSSteffen Eiden 	unsigned char skey;
3011b09c13cSSteffen Eiden 	struct {
3021b09c13cSSteffen Eiden 		unsigned char acc :4;
3031b09c13cSSteffen Eiden 		unsigned char fp  :1;
3041b09c13cSSteffen Eiden 		unsigned char r   :1;
3051b09c13cSSteffen Eiden 		unsigned char c   :1;
3061b09c13cSSteffen Eiden 		unsigned char zero:1;
3071b09c13cSSteffen Eiden 	};
3081b09c13cSSteffen Eiden };
3091b09c13cSSteffen Eiden 
3101b09c13cSSteffen Eiden static_assert(sizeof(union pgste) == sizeof(unsigned long));
3111b09c13cSSteffen Eiden static_assert(sizeof(union pte) == sizeof(unsigned long));
3121b09c13cSSteffen Eiden static_assert(sizeof(union pmd) == sizeof(unsigned long));
3131b09c13cSSteffen Eiden static_assert(sizeof(union pud) == sizeof(unsigned long));
3141b09c13cSSteffen Eiden static_assert(sizeof(union p4d) == sizeof(unsigned long));
3151b09c13cSSteffen Eiden static_assert(sizeof(union pgd) == sizeof(unsigned long));
3161b09c13cSSteffen Eiden static_assert(sizeof(union crste) == sizeof(unsigned long));
3171b09c13cSSteffen Eiden static_assert(sizeof(union skey) == sizeof(char));
3181b09c13cSSteffen Eiden 
3191b09c13cSSteffen Eiden struct segment_table {
3201b09c13cSSteffen Eiden 	union pmd pmds[_CRST_ENTRIES];
3211b09c13cSSteffen Eiden };
3221b09c13cSSteffen Eiden 
3231b09c13cSSteffen Eiden struct region3_table {
3241b09c13cSSteffen Eiden 	union pud puds[_CRST_ENTRIES];
3251b09c13cSSteffen Eiden };
3261b09c13cSSteffen Eiden 
3271b09c13cSSteffen Eiden struct region2_table {
3281b09c13cSSteffen Eiden 	union p4d p4ds[_CRST_ENTRIES];
3291b09c13cSSteffen Eiden };
3301b09c13cSSteffen Eiden 
3311b09c13cSSteffen Eiden struct region1_table {
3321b09c13cSSteffen Eiden 	union pgd pgds[_CRST_ENTRIES];
3331b09c13cSSteffen Eiden };
3341b09c13cSSteffen Eiden 
3351b09c13cSSteffen Eiden struct crst_table {
3361b09c13cSSteffen Eiden 	union {
3371b09c13cSSteffen Eiden 		union crste crstes[_CRST_ENTRIES];
3381b09c13cSSteffen Eiden 		struct segment_table segment;
3391b09c13cSSteffen Eiden 		struct region3_table region3;
3401b09c13cSSteffen Eiden 		struct region2_table region2;
3411b09c13cSSteffen Eiden 		struct region1_table region1;
3421b09c13cSSteffen Eiden 	};
3431b09c13cSSteffen Eiden };
3441b09c13cSSteffen Eiden 
3451b09c13cSSteffen Eiden struct page_table {
3461b09c13cSSteffen Eiden 	union pte ptes[_PAGE_ENTRIES];
3471b09c13cSSteffen Eiden 	union pgste pgstes[_PAGE_ENTRIES];
3481b09c13cSSteffen Eiden };
3491b09c13cSSteffen Eiden 
3501b09c13cSSteffen Eiden static_assert(sizeof(struct crst_table) == _CRST_TABLE_SIZE);
3511b09c13cSSteffen Eiden static_assert(sizeof(struct page_table) == PAGE_SIZE);
3521b09c13cSSteffen Eiden 
3531b09c13cSSteffen Eiden struct dat_walk;
3541b09c13cSSteffen Eiden 
3551b09c13cSSteffen Eiden typedef long (*dat_walk_op)(union crste *crste, gfn_t gfn, gfn_t next, struct dat_walk *w);
3561b09c13cSSteffen Eiden 
3571b09c13cSSteffen Eiden struct dat_walk_ops {
3581b09c13cSSteffen Eiden 	union {
3591b09c13cSSteffen Eiden 		dat_walk_op crste_ops[4];
3601b09c13cSSteffen Eiden 		struct {
3611b09c13cSSteffen Eiden 			dat_walk_op pmd_entry;
3621b09c13cSSteffen Eiden 			dat_walk_op pud_entry;
3631b09c13cSSteffen Eiden 			dat_walk_op p4d_entry;
3641b09c13cSSteffen Eiden 			dat_walk_op pgd_entry;
3651b09c13cSSteffen Eiden 		};
3661b09c13cSSteffen Eiden 	};
3671b09c13cSSteffen Eiden 	long (*pte_entry)(union pte *pte, gfn_t gfn, gfn_t next, struct dat_walk *w);
3681b09c13cSSteffen Eiden };
3691b09c13cSSteffen Eiden 
3701b09c13cSSteffen Eiden struct dat_walk {
3711b09c13cSSteffen Eiden 	const struct dat_walk_ops *ops;
3721b09c13cSSteffen Eiden 	union crste *last;
3731b09c13cSSteffen Eiden 	union pte *last_pte;
3741b09c13cSSteffen Eiden 	union asce asce;
3751b09c13cSSteffen Eiden 	gfn_t start;
3761b09c13cSSteffen Eiden 	gfn_t end;
3771b09c13cSSteffen Eiden 	int flags;
3781b09c13cSSteffen Eiden 	void *priv;
3791b09c13cSSteffen Eiden };
3801b09c13cSSteffen Eiden 
3811b09c13cSSteffen Eiden struct ptval_param {
3821b09c13cSSteffen Eiden 	unsigned char offset : 6;
3831b09c13cSSteffen Eiden 	unsigned char len : 2;
3841b09c13cSSteffen Eiden };
3851b09c13cSSteffen Eiden 
3861b09c13cSSteffen Eiden /**
3871b09c13cSSteffen Eiden  * _pte() - Useful constructor for union pte
3881b09c13cSSteffen Eiden  * @pfn: the pfn this pte should point to.
3891b09c13cSSteffen Eiden  * @writable: whether the pte should be writable.
3901b09c13cSSteffen Eiden  * @dirty: whether the pte should be dirty.
3911b09c13cSSteffen Eiden  * @special: whether the pte should be marked as special
3921b09c13cSSteffen Eiden  *
3931b09c13cSSteffen Eiden  * The pte is also marked as young and present. If the pte is marked as dirty,
3941b09c13cSSteffen Eiden  * it gets marked as soft-dirty too. If the pte is not dirty, the hardware
3951b09c13cSSteffen Eiden  * protect bit is set (independently of the write softbit); this way proper
3961b09c13cSSteffen Eiden  * dirty tracking can be performed.
3971b09c13cSSteffen Eiden  *
3981b09c13cSSteffen Eiden  * Return: a union pte value.
3991b09c13cSSteffen Eiden  */
4001b09c13cSSteffen Eiden static inline union pte _pte(kvm_pfn_t pfn, bool writable, bool dirty, bool special)
4011b09c13cSSteffen Eiden {
4021b09c13cSSteffen Eiden 	union pte res = { .val = PFN_PHYS(pfn) };
4031b09c13cSSteffen Eiden 
4041b09c13cSSteffen Eiden 	res.h.p = !dirty;
4051b09c13cSSteffen Eiden 	res.s.y = 1;
4061b09c13cSSteffen Eiden 	res.s.pr = 1;
4071b09c13cSSteffen Eiden 	res.s.w = writable;
4081b09c13cSSteffen Eiden 	res.s.d = dirty;
4091b09c13cSSteffen Eiden 	res.s.sd = dirty;
4101b09c13cSSteffen Eiden 	res.s.s = special;
4111b09c13cSSteffen Eiden 	return res;
4121b09c13cSSteffen Eiden }
4131b09c13cSSteffen Eiden 
4141b09c13cSSteffen Eiden static inline union crste _crste_fc0(kvm_pfn_t pfn, int tt)
4151b09c13cSSteffen Eiden {
4161b09c13cSSteffen Eiden 	union crste res = { .val = PFN_PHYS(pfn) };
4171b09c13cSSteffen Eiden 
4181b09c13cSSteffen Eiden 	res.h.tt = tt;
4191b09c13cSSteffen Eiden 	res.h.fc0.tl = _REGION_ENTRY_LENGTH;
4201b09c13cSSteffen Eiden 	res.h.fc0.tf = 0;
4211b09c13cSSteffen Eiden 	return res;
4221b09c13cSSteffen Eiden }
4231b09c13cSSteffen Eiden 
4241b09c13cSSteffen Eiden /**
4251b09c13cSSteffen Eiden  * _crste() - Useful constructor for union crste with FC=1
4261b09c13cSSteffen Eiden  * @pfn: the pfn this pte should point to.
4271b09c13cSSteffen Eiden  * @tt: the table type
4281b09c13cSSteffen Eiden  * @writable: whether the pte should be writable.
4291b09c13cSSteffen Eiden  * @dirty: whether the pte should be dirty.
4301b09c13cSSteffen Eiden  *
4311b09c13cSSteffen Eiden  * The crste is also marked as young and present. If the crste is marked as
4321b09c13cSSteffen Eiden  * dirty, it gets marked as soft-dirty too. If the crste is not dirty, the
4331b09c13cSSteffen Eiden  * hardware protect bit is set (independently of the write softbit); this way
4341b09c13cSSteffen Eiden  * proper dirty tracking can be performed.
4351b09c13cSSteffen Eiden  *
4361b09c13cSSteffen Eiden  * Return: a union crste value.
4371b09c13cSSteffen Eiden  */
4381b09c13cSSteffen Eiden static inline union crste _crste_fc1(kvm_pfn_t pfn, int tt, bool writable, bool dirty)
4391b09c13cSSteffen Eiden {
4401b09c13cSSteffen Eiden 	union crste res = { .val = PFN_PHYS(pfn) & _SEGMENT_MASK };
4411b09c13cSSteffen Eiden 
4421b09c13cSSteffen Eiden 	res.h.tt = tt;
4431b09c13cSSteffen Eiden 	res.h.p = !dirty;
4441b09c13cSSteffen Eiden 	res.h.fc = 1;
4451b09c13cSSteffen Eiden 	res.s.fc1.y = 1;
4461b09c13cSSteffen Eiden 	res.s.fc1.pr = 1;
4471b09c13cSSteffen Eiden 	res.s.fc1.w = writable;
4481b09c13cSSteffen Eiden 	res.s.fc1.d = dirty;
4491b09c13cSSteffen Eiden 	res.s.fc1.sd = dirty;
4501b09c13cSSteffen Eiden 	return res;
4511b09c13cSSteffen Eiden }
4521b09c13cSSteffen Eiden 
4531b09c13cSSteffen Eiden union essa_state {
4541b09c13cSSteffen Eiden 	unsigned char val;
4551b09c13cSSteffen Eiden 	struct {
4561b09c13cSSteffen Eiden 		unsigned char		: 2;
4571b09c13cSSteffen Eiden 		unsigned char nodat	: 1;
4581b09c13cSSteffen Eiden 		unsigned char exception	: 1;
4591b09c13cSSteffen Eiden 		unsigned char usage	: 2;
4601b09c13cSSteffen Eiden 		unsigned char content	: 2;
4611b09c13cSSteffen Eiden 	};
4621b09c13cSSteffen Eiden };
4631b09c13cSSteffen Eiden 
4641b09c13cSSteffen Eiden /**
4651b09c13cSSteffen Eiden  * struct vsie_rmap - reverse mapping for shadow page table entries
4661b09c13cSSteffen Eiden  * @next: pointer to next rmap in the list
4671b09c13cSSteffen Eiden  * @r_gfn: virtual rmap address in the shadow guest address space
4681b09c13cSSteffen Eiden  */
4691b09c13cSSteffen Eiden struct vsie_rmap {
4701b09c13cSSteffen Eiden 	struct vsie_rmap *next;
4711b09c13cSSteffen Eiden 	union {
4721b09c13cSSteffen Eiden 		unsigned long val;
4731b09c13cSSteffen Eiden 		struct {
4741b09c13cSSteffen Eiden 			long          level: 8;
4751b09c13cSSteffen Eiden 			unsigned long      : 4;
4761b09c13cSSteffen Eiden 			unsigned long r_gfn:52;
4771b09c13cSSteffen Eiden 		};
4781b09c13cSSteffen Eiden 	};
4791b09c13cSSteffen Eiden };
4801b09c13cSSteffen Eiden 
4811b09c13cSSteffen Eiden static_assert(sizeof(struct vsie_rmap) == 2 * sizeof(long));
4821b09c13cSSteffen Eiden 
4831b09c13cSSteffen Eiden #define KVM_S390_MMU_CACHE_N_CRSTS	6
4841b09c13cSSteffen Eiden #define KVM_S390_MMU_CACHE_N_PTS	2
4851b09c13cSSteffen Eiden #define KVM_S390_MMU_CACHE_N_RMAPS	16
4861b09c13cSSteffen Eiden struct kvm_s390_mmu_cache {
4871b09c13cSSteffen Eiden 	void *crsts[KVM_S390_MMU_CACHE_N_CRSTS];
4881b09c13cSSteffen Eiden 	void *pts[KVM_S390_MMU_CACHE_N_PTS];
4891b09c13cSSteffen Eiden 	void *rmaps[KVM_S390_MMU_CACHE_N_RMAPS];
4901b09c13cSSteffen Eiden 	short int n_crsts;
4911b09c13cSSteffen Eiden 	short int n_pts;
4921b09c13cSSteffen Eiden 	short int n_rmaps;
4931b09c13cSSteffen Eiden };
4941b09c13cSSteffen Eiden 
4951b09c13cSSteffen Eiden struct guest_fault {
4961b09c13cSSteffen Eiden 	gfn_t gfn;		/* Guest frame */
4971b09c13cSSteffen Eiden 	kvm_pfn_t pfn;		/* Host PFN */
4981b09c13cSSteffen Eiden 	struct page *page;	/* Host page */
4991b09c13cSSteffen Eiden 	union pte *ptep;	/* Used to resolve the fault, or NULL */
5001b09c13cSSteffen Eiden 	union crste *crstep;	/* Used to resolve the fault, or NULL */
5011b09c13cSSteffen Eiden 	bool writable;		/* Mapping is writable */
5021b09c13cSSteffen Eiden 	bool write_attempt;	/* Write access attempted */
5031b09c13cSSteffen Eiden 	bool attempt_pfault;	/* Attempt a pfault first */
5041b09c13cSSteffen Eiden 	bool valid;		/* This entry contains valid data */
5051b09c13cSSteffen Eiden 	bool crste_region3;     /* Whether crstep refers to a region3 entry */
5061b09c13cSSteffen Eiden 	void (*callback)(struct guest_fault *f);
5071b09c13cSSteffen Eiden 	void *priv;
5081b09c13cSSteffen Eiden };
5091b09c13cSSteffen Eiden 
5101b09c13cSSteffen Eiden /*
5111b09c13cSSteffen Eiden  *	0	1	2	3	4	5	6	7
5121b09c13cSSteffen Eiden  *	+-------+-------+-------+-------+-------+-------+-------+-------+
5131b09c13cSSteffen Eiden  *  0	|				|	    PGT_ADDR		|
5141b09c13cSSteffen Eiden  *  8	|	 VMADDR		|					|
5151b09c13cSSteffen Eiden  * 16	|								|
5161b09c13cSSteffen Eiden  * 24	|								|
5171b09c13cSSteffen Eiden  */
5181b09c13cSSteffen Eiden #define MKPTVAL(o, l) ((struct ptval_param) { .offset = (o), .len = ((l) + 1) / 2 - 1})
5191b09c13cSSteffen Eiden #define PTVAL_PGT_ADDR	MKPTVAL(4, 8)
5201b09c13cSSteffen Eiden #define PTVAL_VMADDR	MKPTVAL(8, 6)
5211b09c13cSSteffen Eiden 
5221b09c13cSSteffen Eiden union pgste __must_check __dat_ptep_xchg(union pte *ptep, union pgste pgste, union pte new,
5231b09c13cSSteffen Eiden 					 gfn_t gfn, union asce asce, bool uses_skeys);
5241b09c13cSSteffen Eiden bool dat_crstep_xchg_atomic(union crste *crstep, union crste old, union crste new, gfn_t gfn,
5251b09c13cSSteffen Eiden 			    union asce asce);
5261b09c13cSSteffen Eiden void dat_crstep_xchg(union crste *crstep, union crste new, gfn_t gfn, union asce asce);
5271b09c13cSSteffen Eiden 
5281b09c13cSSteffen Eiden long _dat_walk_gfn_range(gfn_t start, gfn_t end, union asce asce,
5291b09c13cSSteffen Eiden 			 const struct dat_walk_ops *ops, int flags, void *priv);
5301b09c13cSSteffen Eiden 
5311b09c13cSSteffen Eiden int dat_entry_walk(struct kvm_s390_mmu_cache *mc, gfn_t gfn, union asce asce, int flags,
5321b09c13cSSteffen Eiden 		   int walk_level, union crste **last, union pte **ptepp);
5331b09c13cSSteffen Eiden void dat_free_level(struct crst_table *table, bool owns_ptes);
5341b09c13cSSteffen Eiden struct crst_table *dat_alloc_crst_sleepable(unsigned long init);
5351b09c13cSSteffen Eiden int dat_set_asce_limit(struct kvm_s390_mmu_cache *mc, union asce *asce, int newtype);
536a07276d5SSteffen Eiden 
537a07276d5SSteffen Eiden #if KVM_S390_MANAGES_S390_GUEST
5381b09c13cSSteffen Eiden int dat_get_storage_key(union asce asce, gfn_t gfn, union skey *skey);
5391b09c13cSSteffen Eiden int dat_set_storage_key(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gfn,
5401b09c13cSSteffen Eiden 			union skey skey, bool nq);
5411b09c13cSSteffen Eiden int dat_cond_set_storage_key(struct kvm_s390_mmu_cache *mmc, union asce asce, gfn_t gfn,
5421b09c13cSSteffen Eiden 			     union skey skey, union skey *oldkey, bool nq, bool mr, bool mc);
5431b09c13cSSteffen Eiden int dat_reset_reference_bit(union asce asce, gfn_t gfn, union skey *skey);
5441b09c13cSSteffen Eiden long dat_reset_skeys(union asce asce, gfn_t start);
545a07276d5SSteffen Eiden #endif /* KVM_S390_MANAGES_S390_GUEST */
5461b09c13cSSteffen Eiden 
5471b09c13cSSteffen Eiden unsigned long dat_get_ptval(struct page_table *table, struct ptval_param param);
5481b09c13cSSteffen Eiden void dat_set_ptval(struct page_table *table, struct ptval_param param, unsigned long val);
5491b09c13cSSteffen Eiden 
5501b09c13cSSteffen Eiden int dat_set_slot(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t start, gfn_t end,
5511b09c13cSSteffen Eiden 		 u16 type, u16 param);
552*188a15ccSSteffen Eiden 
553*188a15ccSSteffen Eiden #if KVM_S390_MANAGES_S390_GUEST
5541b09c13cSSteffen Eiden int dat_set_prefix_notif_bit(union asce asce, gfn_t gfn);
555*188a15ccSSteffen Eiden #else
556*188a15ccSSteffen Eiden static inline int dat_set_prefix_notif_bit(union asce asce, gfn_t gfn)
557*188a15ccSSteffen Eiden {
558*188a15ccSSteffen Eiden 	return 0;
559*188a15ccSSteffen Eiden }
560*188a15ccSSteffen Eiden #endif /* KVM_S390_MANAGES_S390_GUEST */
561*188a15ccSSteffen Eiden 
5621b09c13cSSteffen Eiden bool dat_test_age_gfn(union asce asce, gfn_t start, gfn_t end);
5631b09c13cSSteffen Eiden 
564ce4bee6aSSteffen Eiden #if KVM_S390_MANAGES_S390_GUEST
5651b09c13cSSteffen Eiden int dat_perform_essa(union asce asce, gfn_t gfn, int orc, union essa_state *state, bool *dirty);
5661b09c13cSSteffen Eiden long dat_reset_cmma(union asce asce, gfn_t start_gfn);
5671b09c13cSSteffen Eiden int dat_peek_cmma(gfn_t start, union asce asce, unsigned int *count, u8 *values);
5681b09c13cSSteffen Eiden int dat_get_cmma(union asce asce, gfn_t *start, unsigned int *count, u8 *values, atomic64_t *rem);
5691b09c13cSSteffen Eiden int dat_set_cmma_bits(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t gfn,
5701b09c13cSSteffen Eiden 		      unsigned long count, unsigned long mask, const uint8_t *bits);
571ce4bee6aSSteffen Eiden #endif /* KVM_S390_MANAGES_S390_GUEST */
5721b09c13cSSteffen Eiden 
5731b09c13cSSteffen Eiden int kvm_s390_mmu_cache_topup(struct kvm_s390_mmu_cache *mc);
5741b09c13cSSteffen Eiden 
5751b09c13cSSteffen Eiden #define GFP_KVM_S390_MMU_CACHE (GFP_ATOMIC | __GFP_ACCOUNT | __GFP_NOWARN)
5761b09c13cSSteffen Eiden 
5771b09c13cSSteffen Eiden static inline struct page_table *kvm_s390_mmu_cache_alloc_pt(struct kvm_s390_mmu_cache *mc)
5781b09c13cSSteffen Eiden {
5791b09c13cSSteffen Eiden 	if (mc->n_pts)
5801b09c13cSSteffen Eiden 		return mc->pts[--mc->n_pts];
5811b09c13cSSteffen Eiden 	return (void *)__get_free_page(GFP_KVM_S390_MMU_CACHE);
5821b09c13cSSteffen Eiden }
5831b09c13cSSteffen Eiden 
5841b09c13cSSteffen Eiden static inline struct crst_table *kvm_s390_mmu_cache_alloc_crst(struct kvm_s390_mmu_cache *mc)
5851b09c13cSSteffen Eiden {
5861b09c13cSSteffen Eiden 	if (mc->n_crsts)
5871b09c13cSSteffen Eiden 		return mc->crsts[--mc->n_crsts];
5881b09c13cSSteffen Eiden 	return (void *)__get_free_pages(GFP_KVM_S390_MMU_CACHE | __GFP_COMP, CRST_ALLOC_ORDER);
5891b09c13cSSteffen Eiden }
5901b09c13cSSteffen Eiden 
5911b09c13cSSteffen Eiden static inline struct vsie_rmap *kvm_s390_mmu_cache_alloc_rmap(struct kvm_s390_mmu_cache *mc)
5921b09c13cSSteffen Eiden {
5931b09c13cSSteffen Eiden 	if (mc->n_rmaps)
5941b09c13cSSteffen Eiden 		return mc->rmaps[--mc->n_rmaps];
5951b09c13cSSteffen Eiden 	return kzalloc_obj(struct vsie_rmap, GFP_KVM_S390_MMU_CACHE);
5961b09c13cSSteffen Eiden }
5971b09c13cSSteffen Eiden 
5981b09c13cSSteffen Eiden static inline struct crst_table *crste_table_start(union crste *crstep)
5991b09c13cSSteffen Eiden {
6001b09c13cSSteffen Eiden 	return (struct crst_table *)ALIGN_DOWN((unsigned long)crstep, _CRST_TABLE_SIZE);
6011b09c13cSSteffen Eiden }
6021b09c13cSSteffen Eiden 
6031b09c13cSSteffen Eiden static inline struct page_table *pte_table_start(union pte *ptep)
6041b09c13cSSteffen Eiden {
6051b09c13cSSteffen Eiden 	return (struct page_table *)ALIGN_DOWN((unsigned long)ptep, _PAGE_TABLE_SIZE);
6061b09c13cSSteffen Eiden }
6071b09c13cSSteffen Eiden 
6081b09c13cSSteffen Eiden static inline bool crdte_crste(union crste *crstep, union crste old, union crste new, gfn_t gfn,
6091b09c13cSSteffen Eiden 			       union asce asce)
6101b09c13cSSteffen Eiden {
6111b09c13cSSteffen Eiden 	unsigned long dtt = 0x10 | new.h.tt << 2;
6121b09c13cSSteffen Eiden 	void *table = crste_table_start(crstep);
6131b09c13cSSteffen Eiden 
6141b09c13cSSteffen Eiden 	return crdte(old.val, new.val, table, dtt, gfn_to_gpa(gfn), asce.val);
6151b09c13cSSteffen Eiden }
6161b09c13cSSteffen Eiden 
6171b09c13cSSteffen Eiden /**
6181b09c13cSSteffen Eiden  * idte_crste() - invalidate a crste entry using idte
6191b09c13cSSteffen Eiden  * @crstep: pointer to the crste to be invalidated
6201b09c13cSSteffen Eiden  * @gfn: a gfn mapped by the crste
6211b09c13cSSteffen Eiden  * @opt: options for the idte instruction
6221b09c13cSSteffen Eiden  * @asce: the asce
6231b09c13cSSteffen Eiden  * @local: whether the operation is cpu-local
6241b09c13cSSteffen Eiden  */
6251b09c13cSSteffen Eiden static __always_inline void idte_crste(union crste *crstep, gfn_t gfn, unsigned long opt,
6261b09c13cSSteffen Eiden 				       union asce asce, int local)
6271b09c13cSSteffen Eiden {
6281b09c13cSSteffen Eiden 	unsigned long table_origin = __pa(crste_table_start(crstep));
6291b09c13cSSteffen Eiden 	unsigned long gaddr = gfn_to_gpa(gfn) & HPAGE_MASK;
6301b09c13cSSteffen Eiden 
6311b09c13cSSteffen Eiden 	if (__builtin_constant_p(opt) && opt == 0) {
6321b09c13cSSteffen Eiden 		/* flush without guest asce */
6331b09c13cSSteffen Eiden 		asm volatile("idte	%[table_origin],0,%[gaddr],%[local]"
6341b09c13cSSteffen Eiden 			: "+m" (*crstep)
6351b09c13cSSteffen Eiden 			: [table_origin] "a" (table_origin), [gaddr] "a" (gaddr),
6361b09c13cSSteffen Eiden 			  [local] "i" (local)
6371b09c13cSSteffen Eiden 			: "cc");
6381b09c13cSSteffen Eiden 	} else {
6391b09c13cSSteffen Eiden 		/* flush with guest asce */
6401b09c13cSSteffen Eiden 		asm volatile("idte %[table_origin],%[asce],%[gaddr_opt],%[local]"
6411b09c13cSSteffen Eiden 			: "+m" (*crstep)
6421b09c13cSSteffen Eiden 			: [table_origin] "a" (table_origin), [gaddr_opt] "a" (gaddr | opt),
6431b09c13cSSteffen Eiden 			  [asce] "a" (asce.val), [local] "i" (local)
6441b09c13cSSteffen Eiden 			: "cc");
6451b09c13cSSteffen Eiden 	}
6461b09c13cSSteffen Eiden }
6471b09c13cSSteffen Eiden 
6481b09c13cSSteffen Eiden static inline void dat_init_pgstes(struct page_table *pt, unsigned long val)
6491b09c13cSSteffen Eiden {
6501b09c13cSSteffen Eiden 	memset64((void *)pt->pgstes, val, PTRS_PER_PTE);
6511b09c13cSSteffen Eiden }
6521b09c13cSSteffen Eiden 
6531b09c13cSSteffen Eiden static inline void dat_init_page_table(struct page_table *pt, unsigned long ptes,
6541b09c13cSSteffen Eiden 				       unsigned long pgstes)
6551b09c13cSSteffen Eiden {
6561b09c13cSSteffen Eiden 	memset64((void *)pt->ptes, ptes, PTRS_PER_PTE);
6571b09c13cSSteffen Eiden 	dat_init_pgstes(pt, pgstes);
6581b09c13cSSteffen Eiden }
6591b09c13cSSteffen Eiden 
6601b09c13cSSteffen Eiden static inline gfn_t asce_end(union asce asce)
6611b09c13cSSteffen Eiden {
6621b09c13cSSteffen Eiden 	return 1ULL << ((asce.dt + 1) * 11 + _SEGMENT_SHIFT - PAGE_SHIFT);
6631b09c13cSSteffen Eiden }
6641b09c13cSSteffen Eiden 
6651b09c13cSSteffen Eiden #define _CRSTE(x) ((union crste) { .val = _Generic((x),	\
6661b09c13cSSteffen Eiden 			union pgd : (x).val,		\
6671b09c13cSSteffen Eiden 			union p4d : (x).val,		\
6681b09c13cSSteffen Eiden 			union pud : (x).val,		\
6691b09c13cSSteffen Eiden 			union pmd : (x).val,		\
6701b09c13cSSteffen Eiden 			union crste : (x).val)})
6711b09c13cSSteffen Eiden 
6721b09c13cSSteffen Eiden #define _CRSTEP(x) ((union crste *)_Generic((*(x)),	\
6731b09c13cSSteffen Eiden 				union pgd : (x),	\
6741b09c13cSSteffen Eiden 				union p4d : (x),	\
6751b09c13cSSteffen Eiden 				union pud : (x),	\
6761b09c13cSSteffen Eiden 				union pmd : (x),	\
6771b09c13cSSteffen Eiden 				union crste : (x)))
6781b09c13cSSteffen Eiden 
6791b09c13cSSteffen Eiden #define _CRSTP(x) ((struct crst_table *)_Generic((*(x)),	\
6801b09c13cSSteffen Eiden 		struct crst_table : (x),			\
6811b09c13cSSteffen Eiden 		struct segment_table : (x),			\
6821b09c13cSSteffen Eiden 		struct region3_table : (x),			\
6831b09c13cSSteffen Eiden 		struct region2_table : (x),			\
6841b09c13cSSteffen Eiden 		struct region1_table : (x)))
6851b09c13cSSteffen Eiden 
6861b09c13cSSteffen Eiden static inline bool asce_contains_gfn(union asce asce, gfn_t gfn)
6871b09c13cSSteffen Eiden {
6881b09c13cSSteffen Eiden 	return gfn < asce_end(asce);
6891b09c13cSSteffen Eiden }
6901b09c13cSSteffen Eiden 
6911b09c13cSSteffen Eiden static inline bool is_pmd(union crste crste)
6921b09c13cSSteffen Eiden {
6931b09c13cSSteffen Eiden 	return crste.h.tt == TABLE_TYPE_SEGMENT;
6941b09c13cSSteffen Eiden }
6951b09c13cSSteffen Eiden 
6961b09c13cSSteffen Eiden static inline bool is_pud(union crste crste)
6971b09c13cSSteffen Eiden {
6981b09c13cSSteffen Eiden 	return crste.h.tt == TABLE_TYPE_REGION3;
6991b09c13cSSteffen Eiden }
7001b09c13cSSteffen Eiden 
7011b09c13cSSteffen Eiden static inline bool is_p4d(union crste crste)
7021b09c13cSSteffen Eiden {
7031b09c13cSSteffen Eiden 	return crste.h.tt == TABLE_TYPE_REGION2;
7041b09c13cSSteffen Eiden }
7051b09c13cSSteffen Eiden 
7061b09c13cSSteffen Eiden static inline bool is_pgd(union crste crste)
7071b09c13cSSteffen Eiden {
7081b09c13cSSteffen Eiden 	return crste.h.tt == TABLE_TYPE_REGION1;
7091b09c13cSSteffen Eiden }
7101b09c13cSSteffen Eiden 
7111b09c13cSSteffen Eiden static inline phys_addr_t pmd_origin_large(union pmd pmd)
7121b09c13cSSteffen Eiden {
7131b09c13cSSteffen Eiden 	return pmd.val & _SEGMENT_ENTRY_ORIGIN_LARGE;
7141b09c13cSSteffen Eiden }
7151b09c13cSSteffen Eiden 
7161b09c13cSSteffen Eiden static inline phys_addr_t pud_origin_large(union pud pud)
7171b09c13cSSteffen Eiden {
7181b09c13cSSteffen Eiden 	return pud.val & _REGION3_ENTRY_ORIGIN_LARGE;
7191b09c13cSSteffen Eiden }
7201b09c13cSSteffen Eiden 
7211b09c13cSSteffen Eiden /**
7221b09c13cSSteffen Eiden  * crste_origin_large() - Return the large frame origin of a large crste
7231b09c13cSSteffen Eiden  * @crste: The crste whose origin is to be returned. Should be either a
7241b09c13cSSteffen Eiden  *         region-3 table entry or a segment table entry, in both cases with
7251b09c13cSSteffen Eiden  *         FC set to 1 (large pages).
7261b09c13cSSteffen Eiden  *
7271b09c13cSSteffen Eiden  * Return: The origin of the large frame pointed to by @crste, or -1 if the
7281b09c13cSSteffen Eiden  *         crste was not large (wrong table type, or FC==0)
7291b09c13cSSteffen Eiden  */
7301b09c13cSSteffen Eiden static inline phys_addr_t crste_origin_large(union crste crste)
7311b09c13cSSteffen Eiden {
7321b09c13cSSteffen Eiden 	if (unlikely(!crste.h.fc || crste.h.tt > TABLE_TYPE_REGION3))
7331b09c13cSSteffen Eiden 		return -1;
7341b09c13cSSteffen Eiden 	if (is_pmd(crste))
7351b09c13cSSteffen Eiden 		return pmd_origin_large(crste.pmd);
7361b09c13cSSteffen Eiden 	return pud_origin_large(crste.pud);
7371b09c13cSSteffen Eiden }
7381b09c13cSSteffen Eiden 
7391b09c13cSSteffen Eiden #define crste_origin(x) (_Generic((x),				\
7401b09c13cSSteffen Eiden 		union pmd : (x).val & _SEGMENT_ENTRY_ORIGIN,	\
7411b09c13cSSteffen Eiden 		union pud : (x).val & _REGION_ENTRY_ORIGIN,	\
7421b09c13cSSteffen Eiden 		union p4d : (x).val & _REGION_ENTRY_ORIGIN,	\
7431b09c13cSSteffen Eiden 		union pgd : (x).val & _REGION_ENTRY_ORIGIN))
7441b09c13cSSteffen Eiden 
7451b09c13cSSteffen Eiden static inline unsigned long pte_origin(union pte pte)
7461b09c13cSSteffen Eiden {
7471b09c13cSSteffen Eiden 	return pte.val & PAGE_MASK;
7481b09c13cSSteffen Eiden }
7491b09c13cSSteffen Eiden 
7501b09c13cSSteffen Eiden static inline bool pmd_prefix(union pmd pmd)
7511b09c13cSSteffen Eiden {
7521b09c13cSSteffen Eiden 	return pmd.h.fc && pmd.s.fc1.prefix_notif;
7531b09c13cSSteffen Eiden }
7541b09c13cSSteffen Eiden 
7551b09c13cSSteffen Eiden static inline bool pud_prefix(union pud pud)
7561b09c13cSSteffen Eiden {
7571b09c13cSSteffen Eiden 	return pud.h.fc && pud.s.fc1.prefix_notif;
7581b09c13cSSteffen Eiden }
7591b09c13cSSteffen Eiden 
7601b09c13cSSteffen Eiden static inline bool crste_leaf(union crste crste)
7611b09c13cSSteffen Eiden {
7621b09c13cSSteffen Eiden 	return (crste.h.tt <= TABLE_TYPE_REGION3) && crste.h.fc;
7631b09c13cSSteffen Eiden }
7641b09c13cSSteffen Eiden 
7651b09c13cSSteffen Eiden static inline bool crste_prefix(union crste crste)
7661b09c13cSSteffen Eiden {
7671b09c13cSSteffen Eiden 	return crste_leaf(crste) && crste.s.fc1.prefix_notif;
7681b09c13cSSteffen Eiden }
7691b09c13cSSteffen Eiden 
7701b09c13cSSteffen Eiden static inline bool crste_dirty(union crste crste)
7711b09c13cSSteffen Eiden {
7721b09c13cSSteffen Eiden 	return crste_leaf(crste) && crste.s.fc1.d;
7731b09c13cSSteffen Eiden }
7741b09c13cSSteffen Eiden 
7751b09c13cSSteffen Eiden static inline union pgste *pgste_of(union pte *pte)
7761b09c13cSSteffen Eiden {
7771b09c13cSSteffen Eiden 	return (union pgste *)(pte + _PAGE_ENTRIES);
7781b09c13cSSteffen Eiden }
7791b09c13cSSteffen Eiden 
7801b09c13cSSteffen Eiden static inline bool pte_hole(union pte pte)
7811b09c13cSSteffen Eiden {
7821b09c13cSSteffen Eiden 	return pte.h.i && !pte.tok.pr && pte.tok.type != _DAT_TOKEN_NONE;
7831b09c13cSSteffen Eiden }
7841b09c13cSSteffen Eiden 
7851b09c13cSSteffen Eiden static inline bool _crste_hole(union crste crste)
7861b09c13cSSteffen Eiden {
7871b09c13cSSteffen Eiden 	return crste.h.i && !crste.tok.pr && crste.tok.type != _DAT_TOKEN_NONE;
7881b09c13cSSteffen Eiden }
7891b09c13cSSteffen Eiden 
7901b09c13cSSteffen Eiden #define crste_hole(x) _crste_hole(_CRSTE(x))
7911b09c13cSSteffen Eiden 
7921b09c13cSSteffen Eiden static inline bool _crste_none(union crste crste)
7931b09c13cSSteffen Eiden {
7941b09c13cSSteffen Eiden 	return crste.h.i && !crste.tok.pr && crste.tok.type == _DAT_TOKEN_NONE;
7951b09c13cSSteffen Eiden }
7961b09c13cSSteffen Eiden 
7971b09c13cSSteffen Eiden #define crste_none(x) _crste_none(_CRSTE(x))
7981b09c13cSSteffen Eiden 
7991b09c13cSSteffen Eiden static inline phys_addr_t large_pud_to_phys(union pud pud, gfn_t gfn)
8001b09c13cSSteffen Eiden {
8011b09c13cSSteffen Eiden 	return pud_origin_large(pud) | (gfn_to_gpa(gfn) & ~_REGION3_MASK);
8021b09c13cSSteffen Eiden }
8031b09c13cSSteffen Eiden 
8041b09c13cSSteffen Eiden static inline phys_addr_t large_pmd_to_phys(union pmd pmd, gfn_t gfn)
8051b09c13cSSteffen Eiden {
8061b09c13cSSteffen Eiden 	return pmd_origin_large(pmd) | (gfn_to_gpa(gfn) & ~_SEGMENT_MASK);
8071b09c13cSSteffen Eiden }
8081b09c13cSSteffen Eiden 
8091b09c13cSSteffen Eiden static inline phys_addr_t large_crste_to_phys(union crste crste, gfn_t gfn)
8101b09c13cSSteffen Eiden {
8111b09c13cSSteffen Eiden 	if (unlikely(!crste.h.fc || crste.h.tt > TABLE_TYPE_REGION3))
8121b09c13cSSteffen Eiden 		return -1;
8131b09c13cSSteffen Eiden 	if (is_pmd(crste))
8141b09c13cSSteffen Eiden 		return large_pmd_to_phys(crste.pmd, gfn);
8151b09c13cSSteffen Eiden 	return large_pud_to_phys(crste.pud, gfn);
8161b09c13cSSteffen Eiden }
8171b09c13cSSteffen Eiden 
8181b09c13cSSteffen Eiden static inline bool cspg_crste(union crste *crstep, union crste old, union crste new)
8191b09c13cSSteffen Eiden {
8201b09c13cSSteffen Eiden 	return cspg(&crstep->val, old.val, new.val);
8211b09c13cSSteffen Eiden }
8221b09c13cSSteffen Eiden 
8231b09c13cSSteffen Eiden static inline struct page_table *dereference_pmd(union pmd pmd)
8241b09c13cSSteffen Eiden {
8251b09c13cSSteffen Eiden 	return phys_to_virt(crste_origin(pmd));
8261b09c13cSSteffen Eiden }
8271b09c13cSSteffen Eiden 
8281b09c13cSSteffen Eiden static inline struct segment_table *dereference_pud(union pud pud)
8291b09c13cSSteffen Eiden {
8301b09c13cSSteffen Eiden 	return phys_to_virt(crste_origin(pud));
8311b09c13cSSteffen Eiden }
8321b09c13cSSteffen Eiden 
8331b09c13cSSteffen Eiden static inline struct region3_table *dereference_p4d(union p4d p4d)
8341b09c13cSSteffen Eiden {
8351b09c13cSSteffen Eiden 	return phys_to_virt(crste_origin(p4d));
8361b09c13cSSteffen Eiden }
8371b09c13cSSteffen Eiden 
8381b09c13cSSteffen Eiden static inline struct region2_table *dereference_pgd(union pgd pgd)
8391b09c13cSSteffen Eiden {
8401b09c13cSSteffen Eiden 	return phys_to_virt(crste_origin(pgd));
8411b09c13cSSteffen Eiden }
8421b09c13cSSteffen Eiden 
8431b09c13cSSteffen Eiden static inline struct crst_table *_dereference_crste(union crste crste)
8441b09c13cSSteffen Eiden {
8451b09c13cSSteffen Eiden 	if (unlikely(is_pmd(crste)))
8461b09c13cSSteffen Eiden 		return NULL;
8471b09c13cSSteffen Eiden 	return phys_to_virt(crste_origin(crste.pud));
8481b09c13cSSteffen Eiden }
8491b09c13cSSteffen Eiden 
8501b09c13cSSteffen Eiden #define dereference_crste(x) (_Generic((x),			\
8511b09c13cSSteffen Eiden 		union pud : _dereference_crste(_CRSTE(x)),	\
8521b09c13cSSteffen Eiden 		union p4d : _dereference_crste(_CRSTE(x)),	\
8531b09c13cSSteffen Eiden 		union pgd : _dereference_crste(_CRSTE(x)),	\
8541b09c13cSSteffen Eiden 		union crste : _dereference_crste(_CRSTE(x))))
8551b09c13cSSteffen Eiden 
8561b09c13cSSteffen Eiden static inline struct crst_table *dereference_asce(union asce asce)
8571b09c13cSSteffen Eiden {
8581b09c13cSSteffen Eiden 	return phys_to_virt(asce.val & _ASCE_ORIGIN);
8591b09c13cSSteffen Eiden }
8601b09c13cSSteffen Eiden 
8611b09c13cSSteffen Eiden static inline void asce_flush_tlb(union asce asce)
8621b09c13cSSteffen Eiden {
8631b09c13cSSteffen Eiden 	__tlb_flush_idte(asce.val);
8641b09c13cSSteffen Eiden }
8651b09c13cSSteffen Eiden 
8661b09c13cSSteffen Eiden static inline bool pgste_get_trylock(union pte *ptep, union pgste *res)
8671b09c13cSSteffen Eiden {
8681b09c13cSSteffen Eiden 	union pgste *pgstep = pgste_of(ptep);
8691b09c13cSSteffen Eiden 	union pgste old_pgste;
8701b09c13cSSteffen Eiden 
8711b09c13cSSteffen Eiden 	if (READ_ONCE(pgstep->val) & PGSTE_PCL_BIT)
8721b09c13cSSteffen Eiden 		return false;
8731b09c13cSSteffen Eiden 	old_pgste.val = __atomic64_or_barrier(PGSTE_PCL_BIT, &pgstep->val);
8741b09c13cSSteffen Eiden 	if (old_pgste.pcl)
8751b09c13cSSteffen Eiden 		return false;
8761b09c13cSSteffen Eiden 	old_pgste.pcl = 1;
8771b09c13cSSteffen Eiden 	*res = old_pgste;
8781b09c13cSSteffen Eiden 	return true;
8791b09c13cSSteffen Eiden }
8801b09c13cSSteffen Eiden 
8811b09c13cSSteffen Eiden static inline union pgste pgste_get_lock(union pte *ptep)
8821b09c13cSSteffen Eiden {
8831b09c13cSSteffen Eiden 	union pgste res;
8841b09c13cSSteffen Eiden 
8851b09c13cSSteffen Eiden 	while (!pgste_get_trylock(ptep, &res))
8861b09c13cSSteffen Eiden 		cpu_relax();
8871b09c13cSSteffen Eiden 	return res;
8881b09c13cSSteffen Eiden }
8891b09c13cSSteffen Eiden 
8901b09c13cSSteffen Eiden static inline void pgste_set_unlock(union pte *ptep, union pgste pgste)
8911b09c13cSSteffen Eiden {
8921b09c13cSSteffen Eiden 	pgste.pcl = 0;
8931b09c13cSSteffen Eiden 	barrier();
8941b09c13cSSteffen Eiden 	WRITE_ONCE(*pgste_of(ptep), pgste);
8951b09c13cSSteffen Eiden }
8961b09c13cSSteffen Eiden 
8971b09c13cSSteffen Eiden static inline void dat_ptep_xchg(union pte *ptep, union pte new, gfn_t gfn, union asce asce,
8981b09c13cSSteffen Eiden 				 bool has_skeys)
8991b09c13cSSteffen Eiden {
9001b09c13cSSteffen Eiden 	union pgste pgste;
9011b09c13cSSteffen Eiden 
9021b09c13cSSteffen Eiden 	pgste = pgste_get_lock(ptep);
9031b09c13cSSteffen Eiden 	pgste = __dat_ptep_xchg(ptep, pgste, new, gfn, asce, has_skeys);
9041b09c13cSSteffen Eiden 	pgste_set_unlock(ptep, pgste);
9051b09c13cSSteffen Eiden }
9061b09c13cSSteffen Eiden 
9071b09c13cSSteffen Eiden static inline void dat_ptep_clear(union pte *ptep, gfn_t gfn, union asce asce, bool has_skeys)
9081b09c13cSSteffen Eiden {
9091b09c13cSSteffen Eiden 	dat_ptep_xchg(ptep, _PTE_EMPTY, gfn, asce, has_skeys);
9101b09c13cSSteffen Eiden }
9111b09c13cSSteffen Eiden 
9121b09c13cSSteffen Eiden static inline void dat_free_pt(struct page_table *pt)
9131b09c13cSSteffen Eiden {
9141b09c13cSSteffen Eiden 	free_page((unsigned long)pt);
9151b09c13cSSteffen Eiden }
9161b09c13cSSteffen Eiden 
9171b09c13cSSteffen Eiden static inline void _dat_free_crst(struct crst_table *table)
9181b09c13cSSteffen Eiden {
9191b09c13cSSteffen Eiden 	free_pages((unsigned long)table, CRST_ALLOC_ORDER);
9201b09c13cSSteffen Eiden }
9211b09c13cSSteffen Eiden 
9221b09c13cSSteffen Eiden #define dat_free_crst(x) _dat_free_crst(_CRSTP(x))
9231b09c13cSSteffen Eiden 
9241b09c13cSSteffen Eiden static inline void kvm_s390_free_mmu_cache(struct kvm_s390_mmu_cache *mc)
9251b09c13cSSteffen Eiden {
9261b09c13cSSteffen Eiden 	if (!mc)
9271b09c13cSSteffen Eiden 		return;
9281b09c13cSSteffen Eiden 	while (mc->n_pts)
9291b09c13cSSteffen Eiden 		dat_free_pt(mc->pts[--mc->n_pts]);
9301b09c13cSSteffen Eiden 	while (mc->n_crsts)
9311b09c13cSSteffen Eiden 		_dat_free_crst(mc->crsts[--mc->n_crsts]);
9321b09c13cSSteffen Eiden 	while (mc->n_rmaps)
9331b09c13cSSteffen Eiden 		kfree(mc->rmaps[--mc->n_rmaps]);
9341b09c13cSSteffen Eiden 	kfree(mc);
9351b09c13cSSteffen Eiden }
9361b09c13cSSteffen Eiden 
9371b09c13cSSteffen Eiden DEFINE_FREE(kvm_s390_mmu_cache, struct kvm_s390_mmu_cache *, if (_T) kvm_s390_free_mmu_cache(_T))
9381b09c13cSSteffen Eiden 
9391b09c13cSSteffen Eiden static inline struct kvm_s390_mmu_cache *kvm_s390_new_mmu_cache(void)
9401b09c13cSSteffen Eiden {
9411b09c13cSSteffen Eiden 	struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
9421b09c13cSSteffen Eiden 
9431b09c13cSSteffen Eiden 	mc = kzalloc_obj(*mc, GFP_KERNEL_ACCOUNT);
9441b09c13cSSteffen Eiden 	if (mc && !kvm_s390_mmu_cache_topup(mc))
9451b09c13cSSteffen Eiden 		return_ptr(mc);
9461b09c13cSSteffen Eiden 	return NULL;
9471b09c13cSSteffen Eiden }
9481b09c13cSSteffen Eiden 
9491b09c13cSSteffen Eiden static inline bool dat_pmdp_xchg_atomic(union pmd *pmdp, union pmd old, union pmd new,
9501b09c13cSSteffen Eiden 					gfn_t gfn, union asce asce)
9511b09c13cSSteffen Eiden {
9521b09c13cSSteffen Eiden 	return dat_crstep_xchg_atomic(_CRSTEP(pmdp), _CRSTE(old), _CRSTE(new), gfn, asce);
9531b09c13cSSteffen Eiden }
9541b09c13cSSteffen Eiden 
9551b09c13cSSteffen Eiden static inline bool dat_pudp_xchg_atomic(union pud *pudp, union pud old, union pud new,
9561b09c13cSSteffen Eiden 					gfn_t gfn, union asce asce)
9571b09c13cSSteffen Eiden {
9581b09c13cSSteffen Eiden 	return dat_crstep_xchg_atomic(_CRSTEP(pudp), _CRSTE(old), _CRSTE(new), gfn, asce);
9591b09c13cSSteffen Eiden }
9601b09c13cSSteffen Eiden 
9611b09c13cSSteffen Eiden static inline union crste dat_crstep_clear_atomic(union crste *crstep, gfn_t gfn, union asce asce)
9621b09c13cSSteffen Eiden {
9631b09c13cSSteffen Eiden 	union crste oldcrste, empty = _CRSTE_EMPTY(crstep->h.tt);
9641b09c13cSSteffen Eiden 
9651b09c13cSSteffen Eiden 	do {
9661b09c13cSSteffen Eiden 		oldcrste = READ_ONCE(*crstep);
9671b09c13cSSteffen Eiden 	} while (!dat_crstep_xchg_atomic(crstep, oldcrste, empty, gfn, asce));
9681b09c13cSSteffen Eiden 	return oldcrste;
9691b09c13cSSteffen Eiden }
9701b09c13cSSteffen Eiden 
9711b09c13cSSteffen Eiden static inline int get_level(union crste *crstep, union pte *ptep)
9721b09c13cSSteffen Eiden {
9731b09c13cSSteffen Eiden 	return ptep ? TABLE_TYPE_PAGE_TABLE : crstep->h.tt;
9741b09c13cSSteffen Eiden }
9751b09c13cSSteffen Eiden 
9761b09c13cSSteffen Eiden static inline int dat_delete_slot(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t start,
9771b09c13cSSteffen Eiden 				  unsigned long npages)
9781b09c13cSSteffen Eiden {
9791b09c13cSSteffen Eiden 	return dat_set_slot(mc, asce, start, start + npages, _DAT_TOKEN_PIC, PGM_ADDRESSING);
9801b09c13cSSteffen Eiden }
9811b09c13cSSteffen Eiden 
9821b09c13cSSteffen Eiden static inline int dat_create_slot(struct kvm_s390_mmu_cache *mc, union asce asce, gfn_t start,
9831b09c13cSSteffen Eiden 				  unsigned long npages)
9841b09c13cSSteffen Eiden {
9851b09c13cSSteffen Eiden 	return dat_set_slot(mc, asce, start, start + npages, _DAT_TOKEN_NONE, 0);
9861b09c13cSSteffen Eiden }
9871b09c13cSSteffen Eiden 
9881b09c13cSSteffen Eiden static inline bool crste_is_ucas(union crste crste)
9891b09c13cSSteffen Eiden {
9901b09c13cSSteffen Eiden 	return is_pmd(crste) && crste.h.i && crste.h.fc0.tl == 1 && crste.h.fc == 0;
9911b09c13cSSteffen Eiden }
9921b09c13cSSteffen Eiden 
9931b09c13cSSteffen Eiden #endif /* ARCH_KVM_GMAP_DAT_H */
994