1*2456fdf7SNico Boehr /* SPDX-License-Identifier: GPL-2.0-only */ 2*2456fdf7SNico Boehr /* 3*2456fdf7SNico Boehr * Tests SIE with paging. 4*2456fdf7SNico Boehr * 5*2456fdf7SNico Boehr * Copyright 2023 IBM Corp. 6*2456fdf7SNico Boehr * 7*2456fdf7SNico Boehr * Authors: 8*2456fdf7SNico Boehr * Nico Boehr <nrb@linux.ibm.com> 9*2456fdf7SNico Boehr */ 10*2456fdf7SNico Boehr #include <libcflat.h> 11*2456fdf7SNico Boehr #include <vmalloc.h> 12*2456fdf7SNico Boehr #include <asm/pgtable.h> 13*2456fdf7SNico Boehr #include <mmu.h> 14*2456fdf7SNico Boehr #include <asm/page.h> 15*2456fdf7SNico Boehr #include <asm/interrupt.h> 16*2456fdf7SNico Boehr #include <alloc_page.h> 17*2456fdf7SNico Boehr #include <sclp.h> 18*2456fdf7SNico Boehr #include <sie.h> 19*2456fdf7SNico Boehr #include <snippet.h> 20*2456fdf7SNico Boehr #include "snippets/c/sie-dat.h" 21*2456fdf7SNico Boehr 22*2456fdf7SNico Boehr static struct vm vm; 23*2456fdf7SNico Boehr static pgd_t *guest_root; 24*2456fdf7SNico Boehr 25*2456fdf7SNico Boehr static void test_sie_dat(void) 26*2456fdf7SNico Boehr { 27*2456fdf7SNico Boehr uint64_t test_page_gpa, test_page_hpa; 28*2456fdf7SNico Boehr uint8_t *test_page_hva, expected_val; 29*2456fdf7SNico Boehr bool contents_match; 30*2456fdf7SNico Boehr uint8_t r1; 31*2456fdf7SNico Boehr 32*2456fdf7SNico Boehr /* guest will tell us the guest physical address of the test buffer */ 33*2456fdf7SNico Boehr sie(&vm); 34*2456fdf7SNico Boehr assert(vm.sblk->icptcode == ICPT_INST && 35*2456fdf7SNico Boehr (vm.sblk->ipa & 0xff00) == 0x8300 && vm.sblk->ipb == 0x9c0000); 36*2456fdf7SNico Boehr 37*2456fdf7SNico Boehr r1 = (vm.sblk->ipa & 0xf0) >> 4; 38*2456fdf7SNico Boehr test_page_gpa = vm.save_area.guest.grs[r1]; 39*2456fdf7SNico Boehr test_page_hpa = virt_to_pte_phys(guest_root, (void*)test_page_gpa); 40*2456fdf7SNico Boehr test_page_hva = __va(test_page_hpa); 41*2456fdf7SNico Boehr report_info("test buffer gpa=0x%lx hva=%p", test_page_gpa, test_page_hva); 42*2456fdf7SNico Boehr 43*2456fdf7SNico Boehr /* guest will now write to the test buffer and we verify the contents */ 44*2456fdf7SNico Boehr sie(&vm); 45*2456fdf7SNico Boehr assert(vm.sblk->icptcode == ICPT_INST && 46*2456fdf7SNico Boehr vm.sblk->ipa == 0x8300 && vm.sblk->ipb == 0x440000); 47*2456fdf7SNico Boehr 48*2456fdf7SNico Boehr contents_match = true; 49*2456fdf7SNico Boehr for (unsigned int i = 0; i < GUEST_TEST_PAGE_COUNT; i++) { 50*2456fdf7SNico Boehr expected_val = 42 + i; 51*2456fdf7SNico Boehr if (test_page_hva[i * PAGE_SIZE] != expected_val) { 52*2456fdf7SNico Boehr report_fail("page %u mismatch actual_val=%x expected_val=%x", 53*2456fdf7SNico Boehr i, test_page_hva[i], expected_val); 54*2456fdf7SNico Boehr contents_match = false; 55*2456fdf7SNico Boehr } 56*2456fdf7SNico Boehr } 57*2456fdf7SNico Boehr report(contents_match, "test buffer contents match"); 58*2456fdf7SNico Boehr 59*2456fdf7SNico Boehr /* the guest will now write to an unmapped address and we check that this causes a segment translation exception */ 60*2456fdf7SNico Boehr report_prefix_push("guest write to unmapped"); 61*2456fdf7SNico Boehr expect_pgm_int(); 62*2456fdf7SNico Boehr sie(&vm); 63*2456fdf7SNico Boehr check_pgm_int_code(PGM_INT_CODE_SEGMENT_TRANSLATION); 64*2456fdf7SNico Boehr report((lowcore.trans_exc_id & PAGE_MASK) == (GUEST_TOTAL_PAGE_COUNT * PAGE_SIZE), "TEID address match"); 65*2456fdf7SNico Boehr report_prefix_pop(); 66*2456fdf7SNico Boehr } 67*2456fdf7SNico Boehr 68*2456fdf7SNico Boehr static void setup_guest(void) 69*2456fdf7SNico Boehr { 70*2456fdf7SNico Boehr extern const char SNIPPET_NAME_START(c, sie_dat)[]; 71*2456fdf7SNico Boehr extern const char SNIPPET_NAME_END(c, sie_dat)[]; 72*2456fdf7SNico Boehr uint64_t guest_max_addr; 73*2456fdf7SNico Boehr pgd_t *root; 74*2456fdf7SNico Boehr 75*2456fdf7SNico Boehr setup_vm(); 76*2456fdf7SNico Boehr root = (pgd_t *)(stctg(1) & PAGE_MASK); 77*2456fdf7SNico Boehr 78*2456fdf7SNico Boehr snippet_setup_guest(&vm, false); 79*2456fdf7SNico Boehr 80*2456fdf7SNico Boehr /* allocate a region-1 table */ 81*2456fdf7SNico Boehr guest_root = pgd_alloc_one(); 82*2456fdf7SNico Boehr 83*2456fdf7SNico Boehr /* map guest memory 1:1 */ 84*2456fdf7SNico Boehr guest_max_addr = GUEST_TOTAL_PAGE_COUNT * PAGE_SIZE; 85*2456fdf7SNico Boehr for (uint64_t i = 0; i < guest_max_addr; i += PAGE_SIZE) 86*2456fdf7SNico Boehr install_page(guest_root, virt_to_pte_phys(root, vm.guest_mem + i), (void *)i); 87*2456fdf7SNico Boehr 88*2456fdf7SNico Boehr /* set up storage limit supression - leave mso and msl intact they are ignored anyways */ 89*2456fdf7SNico Boehr vm.sblk->cpuflags |= CPUSTAT_SM; 90*2456fdf7SNico Boehr 91*2456fdf7SNico Boehr /* set up the guest asce */ 92*2456fdf7SNico Boehr vm.save_area.guest.asce = __pa(guest_root) | ASCE_DT_REGION1 | REGION_TABLE_LENGTH; 93*2456fdf7SNico Boehr 94*2456fdf7SNico Boehr snippet_init(&vm, SNIPPET_NAME_START(c, sie_dat), 95*2456fdf7SNico Boehr SNIPPET_LEN(c, sie_dat), SNIPPET_UNPACK_OFF); 96*2456fdf7SNico Boehr } 97*2456fdf7SNico Boehr 98*2456fdf7SNico Boehr int main(void) 99*2456fdf7SNico Boehr { 100*2456fdf7SNico Boehr report_prefix_push("sie-dat"); 101*2456fdf7SNico Boehr if (!sclp_facilities.has_sief2) { 102*2456fdf7SNico Boehr report_skip("SIEF2 facility unavailable"); 103*2456fdf7SNico Boehr goto done; 104*2456fdf7SNico Boehr } 105*2456fdf7SNico Boehr 106*2456fdf7SNico Boehr setup_guest(); 107*2456fdf7SNico Boehr test_sie_dat(); 108*2456fdf7SNico Boehr sie_guest_destroy(&vm); 109*2456fdf7SNico Boehr 110*2456fdf7SNico Boehr done: 111*2456fdf7SNico Boehr report_prefix_pop(); 112*2456fdf7SNico Boehr return report_summary(); 113*2456fdf7SNico Boehr 114*2456fdf7SNico Boehr } 115