1*1a7b0521SNico Boehr /* SPDX-License-Identifier: GPL-2.0-only */ 2*1a7b0521SNico Boehr /* 3*1a7b0521SNico Boehr * Storage Key migration tests 4*1a7b0521SNico Boehr * 5*1a7b0521SNico Boehr * Copyright IBM Corp. 2022 6*1a7b0521SNico Boehr * 7*1a7b0521SNico Boehr * Authors: 8*1a7b0521SNico Boehr * Nico Boehr <nrb@linux.ibm.com> 9*1a7b0521SNico Boehr */ 10*1a7b0521SNico Boehr 11*1a7b0521SNico Boehr #include <libcflat.h> 12*1a7b0521SNico Boehr #include <asm/facility.h> 13*1a7b0521SNico Boehr #include <asm/page.h> 14*1a7b0521SNico Boehr #include <asm/mem.h> 15*1a7b0521SNico Boehr #include <asm/interrupt.h> 16*1a7b0521SNico Boehr #include <hardware.h> 17*1a7b0521SNico Boehr 18*1a7b0521SNico Boehr #define NUM_PAGES 128 19*1a7b0521SNico Boehr static uint8_t pagebuf[NUM_PAGES][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); 20*1a7b0521SNico Boehr 21*1a7b0521SNico Boehr static void test_migration(void) 22*1a7b0521SNico Boehr { 23*1a7b0521SNico Boehr union skey expected_key, actual_key; 24*1a7b0521SNico Boehr int i, key_to_set, key_mismatches = 0; 25*1a7b0521SNico Boehr 26*1a7b0521SNico Boehr for (i = 0; i < NUM_PAGES; i++) { 27*1a7b0521SNico Boehr /* 28*1a7b0521SNico Boehr * Storage keys are 7 bit, lowest bit is always returned as zero 29*1a7b0521SNico Boehr * by iske. 30*1a7b0521SNico Boehr * This loop will set all 7 bits which means we set fetch 31*1a7b0521SNico Boehr * protection as well as reference and change indication for 32*1a7b0521SNico Boehr * some keys. 33*1a7b0521SNico Boehr */ 34*1a7b0521SNico Boehr key_to_set = i * 2; 35*1a7b0521SNico Boehr set_storage_key(pagebuf[i], key_to_set, 1); 36*1a7b0521SNico Boehr } 37*1a7b0521SNico Boehr 38*1a7b0521SNico Boehr puts("Please migrate me, then press return\n"); 39*1a7b0521SNico Boehr (void)getchar(); 40*1a7b0521SNico Boehr 41*1a7b0521SNico Boehr for (i = 0; i < NUM_PAGES; i++) { 42*1a7b0521SNico Boehr actual_key.val = get_storage_key(pagebuf[i]); 43*1a7b0521SNico Boehr expected_key.val = i * 2; 44*1a7b0521SNico Boehr 45*1a7b0521SNico Boehr /* 46*1a7b0521SNico Boehr * The PoP neither gives a guarantee that the reference bit is 47*1a7b0521SNico Boehr * accurate nor that it won't be cleared by hardware. Hence we 48*1a7b0521SNico Boehr * don't rely on it and just clear the bits to avoid compare 49*1a7b0521SNico Boehr * errors. 50*1a7b0521SNico Boehr */ 51*1a7b0521SNico Boehr actual_key.str.rf = 0; 52*1a7b0521SNico Boehr expected_key.str.rf = 0; 53*1a7b0521SNico Boehr 54*1a7b0521SNico Boehr /* don't log anything when key matches to avoid spamming the log */ 55*1a7b0521SNico Boehr if (actual_key.val != expected_key.val) { 56*1a7b0521SNico Boehr key_mismatches++; 57*1a7b0521SNico Boehr report_fail("page %d expected_key=0x%x actual_key=0x%x", i, expected_key.val, actual_key.val); 58*1a7b0521SNico Boehr } 59*1a7b0521SNico Boehr } 60*1a7b0521SNico Boehr 61*1a7b0521SNico Boehr report(!key_mismatches, "skeys after migration match"); 62*1a7b0521SNico Boehr } 63*1a7b0521SNico Boehr 64*1a7b0521SNico Boehr int main(void) 65*1a7b0521SNico Boehr { 66*1a7b0521SNico Boehr report_prefix_push("migration-skey"); 67*1a7b0521SNico Boehr if (test_facility(169)) { 68*1a7b0521SNico Boehr report_skip("storage key removal facility is active"); 69*1a7b0521SNico Boehr 70*1a7b0521SNico Boehr /* 71*1a7b0521SNico Boehr * If we just exit and don't ask migrate_cmd to migrate us, it 72*1a7b0521SNico Boehr * will just hang forever. Hence, also ask for migration when we 73*1a7b0521SNico Boehr * skip this test altogether. 74*1a7b0521SNico Boehr */ 75*1a7b0521SNico Boehr puts("Please migrate me, then press return\n"); 76*1a7b0521SNico Boehr (void)getchar(); 77*1a7b0521SNico Boehr } else { 78*1a7b0521SNico Boehr test_migration(); 79*1a7b0521SNico Boehr } 80*1a7b0521SNico Boehr 81*1a7b0521SNico Boehr report_prefix_pop(); 82*1a7b0521SNico Boehr return report_summary(); 83*1a7b0521SNico Boehr } 84