1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Perform Frame Management Function (pfmf) tests 4 * 5 * Copyright (c) 2018 IBM 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 <asm/page.h> 14 #include <asm/facility.h> 15 #include <asm/mem.h> 16 17 static uint8_t pagebuf[PAGE_SIZE * 256] __attribute__((aligned(PAGE_SIZE * 256))); 18 19 static void test_priv(void) 20 { 21 report_prefix_push("privileged"); 22 expect_pgm_int(); 23 enter_pstate(); 24 pfmf(0, pagebuf); 25 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 26 report_prefix_pop(); 27 } 28 29 static void test_4k_key(void) 30 { 31 union pfmf_r1 r1; 32 union skey skey; 33 34 report_prefix_push("4K"); 35 if (test_facility(169)) { 36 report_skip("storage key removal facility is active"); 37 goto out; 38 } 39 r1.val = 0; 40 r1.reg.sk = 1; 41 r1.reg.fsc = PFMF_FSC_4K; 42 r1.reg.key = 0x30; 43 pfmf(r1.val, pagebuf); 44 skey.val = get_storage_key(pagebuf); 45 skey.val &= SKEY_ACC | SKEY_FP; 46 report(skey.val == 0x30, "set storage keys"); 47 out: 48 report_prefix_pop(); 49 } 50 51 static void test_1m_key(void) 52 { 53 int i; 54 bool rp = true; 55 union pfmf_r1 r1; 56 union skey skey; 57 58 report_prefix_push("1M"); 59 if (test_facility(169)) { 60 report_skip("storage key removal facility is active"); 61 goto out; 62 } 63 r1.val = 0; 64 r1.reg.sk = 1; 65 r1.reg.fsc = PFMF_FSC_1M; 66 r1.reg.key = 0x30; 67 pfmf(r1.val, pagebuf); 68 for (i = 0; i < 256; i++) { 69 skey.val = get_storage_key(pagebuf + i * PAGE_SIZE); 70 skey.val &= SKEY_ACC | SKEY_FP; 71 if (skey.val != 0x30) { 72 rp = false; 73 break; 74 } 75 } 76 report(rp, "set storage keys"); 77 out: 78 report_prefix_pop(); 79 } 80 81 static void test_4k_clear(void) 82 { 83 union pfmf_r1 r1; 84 85 r1.val = 0; 86 r1.reg.cf = 1; 87 r1.reg.fsc = PFMF_FSC_4K; 88 89 report_prefix_push("4K"); 90 memset(pagebuf, 42, PAGE_SIZE); 91 pfmf(r1.val, pagebuf); 92 report(!memcmp(pagebuf, pagebuf + PAGE_SIZE, PAGE_SIZE), 93 "clear memory"); 94 report_prefix_pop(); 95 } 96 97 static void test_1m_clear(void) 98 { 99 int i; 100 union pfmf_r1 r1; 101 unsigned long sum = 0; 102 103 r1.val = 0; 104 r1.reg.cf = 1; 105 r1.reg.fsc = PFMF_FSC_1M; 106 107 report_prefix_push("1M"); 108 memset(pagebuf, 42, PAGE_SIZE * 256); 109 pfmf(r1.val, pagebuf); 110 for (i = 0; i < PAGE_SIZE * 256; i++) 111 sum |= pagebuf[i]; 112 report(!sum, "clear memory"); 113 report_prefix_pop(); 114 } 115 116 int main(void) 117 { 118 bool has_edat = test_facility(8); 119 120 report_prefix_push("pfmf"); 121 if (!has_edat) { 122 report_skip("PFMF is not available"); 123 goto done; 124 } 125 126 test_priv(); 127 /* Force the buffer pages in */ 128 memset(pagebuf, 0, PAGE_SIZE * 256); 129 130 test_4k_key(); 131 test_4k_clear(); 132 test_1m_key(); 133 test_1m_clear(); 134 135 done: 136 report_prefix_pop(); 137 return report_summary(); 138 } 139