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