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 const unsigned long page0 = (unsigned long)pagebuf; 22f6b354fbSJanosch Frank const unsigned long page1 = (unsigned long)(pagebuf + PAGE_SIZE); 23f6b354fbSJanosch Frank 24f6b354fbSJanosch Frank static void test_set_mb(void) 25f6b354fbSJanosch Frank { 26f6b354fbSJanosch Frank union skey skey, ret1, ret2; 27f6b354fbSJanosch Frank unsigned long addr = 0x10000 - 2 * PAGE_SIZE; 28f6b354fbSJanosch Frank unsigned long end = 0x10000; 29f6b354fbSJanosch Frank 30f6b354fbSJanosch Frank /* Multi block support came with EDAT 1 */ 31f6b354fbSJanosch Frank if (!test_facility(8)) 32f6b354fbSJanosch Frank return; 33f6b354fbSJanosch Frank 34f6b354fbSJanosch Frank skey.val = 0x30; 35f6b354fbSJanosch Frank while (addr < end) 36f6b354fbSJanosch Frank addr = set_storage_key_mb(addr, skey.val); 37f6b354fbSJanosch Frank 38*d0bfafdfSJanosch Frank ret1.val = get_storage_key(end - PAGE_SIZE) & (SKEY_ACC | SKEY_FP); 39*d0bfafdfSJanosch Frank ret2.val = get_storage_key(end - PAGE_SIZE * 2) & (SKEY_ACC | SKEY_FP); 40*d0bfafdfSJanosch Frank report("multi block", 41*d0bfafdfSJanosch Frank ret1.val == ret2.val && ret1.val == skey.val); 42f6b354fbSJanosch Frank } 43f6b354fbSJanosch Frank 44f6b354fbSJanosch Frank static void test_chg(void) 45f6b354fbSJanosch Frank { 46f6b354fbSJanosch Frank union skey skey1, skey2; 47f6b354fbSJanosch Frank 48f6b354fbSJanosch Frank skey1.val = 0x30; 49f6b354fbSJanosch Frank set_storage_key(page0, skey1.val, 0); 50f6b354fbSJanosch Frank skey1.val = get_storage_key(page0); 51f6b354fbSJanosch Frank pagebuf[0] = 3; 52f6b354fbSJanosch Frank skey2.val = get_storage_key(page0); 53f6b354fbSJanosch Frank report("chg bit test", !skey1.str.ch && skey2.str.ch); 54f6b354fbSJanosch Frank } 55f6b354fbSJanosch Frank 56f6b354fbSJanosch Frank static void test_set(void) 57f6b354fbSJanosch Frank { 58f6b354fbSJanosch Frank union skey skey, ret; 59f6b354fbSJanosch Frank 60f6b354fbSJanosch Frank skey.val = 0x30; 61f6b354fbSJanosch Frank ret.val = get_storage_key(page0); 62f6b354fbSJanosch Frank set_storage_key(page0, skey.val, 0); 63f6b354fbSJanosch Frank ret.val = get_storage_key(page0); 64*d0bfafdfSJanosch Frank /* 65*d0bfafdfSJanosch Frank * For all set tests we only test the ACC and FP bits. RF and 66*d0bfafdfSJanosch Frank * CH are set by the machine for memory references and changes 67*d0bfafdfSJanosch Frank * and hence might change between a set and a get. 68*d0bfafdfSJanosch Frank */ 69*d0bfafdfSJanosch Frank report("set key test", 70*d0bfafdfSJanosch Frank skey.str.acc == ret.str.acc && skey.str.fp == ret.str.fp); 71f6b354fbSJanosch Frank } 72f6b354fbSJanosch Frank 73f6b354fbSJanosch Frank static void test_priv(void) 74f6b354fbSJanosch Frank { 75f6b354fbSJanosch Frank union skey skey; 76f6b354fbSJanosch Frank 77f6b354fbSJanosch Frank memset(pagebuf, 0, PAGE_SIZE * 2); 78e4654a1bSJanosch Frank report_prefix_push("privileged"); 79e4654a1bSJanosch Frank report_prefix_push("sske"); 80f6b354fbSJanosch Frank expect_pgm_int(); 81f6b354fbSJanosch Frank enter_pstate(); 82f6b354fbSJanosch Frank set_storage_key(page0, 0x30, 0); 83f6b354fbSJanosch Frank check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 84e4654a1bSJanosch Frank report_prefix_pop(); 85f6b354fbSJanosch Frank 86f6b354fbSJanosch Frank skey.val = get_storage_key(page0); 87f6b354fbSJanosch Frank report("skey did not change on exception", skey.str.acc != 3); 88f6b354fbSJanosch Frank 89e4654a1bSJanosch Frank report_prefix_push("iske"); 90f6b354fbSJanosch Frank expect_pgm_int(); 91f6b354fbSJanosch Frank enter_pstate(); 92f6b354fbSJanosch Frank get_storage_key(page0); 93f6b354fbSJanosch Frank check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 94e4654a1bSJanosch Frank report_prefix_pop(); 95e4654a1bSJanosch Frank 96e4654a1bSJanosch Frank report_prefix_pop(); 97f6b354fbSJanosch Frank } 98f6b354fbSJanosch Frank 99f6b354fbSJanosch Frank int main(void) 100f6b354fbSJanosch Frank { 101f6b354fbSJanosch Frank report_prefix_push("skey"); 102f6b354fbSJanosch Frank test_priv(); 103f6b354fbSJanosch Frank test_set(); 104f6b354fbSJanosch Frank test_set_mb(); 105f6b354fbSJanosch Frank test_chg(); 106f6b354fbSJanosch Frank report_prefix_pop(); 107f6b354fbSJanosch Frank return report_summary(); 108f6b354fbSJanosch Frank } 109