1f6b354fbSJanosch Frank /* 2f6b354fbSJanosch Frank * Storage key tests 3f6b354fbSJanosch Frank * 4f6b354fbSJanosch Frank * Copyright (c) 2018 IBM Corp 5f6b354fbSJanosch Frank * 6f6b354fbSJanosch Frank * Authors: 7f6b354fbSJanosch Frank * Janosch Frank <frankja@linux.vnet.ibm.com> 8f6b354fbSJanosch Frank * 9f6b354fbSJanosch Frank * This code is free software; you can redistribute it and/or modify it 10f6b354fbSJanosch Frank * under the terms of the GNU Library General Public License version 2. 11f6b354fbSJanosch Frank */ 12f6b354fbSJanosch Frank #include <libcflat.h> 13f6b354fbSJanosch Frank #include <asm/asm-offsets.h> 14f6b354fbSJanosch Frank #include <asm/interrupt.h> 15f6b354fbSJanosch Frank #include <asm/page.h> 16f6b354fbSJanosch Frank #include <asm/facility.h> 17f6b354fbSJanosch Frank #include <asm/mem.h> 18f6b354fbSJanosch Frank 19f6b354fbSJanosch Frank 20f6b354fbSJanosch Frank static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2))); 21f6b354fbSJanosch Frank 22f6b354fbSJanosch Frank static void test_set_mb(void) 23f6b354fbSJanosch Frank { 24f6b354fbSJanosch Frank union skey skey, ret1, ret2; 25*7b9ca995SJanosch Frank void *addr = (void *)0x10000 - 2 * PAGE_SIZE; 26*7b9ca995SJanosch Frank void *end = (void *)0x10000; 27f6b354fbSJanosch Frank 28f6b354fbSJanosch Frank /* Multi block support came with EDAT 1 */ 29f6b354fbSJanosch Frank if (!test_facility(8)) 30f6b354fbSJanosch Frank return; 31f6b354fbSJanosch Frank 32f6b354fbSJanosch Frank skey.val = 0x30; 33f6b354fbSJanosch Frank while (addr < end) 34f6b354fbSJanosch Frank addr = set_storage_key_mb(addr, skey.val); 35f6b354fbSJanosch Frank 36d0bfafdfSJanosch Frank ret1.val = get_storage_key(end - PAGE_SIZE) & (SKEY_ACC | SKEY_FP); 37d0bfafdfSJanosch Frank ret2.val = get_storage_key(end - PAGE_SIZE * 2) & (SKEY_ACC | SKEY_FP); 38d0bfafdfSJanosch Frank report("multi block", 39d0bfafdfSJanosch Frank ret1.val == ret2.val && ret1.val == skey.val); 40f6b354fbSJanosch Frank } 41f6b354fbSJanosch Frank 42f6b354fbSJanosch Frank static void test_chg(void) 43f6b354fbSJanosch Frank { 44f6b354fbSJanosch Frank union skey skey1, skey2; 45f6b354fbSJanosch Frank 46f6b354fbSJanosch Frank skey1.val = 0x30; 47*7b9ca995SJanosch Frank set_storage_key(pagebuf, skey1.val, 0); 48*7b9ca995SJanosch Frank skey1.val = get_storage_key(pagebuf); 49f6b354fbSJanosch Frank pagebuf[0] = 3; 50*7b9ca995SJanosch Frank skey2.val = get_storage_key(pagebuf); 51f6b354fbSJanosch Frank report("chg bit test", !skey1.str.ch && skey2.str.ch); 52f6b354fbSJanosch Frank } 53f6b354fbSJanosch Frank 54f6b354fbSJanosch Frank static void test_set(void) 55f6b354fbSJanosch Frank { 56f6b354fbSJanosch Frank union skey skey, ret; 57f6b354fbSJanosch Frank 58f6b354fbSJanosch Frank skey.val = 0x30; 59*7b9ca995SJanosch Frank ret.val = get_storage_key(pagebuf); 60*7b9ca995SJanosch Frank set_storage_key(pagebuf, skey.val, 0); 61*7b9ca995SJanosch Frank ret.val = get_storage_key(pagebuf); 62d0bfafdfSJanosch Frank /* 63d0bfafdfSJanosch Frank * For all set tests we only test the ACC and FP bits. RF and 64d0bfafdfSJanosch Frank * CH are set by the machine for memory references and changes 65d0bfafdfSJanosch Frank * and hence might change between a set and a get. 66d0bfafdfSJanosch Frank */ 67d0bfafdfSJanosch Frank report("set key test", 68d0bfafdfSJanosch Frank skey.str.acc == ret.str.acc && skey.str.fp == ret.str.fp); 69f6b354fbSJanosch Frank } 70f6b354fbSJanosch Frank 711018ec15SThomas Huth /* Returns true if we are running under z/VM 6.x */ 721018ec15SThomas Huth static bool check_for_zvm6(void) 731018ec15SThomas Huth { 741018ec15SThomas Huth int dcbt; /* Descriptor block count */ 751018ec15SThomas Huth int nr; 761018ec15SThomas Huth static const unsigned char zvm6[] = { 771018ec15SThomas Huth /* This is "z/VM 6" in EBCDIC */ 781018ec15SThomas Huth 0xa9, 0x61, 0xe5, 0xd4, 0x40, 0x40, 0x40, 0x40, 0xf6 791018ec15SThomas Huth }; 801018ec15SThomas Huth 811018ec15SThomas Huth if (stsi(pagebuf, 3, 2, 2)) 821018ec15SThomas Huth return false; 831018ec15SThomas Huth 841018ec15SThomas Huth dcbt = pagebuf[31] & 0xf; 851018ec15SThomas Huth 861018ec15SThomas Huth for (nr = 0; nr < dcbt; nr++) { 871018ec15SThomas Huth if (!memcmp(&pagebuf[32 + nr * 64 + 24], zvm6, sizeof(zvm6))) 881018ec15SThomas Huth return true; 891018ec15SThomas Huth } 901018ec15SThomas Huth 911018ec15SThomas Huth return false; 921018ec15SThomas Huth } 931018ec15SThomas Huth 94f6b354fbSJanosch Frank static void test_priv(void) 95f6b354fbSJanosch Frank { 96f6b354fbSJanosch Frank union skey skey; 971018ec15SThomas Huth bool is_zvm6 = check_for_zvm6(); 98f6b354fbSJanosch Frank 99f6b354fbSJanosch Frank memset(pagebuf, 0, PAGE_SIZE * 2); 100e4654a1bSJanosch Frank report_prefix_push("privileged"); 101e4654a1bSJanosch Frank report_prefix_push("sske"); 102f6b354fbSJanosch Frank expect_pgm_int(); 103f6b354fbSJanosch Frank enter_pstate(); 104*7b9ca995SJanosch Frank set_storage_key(pagebuf, 0x30, 0); 105f6b354fbSJanosch Frank check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 106e4654a1bSJanosch Frank report_prefix_pop(); 107f6b354fbSJanosch Frank 108*7b9ca995SJanosch Frank skey.val = get_storage_key(pagebuf); 109f6b354fbSJanosch Frank report("skey did not change on exception", skey.str.acc != 3); 110f6b354fbSJanosch Frank 111e4654a1bSJanosch Frank report_prefix_push("iske"); 1121018ec15SThomas Huth if (is_zvm6) { 1131018ec15SThomas Huth /* There is a known bug with z/VM 6, so skip the test there */ 1141018ec15SThomas Huth report_skip("not working on z/VM 6"); 1151018ec15SThomas Huth } else { 116f6b354fbSJanosch Frank expect_pgm_int(); 117f6b354fbSJanosch Frank enter_pstate(); 118*7b9ca995SJanosch Frank get_storage_key(pagebuf); 119f6b354fbSJanosch Frank check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 1201018ec15SThomas Huth } 121e4654a1bSJanosch Frank report_prefix_pop(); 122e4654a1bSJanosch Frank 123e4654a1bSJanosch Frank report_prefix_pop(); 124f6b354fbSJanosch Frank } 125f6b354fbSJanosch Frank 126f6b354fbSJanosch Frank int main(void) 127f6b354fbSJanosch Frank { 128f6b354fbSJanosch Frank report_prefix_push("skey"); 129f6b354fbSJanosch Frank test_priv(); 130f6b354fbSJanosch Frank test_set(); 131f6b354fbSJanosch Frank test_set_mb(); 132f6b354fbSJanosch Frank test_chg(); 133f6b354fbSJanosch Frank report_prefix_pop(); 134f6b354fbSJanosch Frank return report_summary(); 135f6b354fbSJanosch Frank } 136