1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Storage key tests 4 * 5 * Copyright (c) 2018 IBM Corp 6 * 7 * Authors: 8 * Janosch Frank <frankja@linux.vnet.ibm.com> 9 */ 10 #include <libcflat.h> 11 #include <asm/asm-offsets.h> 12 #include <asm/interrupt.h> 13 #include <vmalloc.h> 14 #include <asm/page.h> 15 #include <asm/facility.h> 16 #include <asm/mem.h> 17 18 19 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2))); 20 21 static void test_set_mb(void) 22 { 23 union skey skey, ret1, ret2; 24 void *addr = (void *)0x10000 - 2 * PAGE_SIZE; 25 void *end = (void *)0x10000; 26 27 /* Multi block support came with EDAT 1 */ 28 if (!test_facility(8)) 29 return; 30 31 skey.val = 0x30; 32 while (addr < end) 33 addr = set_storage_key_mb(addr, skey.val); 34 35 ret1.val = get_storage_key(end - PAGE_SIZE) & (SKEY_ACC | SKEY_FP); 36 ret2.val = get_storage_key(end - PAGE_SIZE * 2) & (SKEY_ACC | SKEY_FP); 37 report(ret1.val == ret2.val && ret1.val == skey.val, "multi block"); 38 } 39 40 static void test_chg(void) 41 { 42 union skey skey1, skey2; 43 44 skey1.val = 0x30; 45 set_storage_key(pagebuf, skey1.val, 0); 46 skey1.val = get_storage_key(pagebuf); 47 pagebuf[0] = 3; 48 skey2.val = get_storage_key(pagebuf); 49 report(!skey1.str.ch && skey2.str.ch, "chg bit test"); 50 } 51 52 static void test_set(void) 53 { 54 union skey skey, ret; 55 56 skey.val = 0x30; 57 ret.val = get_storage_key(pagebuf); 58 set_storage_key(pagebuf, skey.val, 0); 59 ret.val = get_storage_key(pagebuf); 60 /* 61 * For all set tests we only test the ACC and FP bits. RF and 62 * CH are set by the machine for memory references and changes 63 * and hence might change between a set and a get. 64 */ 65 report(skey.str.acc == ret.str.acc && skey.str.fp == ret.str.fp, 66 "set key test"); 67 } 68 69 static void test_priv(void) 70 { 71 union skey skey; 72 73 memset(pagebuf, 0, PAGE_SIZE * 2); 74 report_prefix_push("privileged"); 75 report_prefix_push("sske"); 76 expect_pgm_int(); 77 enter_pstate(); 78 set_storage_key(pagebuf, 0x30, 0); 79 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 80 report_prefix_pop(); 81 82 skey.val = get_storage_key(pagebuf); 83 report(skey.str.acc != 3, "skey did not change on exception"); 84 85 report_prefix_push("iske"); 86 expect_pgm_int(); 87 enter_pstate(); 88 get_storage_key(pagebuf); 89 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 90 report_prefix_pop(); 91 92 report_prefix_pop(); 93 } 94 95 static void test_invalid_address(void) 96 { 97 void *inv_addr = (void *)-1ull; 98 99 report_prefix_push("invalid address"); 100 101 report_prefix_push("sske"); 102 expect_pgm_int(); 103 set_storage_key(inv_addr, 0, 0); 104 check_pgm_int_code(PGM_INT_CODE_ADDRESSING); 105 report_prefix_pop(); 106 107 report_prefix_push("iske"); 108 expect_pgm_int(); 109 get_storage_key(inv_addr); 110 check_pgm_int_code(PGM_INT_CODE_ADDRESSING); 111 report_prefix_pop(); 112 113 report_prefix_push("rrbe"); 114 expect_pgm_int(); 115 reset_reference_bit(inv_addr); 116 check_pgm_int_code(PGM_INT_CODE_ADDRESSING); 117 report_prefix_pop(); 118 119 report_prefix_pop(); 120 } 121 122 static void test_test_protection(void) 123 { 124 unsigned long addr = (unsigned long)pagebuf; 125 126 report_prefix_push("TPROT"); 127 128 set_storage_key(pagebuf, 0x10, 0); 129 report(tprot(addr, 0) == TPROT_READ_WRITE, "zero key: no protection"); 130 report(tprot(addr, 1) == TPROT_READ_WRITE, "matching key: no protection"); 131 132 report_prefix_push("mismatching key"); 133 134 report(tprot(addr, 2) == TPROT_READ, "no fetch protection: store protection"); 135 136 set_storage_key(pagebuf, 0x18, 0); 137 report(tprot(addr, 2) == TPROT_RW_PROTECTED, 138 "fetch protection: fetch & store protection"); 139 140 report_prefix_push("fetch-protection override"); 141 set_storage_key(0, 0x18, 0); 142 report(tprot(0, 2) == TPROT_RW_PROTECTED, "disabled: fetch & store protection"); 143 ctl_set_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE); 144 report(tprot(0, 2) == TPROT_READ, "enabled: store protection"); 145 report(tprot(2048, 2) == TPROT_RW_PROTECTED, "invalid: fetch & store protection"); 146 ctl_clear_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE); 147 set_storage_key(0, 0x00, 0); 148 report_prefix_pop(); 149 150 ctl_set_bit(0, CTL0_STORAGE_PROTECTION_OVERRIDE); 151 set_storage_key(pagebuf, 0x90, 0); 152 report(tprot(addr, 2) == TPROT_READ_WRITE, 153 "storage-protection override: no protection"); 154 ctl_clear_bit(0, CTL0_STORAGE_PROTECTION_OVERRIDE); 155 156 report_prefix_pop(); 157 set_storage_key(pagebuf, 0x00, 0); 158 report_prefix_pop(); 159 } 160 161 /* 162 * Perform STORE CPU ADDRESS (STAP) instruction while temporarily executing 163 * with access key 1. 164 */ 165 static void store_cpu_address_key_1(uint16_t *out) 166 { 167 asm volatile ( 168 "spka 0x10\n\t" 169 "stap %0\n\t" 170 "spka 0\n" 171 : "+Q" (*out) /* exception: old value remains in out -> + constraint */ 172 ); 173 } 174 175 static void test_store_cpu_address(void) 176 { 177 uint16_t *out = (uint16_t *)pagebuf; 178 uint16_t cpu_addr; 179 180 report_prefix_push("STORE CPU ADDRESS"); 181 asm ("stap %0" : "=Q" (cpu_addr)); 182 183 report_prefix_push("zero key"); 184 set_storage_key(pagebuf, 0x20, 0); 185 WRITE_ONCE(*out, 0xbeef); 186 asm ("stap %0" : "=Q" (*out)); 187 report(*out == cpu_addr, "store occurred"); 188 report_prefix_pop(); 189 190 report_prefix_push("matching key"); 191 set_storage_key(pagebuf, 0x10, 0); 192 *out = 0xbeef; 193 store_cpu_address_key_1(out); 194 report(*out == cpu_addr, "store occurred"); 195 report_prefix_pop(); 196 197 report_prefix_push("mismatching key"); 198 set_storage_key(pagebuf, 0x20, 0); 199 expect_pgm_int(); 200 *out = 0xbeef; 201 store_cpu_address_key_1(out); 202 check_pgm_int_code(PGM_INT_CODE_PROTECTION); 203 report(*out == 0xbeef, "no store occurred"); 204 report_prefix_pop(); 205 206 ctl_set_bit(0, CTL0_STORAGE_PROTECTION_OVERRIDE); 207 208 report_prefix_push("storage-protection override, invalid key"); 209 set_storage_key(pagebuf, 0x20, 0); 210 expect_pgm_int(); 211 *out = 0xbeef; 212 store_cpu_address_key_1(out); 213 check_pgm_int_code(PGM_INT_CODE_PROTECTION); 214 report(*out == 0xbeef, "no store occurred"); 215 report_prefix_pop(); 216 217 report_prefix_push("storage-protection override, override key"); 218 set_storage_key(pagebuf, 0x90, 0); 219 *out = 0xbeef; 220 store_cpu_address_key_1(out); 221 report(*out == cpu_addr, "override occurred"); 222 report_prefix_pop(); 223 224 ctl_clear_bit(0, CTL0_STORAGE_PROTECTION_OVERRIDE); 225 226 report_prefix_push("storage-protection override disabled, override key"); 227 set_storage_key(pagebuf, 0x90, 0); 228 expect_pgm_int(); 229 *out = 0xbeef; 230 store_cpu_address_key_1(out); 231 check_pgm_int_code(PGM_INT_CODE_PROTECTION); 232 report(*out == 0xbeef, "no store occurred"); 233 report_prefix_pop(); 234 235 set_storage_key(pagebuf, 0x00, 0); 236 report_prefix_pop(); 237 } 238 239 /* 240 * Perform SET PREFIX (SPX) instruction while temporarily executing 241 * with access key 1. 242 */ 243 static void set_prefix_key_1(uint32_t *prefix_ptr) 244 { 245 asm volatile ( 246 "spka 0x10\n\t" 247 "spx %0\n\t" 248 "spka 0\n" 249 :: "Q" (*prefix_ptr) 250 ); 251 } 252 253 /* 254 * We remapped page 0, making the lowcore inaccessible, which breaks the normal 255 * handler and breaks skipping the faulting instruction. 256 * Just disable dynamic address translation to make things work. 257 */ 258 static void dat_fixup_pgm_int(void) 259 { 260 uint64_t psw_mask = extract_psw_mask(); 261 262 psw_mask &= ~PSW_MASK_DAT; 263 load_psw_mask(psw_mask); 264 } 265 266 #define PREFIX_AREA_SIZE (PAGE_SIZE * 2) 267 static char lowcore_tmp[PREFIX_AREA_SIZE] __attribute__((aligned(PREFIX_AREA_SIZE))); 268 269 /* 270 * Test accessibility of the operand to SET PREFIX given different configurations 271 * with regards to storage keys. That is, check the accessibility of the location 272 * holding the new prefix, not that of the new prefix area. The new prefix area 273 * is a valid lowcore, so that the test does not crash on failure. 274 */ 275 static void test_set_prefix(void) 276 { 277 uint32_t *prefix_ptr = (uint32_t *)pagebuf; 278 uint32_t *no_override_prefix_ptr; 279 uint32_t old_prefix; 280 pgd_t *root; 281 282 report_prefix_push("SET PREFIX"); 283 root = (pgd_t *)(stctg(1) & PAGE_MASK); 284 old_prefix = get_prefix(); 285 memcpy(lowcore_tmp, 0, sizeof(lowcore_tmp)); 286 assert(((uint64_t)&lowcore_tmp >> 31) == 0); 287 *prefix_ptr = (uint32_t)(uint64_t)&lowcore_tmp; 288 289 report_prefix_push("zero key"); 290 set_prefix(old_prefix); 291 set_storage_key(prefix_ptr, 0x20, 0); 292 set_prefix(*prefix_ptr); 293 report(get_prefix() == *prefix_ptr, "set prefix"); 294 report_prefix_pop(); 295 296 report_prefix_push("matching key"); 297 set_prefix(old_prefix); 298 set_storage_key(pagebuf, 0x10, 0); 299 set_prefix_key_1(prefix_ptr); 300 report(get_prefix() == *prefix_ptr, "set prefix"); 301 report_prefix_pop(); 302 303 report_prefix_push("mismatching key"); 304 305 report_prefix_push("no fetch protection"); 306 set_prefix(old_prefix); 307 set_storage_key(pagebuf, 0x20, 0); 308 set_prefix_key_1(prefix_ptr); 309 report(get_prefix() == *prefix_ptr, "set prefix"); 310 report_prefix_pop(); 311 312 report_prefix_push("fetch protection"); 313 set_prefix(old_prefix); 314 set_storage_key(pagebuf, 0x28, 0); 315 expect_pgm_int(); 316 set_prefix_key_1(prefix_ptr); 317 check_pgm_int_code(PGM_INT_CODE_PROTECTION); 318 report(get_prefix() == old_prefix, "did not set prefix"); 319 report_prefix_pop(); 320 321 register_pgm_cleanup_func(dat_fixup_pgm_int); 322 323 report_prefix_push("remapped page, fetch protection"); 324 set_prefix(old_prefix); 325 set_storage_key(pagebuf, 0x28, 0); 326 expect_pgm_int(); 327 install_page(root, virt_to_pte_phys(root, pagebuf), 0); 328 set_prefix_key_1((uint32_t *)0); 329 install_page(root, 0, 0); 330 check_pgm_int_code(PGM_INT_CODE_PROTECTION); 331 report(get_prefix() == old_prefix, "did not set prefix"); 332 report_prefix_pop(); 333 334 ctl_set_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE); 335 336 report_prefix_push("fetch protection override applies"); 337 set_prefix(old_prefix); 338 set_storage_key(pagebuf, 0x28, 0); 339 install_page(root, virt_to_pte_phys(root, pagebuf), 0); 340 set_prefix_key_1((uint32_t *)0); 341 install_page(root, 0, 0); 342 report(get_prefix() == *prefix_ptr, "set prefix"); 343 report_prefix_pop(); 344 345 no_override_prefix_ptr = (uint32_t *)(pagebuf + 2048); 346 WRITE_ONCE(*no_override_prefix_ptr, (uint32_t)(uint64_t)&lowcore_tmp); 347 report_prefix_push("fetch protection override does not apply"); 348 set_prefix(old_prefix); 349 set_storage_key(pagebuf, 0x28, 0); 350 expect_pgm_int(); 351 install_page(root, virt_to_pte_phys(root, pagebuf), 0); 352 set_prefix_key_1((uint32_t *)2048); 353 install_page(root, 0, 0); 354 check_pgm_int_code(PGM_INT_CODE_PROTECTION); 355 report(get_prefix() == old_prefix, "did not set prefix"); 356 report_prefix_pop(); 357 358 ctl_clear_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE); 359 register_pgm_cleanup_func(NULL); 360 report_prefix_pop(); 361 set_storage_key(pagebuf, 0x00, 0); 362 report_prefix_pop(); 363 } 364 365 int main(void) 366 { 367 report_prefix_push("skey"); 368 if (test_facility(169)) { 369 report_skip("storage key removal facility is active"); 370 goto done; 371 } 372 test_priv(); 373 test_invalid_address(); 374 test_set(); 375 test_set_mb(); 376 test_chg(); 377 test_test_protection(); 378 test_store_cpu_address(); 379 380 setup_vm(); 381 test_set_prefix(); 382 done: 383 report_prefix_pop(); 384 return report_summary(); 385 } 386