1 /* 2 * Storage key tests 3 * 4 * Copyright (c) 2018 IBM Corp 5 * 6 * Authors: 7 * Janosch Frank <frankja@linux.vnet.ibm.com> 8 * 9 * This code is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU Library General Public License version 2. 11 */ 12 #include <libcflat.h> 13 #include <asm/asm-offsets.h> 14 #include <asm/interrupt.h> 15 #include <asm/page.h> 16 #include <asm/facility.h> 17 #include <asm/mem.h> 18 19 20 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2))); 21 const unsigned long page0 = (unsigned long)pagebuf; 22 const unsigned long page1 = (unsigned long)(pagebuf + PAGE_SIZE); 23 24 static void test_set_mb(void) 25 { 26 union skey skey, ret1, ret2; 27 unsigned long addr = 0x10000 - 2 * PAGE_SIZE; 28 unsigned long end = 0x10000; 29 30 /* Multi block support came with EDAT 1 */ 31 if (!test_facility(8)) 32 return; 33 34 skey.val = 0x30; 35 while (addr < end) 36 addr = set_storage_key_mb(addr, skey.val); 37 38 ret1.val = get_storage_key(end - PAGE_SIZE) & (SKEY_ACC | SKEY_FP); 39 ret2.val = get_storage_key(end - PAGE_SIZE * 2) & (SKEY_ACC | SKEY_FP); 40 report("multi block", 41 ret1.val == ret2.val && ret1.val == skey.val); 42 } 43 44 static void test_chg(void) 45 { 46 union skey skey1, skey2; 47 48 skey1.val = 0x30; 49 set_storage_key(page0, skey1.val, 0); 50 skey1.val = get_storage_key(page0); 51 pagebuf[0] = 3; 52 skey2.val = get_storage_key(page0); 53 report("chg bit test", !skey1.str.ch && skey2.str.ch); 54 } 55 56 static void test_set(void) 57 { 58 union skey skey, ret; 59 60 skey.val = 0x30; 61 ret.val = get_storage_key(page0); 62 set_storage_key(page0, skey.val, 0); 63 ret.val = get_storage_key(page0); 64 /* 65 * For all set tests we only test the ACC and FP bits. RF and 66 * CH are set by the machine for memory references and changes 67 * and hence might change between a set and a get. 68 */ 69 report("set key test", 70 skey.str.acc == ret.str.acc && skey.str.fp == ret.str.fp); 71 } 72 73 static void test_priv(void) 74 { 75 union skey skey; 76 77 memset(pagebuf, 0, PAGE_SIZE * 2); 78 report_prefix_push("privileged"); 79 report_prefix_push("sske"); 80 expect_pgm_int(); 81 enter_pstate(); 82 set_storage_key(page0, 0x30, 0); 83 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 84 report_prefix_pop(); 85 86 skey.val = get_storage_key(page0); 87 report("skey did not change on exception", skey.str.acc != 3); 88 89 report_prefix_push("iske"); 90 expect_pgm_int(); 91 enter_pstate(); 92 get_storage_key(page0); 93 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 94 report_prefix_pop(); 95 96 report_prefix_pop(); 97 } 98 99 int main(void) 100 { 101 report_prefix_push("skey"); 102 test_priv(); 103 test_set(); 104 test_set_mb(); 105 test_chg(); 106 report_prefix_pop(); 107 return report_summary(); 108 } 109