^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * guest access functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright IBM Corp. 2014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mm_types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pgtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/gmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "kvm-s390.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "gaccess.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/switch_to.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) union asce {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned long origin : 52; /* Region- or Segment-Table Origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned long g : 1; /* Subspace Group Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned long p : 1; /* Private Space Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long s : 1; /* Storage-Alteration-Event Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long x : 1; /* Space-Switch-Event Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long r : 1; /* Real-Space Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned long dt : 2; /* Designation-Type Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned long tl : 2; /* Region- or Segment-Table Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ASCE_TYPE_SEGMENT = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ASCE_TYPE_REGION3 = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ASCE_TYPE_REGION2 = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ASCE_TYPE_REGION1 = 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) union region1_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned long rto: 52;/* Region-Table Origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned long p : 1; /* DAT-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long tf : 2; /* Region-Second-Table Offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned long i : 1; /* Region-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned long tt : 2; /* Table-Type Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned long tl : 2; /* Region-Second-Table Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) union region2_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned long rto: 52;/* Region-Table Origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned long p : 1; /* DAT-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned long tf : 2; /* Region-Third-Table Offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned long i : 1; /* Region-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned long tt : 2; /* Table-Type Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned long tl : 2; /* Region-Third-Table Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct region3_table_entry_fc0 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned long sto: 52;/* Segment-Table Origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long fc : 1; /* Format-Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned long p : 1; /* DAT-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned long tf : 2; /* Segment-Table Offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned long i : 1; /* Region-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned long cr : 1; /* Common-Region Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned long tt : 2; /* Table-Type Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned long tl : 2; /* Segment-Table Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct region3_table_entry_fc1 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned long rfaa : 33; /* Region-Frame Absolute Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned long : 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) unsigned long av : 1; /* ACCF-Validity Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long acc: 4; /* Access-Control Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned long f : 1; /* Fetch-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned long fc : 1; /* Format-Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned long p : 1; /* DAT-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned long iep: 1; /* Instruction-Execution-Protection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned long i : 1; /* Region-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned long cr : 1; /* Common-Region Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned long tt : 2; /* Table-Type Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) union region3_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct region3_table_entry_fc0 fc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct region3_table_entry_fc1 fc1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned long : 53;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned long fc : 1; /* Format-Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) unsigned long : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned long i : 1; /* Region-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned long cr : 1; /* Common-Region Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned long tt : 2; /* Table-Type Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct segment_entry_fc0 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned long pto: 53;/* Page-Table Origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned long fc : 1; /* Format-Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned long p : 1; /* DAT-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned long : 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned long i : 1; /* Segment-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned long cs : 1; /* Common-Segment Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned long tt : 2; /* Table-Type Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct segment_entry_fc1 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned long sfaa : 44; /* Segment-Frame Absolute Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned long : 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) unsigned long av : 1; /* ACCF-Validity Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned long acc: 4; /* Access-Control Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) unsigned long f : 1; /* Fetch-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned long fc : 1; /* Format-Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned long p : 1; /* DAT-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned long iep: 1; /* Instruction-Execution-Protection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) unsigned long i : 1; /* Segment-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned long cs : 1; /* Common-Segment Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned long tt : 2; /* Table-Type Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) union segment_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct segment_entry_fc0 fc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct segment_entry_fc1 fc1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned long : 53;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned long fc : 1; /* Format-Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned long : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned long i : 1; /* Segment-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned long cs : 1; /* Common-Segment Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned long tt : 2; /* Table-Type Bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) TABLE_TYPE_SEGMENT = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) TABLE_TYPE_REGION3 = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) TABLE_TYPE_REGION2 = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) TABLE_TYPE_REGION1 = 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) union page_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned long pfra : 52; /* Page-Frame Real Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) unsigned long z : 1; /* Zero Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned long i : 1; /* Page-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned long p : 1; /* DAT-Protection Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned long iep: 1; /* Instruction-Execution-Protection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned long : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * vaddress union in order to easily decode a virtual address into its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * region first index, region second index etc. parts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) union vaddress {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned long rfx : 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned long rsx : 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned long rtx : 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) unsigned long sx : 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) unsigned long px : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) unsigned long bx : 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned long rfx01 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) unsigned long : 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned long rsx01 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) unsigned long : 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) unsigned long rtx01 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) unsigned long : 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) unsigned long sx01 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) unsigned long : 29;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * raddress union which will contain the result (real or absolute address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * after a page table walk. The rfaa, sfaa and pfra members are used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * simply assign them the value of a region, segment or page table entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) union raddress {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) unsigned long rfaa : 33; /* Region-Frame Absolute Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned long sfaa : 44; /* Segment-Frame Absolute Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) unsigned long pfra : 52; /* Page-Frame Real Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) union alet {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) u32 reserved : 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) u32 p : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u32 alesn : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u32 alen : 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) union ald {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u32 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u32 alo : 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) u32 all : 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct ale {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unsigned long i : 1; /* ALEN-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned long : 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) unsigned long fo : 1; /* Fetch-Only Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) unsigned long p : 1; /* Private Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) unsigned long alesn : 8; /* Access-List-Entry Sequence Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) unsigned long aleax : 16; /* Access-List-Entry Authorization Index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) unsigned long : 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) unsigned long asteo : 25; /* ASN-Second-Table-Entry Origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned long : 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned long astesn : 32; /* ASTE Sequence Number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct aste {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned long i : 1; /* ASX-Invalid Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) unsigned long ato : 29; /* Authority-Table Origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) unsigned long : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) unsigned long b : 1; /* Base-Space Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) unsigned long ax : 16; /* Authorization Index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) unsigned long atl : 12; /* Authority-Table Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) unsigned long ca : 1; /* Controlled-ASN Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) unsigned long ra : 1; /* Reusable-ASN Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) unsigned long asce : 64; /* Address-Space-Control Element */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) unsigned long ald : 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned long astesn : 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* .. more fields there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int ipte_lock_held(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (vcpu->arch.sie_block->eca & ECA_SII) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) read_lock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) rc = kvm_s390_get_ipte_control(vcpu->kvm)->kh != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) read_unlock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return vcpu->kvm->arch.ipte_lock_count != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static void ipte_lock_simple(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) union ipte_control old, new, *ic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) mutex_lock(&vcpu->kvm->arch.ipte_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) vcpu->kvm->arch.ipte_lock_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (vcpu->kvm->arch.ipte_lock_count > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) read_lock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ic = kvm_s390_get_ipte_control(vcpu->kvm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) old = READ_ONCE(*ic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (old.k) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) read_unlock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) new = old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) new.k = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) read_unlock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) mutex_unlock(&vcpu->kvm->arch.ipte_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static void ipte_unlock_simple(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) union ipte_control old, new, *ic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) mutex_lock(&vcpu->kvm->arch.ipte_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) vcpu->kvm->arch.ipte_lock_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (vcpu->kvm->arch.ipte_lock_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) read_lock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) ic = kvm_s390_get_ipte_control(vcpu->kvm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) old = READ_ONCE(*ic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) new = old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) new.k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) read_unlock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) wake_up(&vcpu->kvm->arch.ipte_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) mutex_unlock(&vcpu->kvm->arch.ipte_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static void ipte_lock_siif(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) union ipte_control old, new, *ic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) read_lock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ic = kvm_s390_get_ipte_control(vcpu->kvm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) old = READ_ONCE(*ic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (old.kg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) read_unlock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) new = old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) new.k = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) new.kh++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) read_unlock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static void ipte_unlock_siif(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) union ipte_control old, new, *ic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) read_lock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) ic = kvm_s390_get_ipte_control(vcpu->kvm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) old = READ_ONCE(*ic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) new = old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) new.kh--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (!new.kh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) new.k = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) read_unlock(&vcpu->kvm->arch.sca_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (!new.kh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) wake_up(&vcpu->kvm->arch.ipte_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) void ipte_lock(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (vcpu->arch.sie_block->eca & ECA_SII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ipte_lock_siif(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ipte_lock_simple(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) void ipte_unlock(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (vcpu->arch.sie_block->eca & ECA_SII)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ipte_unlock_siif(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) ipte_unlock_simple(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, u8 ar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) enum gacc_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) union alet alet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct ale ale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct aste aste;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) unsigned long ald_addr, authority_table_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) union ald ald;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int eax, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) u8 authority_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (ar >= NUM_ACRS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) save_access_regs(vcpu->run->s.regs.acrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) alet.val = vcpu->run->s.regs.acrs[ar];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (ar == 0 || alet.val == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) asce->val = vcpu->arch.sie_block->gcr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) } else if (alet.val == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) asce->val = vcpu->arch.sie_block->gcr[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (alet.reserved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return PGM_ALET_SPECIFICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (alet.p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ald_addr = vcpu->arch.sie_block->gcr[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ald_addr = vcpu->arch.sie_block->gcr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ald_addr &= 0x7fffffc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) rc = read_guest_real(vcpu, ald_addr + 16, &ald.val, sizeof(union ald));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (alet.alen / 8 > ald.all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return PGM_ALEN_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (0x7fffffff - ald.alo * 128 < alet.alen * 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return PGM_ADDRESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) rc = read_guest_real(vcpu, ald.alo * 128 + alet.alen * 16, &ale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) sizeof(struct ale));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (ale.i == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return PGM_ALEN_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (ale.alesn != alet.alesn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return PGM_ALE_SEQUENCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) rc = read_guest_real(vcpu, ale.asteo * 64, &aste, sizeof(struct aste));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (aste.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return PGM_ASTE_VALIDITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (aste.astesn != ale.astesn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return PGM_ASTE_SEQUENCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (ale.p == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) eax = (vcpu->arch.sie_block->gcr[8] >> 16) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (ale.aleax != eax) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (eax / 16 > aste.atl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return PGM_EXTENDED_AUTHORITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) authority_table_addr = aste.ato * 4 + eax / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) rc = read_guest_real(vcpu, authority_table_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) &authority_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) sizeof(u8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if ((authority_table & (0x40 >> ((eax & 3) * 2))) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return PGM_EXTENDED_AUTHORITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (ale.fo == 1 && mode == GACC_STORE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return PGM_PROTECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) asce->val = aste.asce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct trans_exc_code_bits {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) unsigned long addr : 52; /* Translation-exception Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) unsigned long fsi : 2; /* Access Exception Fetch/Store Indication */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) unsigned long : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) unsigned long b56 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) unsigned long : 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) unsigned long b60 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) unsigned long b61 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) unsigned long as : 2; /* ASCE Identifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) FSI_UNKNOWN = 0, /* Unknown wether fetch or store */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) FSI_STORE = 1, /* Exception was due to store operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) FSI_FETCH = 2 /* Exception was due to fetch operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) enum prot_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) PROT_TYPE_LA = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) PROT_TYPE_KEYC = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) PROT_TYPE_ALC = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) PROT_TYPE_DAT = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) PROT_TYPE_IEP = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) u8 ar, enum gacc_mode mode, enum prot_type prot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct trans_exc_code_bits *tec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) memset(pgm, 0, sizeof(*pgm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) pgm->code = code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) tec = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) switch (code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) case PGM_PROTECTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) switch (prot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) case PROT_TYPE_IEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) tec->b61 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) case PROT_TYPE_LA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) tec->b56 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case PROT_TYPE_KEYC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) tec->b60 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case PROT_TYPE_ALC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) tec->b60 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case PROT_TYPE_DAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) tec->b61 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case PGM_ASCE_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) case PGM_PAGE_TRANSLATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) case PGM_REGION_FIRST_TRANS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) case PGM_REGION_SECOND_TRANS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) case PGM_REGION_THIRD_TRANS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case PGM_SEGMENT_TRANSLATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * op_access_id only applies to MOVE_PAGE -> set bit 61
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * exc_access_id has to be set to 0 for some instructions. Both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * cases have to be handled by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) tec->addr = gva >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) tec->fsi = mode == GACC_STORE ? FSI_STORE : FSI_FETCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) tec->as = psw_bits(vcpu->arch.sie_block->gpsw).as;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) case PGM_ALEN_TRANSLATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) case PGM_ALE_SEQUENCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) case PGM_ASTE_VALIDITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) case PGM_ASTE_SEQUENCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) case PGM_EXTENDED_AUTHORITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * We can always store exc_access_id, as it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * undefined for non-ar cases. It is undefined for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * most DAT protection exceptions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) pgm->exc_access_id = ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static int get_vcpu_asce(struct kvm_vcpu *vcpu, union asce *asce,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) unsigned long ga, u8 ar, enum gacc_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct psw_bits psw = psw_bits(vcpu->arch.sie_block->gpsw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (!psw.dat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) asce->val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) asce->r = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if ((mode == GACC_IFETCH) && (psw.as != PSW_BITS_AS_HOME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) psw.as = PSW_BITS_AS_PRIMARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) switch (psw.as) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) case PSW_BITS_AS_PRIMARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) asce->val = vcpu->arch.sie_block->gcr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) case PSW_BITS_AS_SECONDARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) asce->val = vcpu->arch.sie_block->gcr[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) case PSW_BITS_AS_HOME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) asce->val = vcpu->arch.sie_block->gcr[13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) case PSW_BITS_AS_ACCREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) rc = ar_translation(vcpu, asce, ar, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (rc > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return trans_exc(vcpu, rc, ga, ar, mode, PROT_TYPE_ALC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int deref_table(struct kvm *kvm, unsigned long gpa, unsigned long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return kvm_read_guest(kvm, gpa, val, sizeof(*val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * guest_translate - translate a guest virtual into a guest absolute address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * @vcpu: virtual cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * @gva: guest virtual address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * @gpa: points to where guest physical (absolute) address should be stored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * @asce: effective asce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * @mode: indicates the access mode to be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * @prot: returns the type for protection exceptions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * Translate a guest virtual address into a guest absolute address by means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * of dynamic address translation as specified by the architecture.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * If the resulting absolute address is not available in the configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * an addressing exception is indicated and @gpa will not be changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * Returns: - zero on success; @gpa contains the resulting absolute address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * - a negative value if guest access failed due to e.g. broken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * guest mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * - a positve value if an access exception happened. In this case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * the returned value is the program interruption code as defined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * by the architecture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) unsigned long *gpa, const union asce asce,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) enum gacc_mode mode, enum prot_type *prot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) union vaddress vaddr = {.addr = gva};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) union raddress raddr = {.addr = gva};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) union page_table_entry pte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int dat_protection = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) int iep_protection = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) union ctlreg0 ctlreg0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) unsigned long ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int edat1, edat2, iep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ctlreg0.val = vcpu->arch.sie_block->gcr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) edat1 = ctlreg0.edat && test_kvm_facility(vcpu->kvm, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) edat2 = edat1 && test_kvm_facility(vcpu->kvm, 78);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) iep = ctlreg0.iep && test_kvm_facility(vcpu->kvm, 130);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (asce.r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) goto real_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ptr = asce.origin * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) switch (asce.dt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) case ASCE_TYPE_REGION1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (vaddr.rfx01 > asce.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return PGM_REGION_FIRST_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ptr += vaddr.rfx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) case ASCE_TYPE_REGION2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (vaddr.rfx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return PGM_ASCE_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (vaddr.rsx01 > asce.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return PGM_REGION_SECOND_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ptr += vaddr.rsx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) case ASCE_TYPE_REGION3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (vaddr.rfx || vaddr.rsx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return PGM_ASCE_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (vaddr.rtx01 > asce.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return PGM_REGION_THIRD_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ptr += vaddr.rtx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) case ASCE_TYPE_SEGMENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (vaddr.rfx || vaddr.rsx || vaddr.rtx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return PGM_ASCE_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (vaddr.sx01 > asce.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return PGM_SEGMENT_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ptr += vaddr.sx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) switch (asce.dt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) case ASCE_TYPE_REGION1: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) union region1_table_entry rfte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (kvm_is_error_gpa(vcpu->kvm, ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return PGM_ADDRESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (deref_table(vcpu->kvm, ptr, &rfte.val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (rfte.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return PGM_REGION_FIRST_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (rfte.tt != TABLE_TYPE_REGION1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (vaddr.rsx01 < rfte.tf || vaddr.rsx01 > rfte.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return PGM_REGION_SECOND_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (edat1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dat_protection |= rfte.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ptr = rfte.rto * PAGE_SIZE + vaddr.rsx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) case ASCE_TYPE_REGION2: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) union region2_table_entry rste;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (kvm_is_error_gpa(vcpu->kvm, ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return PGM_ADDRESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (deref_table(vcpu->kvm, ptr, &rste.val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (rste.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return PGM_REGION_SECOND_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (rste.tt != TABLE_TYPE_REGION2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (vaddr.rtx01 < rste.tf || vaddr.rtx01 > rste.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return PGM_REGION_THIRD_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (edat1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) dat_protection |= rste.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ptr = rste.rto * PAGE_SIZE + vaddr.rtx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) case ASCE_TYPE_REGION3: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) union region3_table_entry rtte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (kvm_is_error_gpa(vcpu->kvm, ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return PGM_ADDRESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (deref_table(vcpu->kvm, ptr, &rtte.val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (rtte.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return PGM_REGION_THIRD_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (rtte.tt != TABLE_TYPE_REGION3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (rtte.cr && asce.p && edat2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (rtte.fc && edat2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) dat_protection |= rtte.fc1.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) iep_protection = rtte.fc1.iep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) raddr.rfaa = rtte.fc1.rfaa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) goto absolute_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (vaddr.sx01 < rtte.fc0.tf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return PGM_SEGMENT_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (vaddr.sx01 > rtte.fc0.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return PGM_SEGMENT_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (edat1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) dat_protection |= rtte.fc0.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ptr = rtte.fc0.sto * PAGE_SIZE + vaddr.sx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) case ASCE_TYPE_SEGMENT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) union segment_table_entry ste;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (kvm_is_error_gpa(vcpu->kvm, ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return PGM_ADDRESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (deref_table(vcpu->kvm, ptr, &ste.val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (ste.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return PGM_SEGMENT_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (ste.tt != TABLE_TYPE_SEGMENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (ste.cs && asce.p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (ste.fc && edat1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) dat_protection |= ste.fc1.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) iep_protection = ste.fc1.iep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) raddr.sfaa = ste.fc1.sfaa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) goto absolute_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) dat_protection |= ste.fc0.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ptr = ste.fc0.pto * (PAGE_SIZE / 2) + vaddr.px * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (kvm_is_error_gpa(vcpu->kvm, ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return PGM_ADDRESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (deref_table(vcpu->kvm, ptr, &pte.val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (pte.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return PGM_PAGE_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (pte.z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) dat_protection |= pte.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) iep_protection = pte.iep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) raddr.pfra = pte.pfra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) real_address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) raddr.addr = kvm_s390_real_to_abs(vcpu, raddr.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) absolute_address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (mode == GACC_STORE && dat_protection) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) *prot = PROT_TYPE_DAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return PGM_PROTECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (mode == GACC_IFETCH && iep_protection && iep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) *prot = PROT_TYPE_IEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return PGM_PROTECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (kvm_is_error_gpa(vcpu->kvm, raddr.addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return PGM_ADDRESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) *gpa = raddr.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) static inline int is_low_address(unsigned long ga)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* Check for address ranges 0..511 and 4096..4607 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return (ga & ~0x11fful) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static int low_address_protection_enabled(struct kvm_vcpu *vcpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) const union asce asce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) union ctlreg0 ctlreg0 = {.val = vcpu->arch.sie_block->gcr[0]};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) psw_t *psw = &vcpu->arch.sie_block->gpsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (!ctlreg0.lap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (psw_bits(*psw).dat && asce.p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) unsigned long *pages, unsigned long nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) const union asce asce, enum gacc_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) psw_t *psw = &vcpu->arch.sie_block->gpsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) int lap_enabled, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) enum prot_type prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) lap_enabled = low_address_protection_enabled(vcpu, asce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) while (nr_pages) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ga = kvm_s390_logical_to_effective(vcpu, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (mode == GACC_STORE && lap_enabled && is_low_address(ga))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return trans_exc(vcpu, PGM_PROTECTION, ga, ar, mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) PROT_TYPE_LA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) ga &= PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (psw_bits(*psw).dat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) rc = guest_translate(vcpu, ga, pages, asce, mode, &prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) *pages = kvm_s390_real_to_abs(vcpu, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (kvm_is_error_gpa(vcpu->kvm, *pages))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) rc = PGM_ADDRESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return trans_exc(vcpu, rc, ga, ar, mode, prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ga += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) pages++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) nr_pages--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) unsigned long len, enum gacc_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) psw_t *psw = &vcpu->arch.sie_block->gpsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) unsigned long _len, nr_pages, gpa, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) unsigned long pages_array[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) unsigned long *pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int need_ipte_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) union asce asce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ga = kvm_s390_logical_to_effective(vcpu, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) rc = get_vcpu_asce(vcpu, &asce, ga, ar, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) pages = pages_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (nr_pages > ARRAY_SIZE(pages_array))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) pages = vmalloc(array_size(nr_pages, sizeof(unsigned long)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (!pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) need_ipte_lock = psw_bits(*psw).dat && !asce.r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (need_ipte_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) ipte_lock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) rc = guest_page_range(vcpu, ga, ar, pages, nr_pages, asce, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) for (idx = 0; idx < nr_pages && !rc; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) gpa = *(pages + idx) + (ga & ~PAGE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) _len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (mode == GACC_STORE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) rc = kvm_write_guest(vcpu->kvm, gpa, data, _len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) rc = kvm_read_guest(vcpu->kvm, gpa, data, _len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) len -= _len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ga += _len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) data += _len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (need_ipte_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) ipte_unlock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (nr_pages > ARRAY_SIZE(pages_array))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) vfree(pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) void *data, unsigned long len, enum gacc_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) unsigned long _len, gpa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) while (len && !rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) gpa = kvm_s390_real_to_abs(vcpu, gra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) _len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) rc = write_guest_abs(vcpu, gpa, data, _len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) rc = read_guest_abs(vcpu, gpa, data, _len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) len -= _len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) gra += _len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) data += _len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * guest_translate_address - translate guest logical into guest absolute address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * Parameter semantics are the same as the ones from guest_translate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * The memory contents at the guest address are not changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * Note: The IPTE lock is not taken during this function, so the caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * has to take care of this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) unsigned long *gpa, enum gacc_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) psw_t *psw = &vcpu->arch.sie_block->gpsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) enum prot_type prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) union asce asce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) gva = kvm_s390_logical_to_effective(vcpu, gva);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) rc = get_vcpu_asce(vcpu, &asce, gva, ar, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (is_low_address(gva) && low_address_protection_enabled(vcpu, asce)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (mode == GACC_STORE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return trans_exc(vcpu, PGM_PROTECTION, gva, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) mode, PROT_TYPE_LA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (psw_bits(*psw).dat && !asce.r) { /* Use DAT? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) rc = guest_translate(vcpu, gva, gpa, asce, mode, &prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (rc > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return trans_exc(vcpu, rc, gva, 0, mode, prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) *gpa = kvm_s390_real_to_abs(vcpu, gva);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (kvm_is_error_gpa(vcpu->kvm, *gpa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return trans_exc(vcpu, rc, gva, PGM_ADDRESSING, mode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) * check_gva_range - test a range of guest virtual addresses for accessibility
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) unsigned long length, enum gacc_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) unsigned long gpa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) unsigned long currlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) ipte_lock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) while (length > 0 && !rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) currlen = min(length, PAGE_SIZE - (gva % PAGE_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) rc = guest_translate_address(vcpu, gva, ar, &gpa, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) gva += currlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) length -= currlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) ipte_unlock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * kvm_s390_check_low_addr_prot_real - check for low-address protection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) * @gra: Guest real address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * Checks whether an address is subject to low-address protection and set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * up vcpu->arch.pgm accordingly if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * Return: 0 if no protection exception, or PGM_PROTECTION if protected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) int kvm_s390_check_low_addr_prot_real(struct kvm_vcpu *vcpu, unsigned long gra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) union ctlreg0 ctlreg0 = {.val = vcpu->arch.sie_block->gcr[0]};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (!ctlreg0.lap || !is_low_address(gra))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return trans_exc(vcpu, PGM_PROTECTION, gra, 0, GACC_STORE, PROT_TYPE_LA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) * kvm_s390_shadow_tables - walk the guest page table and create shadow tables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) * @sg: pointer to the shadow guest address space structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * @saddr: faulting address in the shadow gmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * @pgt: pointer to the beginning of the page table for the given address if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * successful (return value 0), or to the first invalid DAT entry in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * case of exceptions (return value > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) * @fake: pgt references contiguous guest memory block, not a pgtable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) unsigned long *pgt, int *dat_protection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) int *fake)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) struct gmap *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) union asce asce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) union vaddress vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) unsigned long ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) *fake = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) *dat_protection = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) parent = sg->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) vaddr.addr = saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) asce.val = sg->orig_asce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ptr = asce.origin * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (asce.r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) *fake = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) asce.dt = ASCE_TYPE_REGION1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) switch (asce.dt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) case ASCE_TYPE_REGION1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (vaddr.rfx01 > asce.tl && !*fake)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return PGM_REGION_FIRST_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) case ASCE_TYPE_REGION2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (vaddr.rfx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) return PGM_ASCE_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (vaddr.rsx01 > asce.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return PGM_REGION_SECOND_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) case ASCE_TYPE_REGION3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (vaddr.rfx || vaddr.rsx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return PGM_ASCE_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (vaddr.rtx01 > asce.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return PGM_REGION_THIRD_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) case ASCE_TYPE_SEGMENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (vaddr.rfx || vaddr.rsx || vaddr.rtx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return PGM_ASCE_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (vaddr.sx01 > asce.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return PGM_SEGMENT_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) switch (asce.dt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) case ASCE_TYPE_REGION1: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) union region1_table_entry rfte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (*fake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) ptr += vaddr.rfx * _REGION1_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) rfte.val = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) goto shadow_r2t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) *pgt = ptr + vaddr.rfx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) rc = gmap_read_table(parent, ptr + vaddr.rfx * 8, &rfte.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (rfte.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return PGM_REGION_FIRST_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (rfte.tt != TABLE_TYPE_REGION1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (vaddr.rsx01 < rfte.tf || vaddr.rsx01 > rfte.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return PGM_REGION_SECOND_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (sg->edat_level >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) *dat_protection |= rfte.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) ptr = rfte.rto * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) shadow_r2t:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) rc = gmap_shadow_r2t(sg, saddr, rfte.val, *fake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case ASCE_TYPE_REGION2: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) union region2_table_entry rste;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (*fake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) ptr += vaddr.rsx * _REGION2_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) rste.val = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) goto shadow_r3t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) *pgt = ptr + vaddr.rsx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) rc = gmap_read_table(parent, ptr + vaddr.rsx * 8, &rste.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (rste.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return PGM_REGION_SECOND_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (rste.tt != TABLE_TYPE_REGION2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (vaddr.rtx01 < rste.tf || vaddr.rtx01 > rste.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) return PGM_REGION_THIRD_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (sg->edat_level >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) *dat_protection |= rste.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) ptr = rste.rto * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) shadow_r3t:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) rste.p |= *dat_protection;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) rc = gmap_shadow_r3t(sg, saddr, rste.val, *fake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) case ASCE_TYPE_REGION3: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) union region3_table_entry rtte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (*fake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) ptr += vaddr.rtx * _REGION3_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) rtte.val = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) goto shadow_sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) *pgt = ptr + vaddr.rtx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) rc = gmap_read_table(parent, ptr + vaddr.rtx * 8, &rtte.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (rtte.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return PGM_REGION_THIRD_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (rtte.tt != TABLE_TYPE_REGION3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (rtte.cr && asce.p && sg->edat_level >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (rtte.fc && sg->edat_level >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) *dat_protection |= rtte.fc0.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) *fake = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) ptr = rtte.fc1.rfaa * _REGION3_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) rtte.val = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) goto shadow_sgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (vaddr.sx01 < rtte.fc0.tf || vaddr.sx01 > rtte.fc0.tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return PGM_SEGMENT_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (sg->edat_level >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) *dat_protection |= rtte.fc0.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) ptr = rtte.fc0.sto * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) shadow_sgt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) rtte.fc0.p |= *dat_protection;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) rc = gmap_shadow_sgt(sg, saddr, rtte.val, *fake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) case ASCE_TYPE_SEGMENT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) union segment_table_entry ste;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (*fake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) ptr += vaddr.sx * _SEGMENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) ste.val = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) goto shadow_pgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) *pgt = ptr + vaddr.sx * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) rc = gmap_read_table(parent, ptr + vaddr.sx * 8, &ste.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (ste.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return PGM_SEGMENT_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if (ste.tt != TABLE_TYPE_SEGMENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) if (ste.cs && asce.p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) return PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) *dat_protection |= ste.fc0.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (ste.fc && sg->edat_level >= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) *fake = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) ptr = ste.fc1.sfaa * _SEGMENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) ste.val = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) goto shadow_pgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) ptr = ste.fc0.pto * (PAGE_SIZE / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) shadow_pgt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) ste.fc0.p |= *dat_protection;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) rc = gmap_shadow_pgt(sg, saddr, ste.val, *fake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* Return the parent address of the page table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) *pgt = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * kvm_s390_shadow_fault - handle fault on a shadow page table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * @vcpu: virtual cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * @sg: pointer to the shadow guest address space structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * @saddr: faulting address in the shadow gmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * @datptr: will contain the address of the faulting DAT table entry, or of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) * the valid leaf, plus some flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * Returns: - 0 if the shadow fault was successfully resolved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * - > 0 (pgm exception code) on exceptions while faulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * - -EAGAIN if the caller can retry immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) * - -EFAULT when accessing invalid guest addresses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) * - -ENOMEM if out of memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) unsigned long saddr, unsigned long *datptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) union vaddress vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) union page_table_entry pte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) unsigned long pgt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) int dat_protection, fake;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) mmap_read_lock(sg->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) * We don't want any guest-2 tables to change - so the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * tables/pointers we read stay valid - unshadowing is however
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * always possible - only guest_table_lock protects us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) ipte_lock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) rc = gmap_shadow_pgt_lookup(sg, saddr, &pgt, &dat_protection, &fake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) rc = kvm_s390_shadow_tables(sg, saddr, &pgt, &dat_protection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) &fake);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) vaddr.addr = saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (fake) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) pte.val = pgt + vaddr.px * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) goto shadow_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) switch (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) case PGM_SEGMENT_TRANSLATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) case PGM_REGION_THIRD_TRANS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) case PGM_REGION_SECOND_TRANS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) case PGM_REGION_FIRST_TRANS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) pgt |= PEI_NOT_PTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) pgt += vaddr.px * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) rc = gmap_read_table(sg->parent, pgt, &pte.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (datptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) *datptr = pgt | dat_protection * PEI_DAT_PROT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (!rc && pte.i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) rc = PGM_PAGE_TRANSLATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (!rc && pte.z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) rc = PGM_TRANSLATION_SPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) shadow_page:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) pte.p |= dat_protection;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) rc = gmap_shadow_page(sg, saddr, __pte(pte.val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) ipte_unlock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) mmap_read_unlock(sg->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }