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