/* SPDX-License-Identifier: GPL-2.0-only */ /* * Tests SIE with paging. * * Copyright 2023 IBM Corp. * * Authors: * Nico Boehr */ #include #include #include #include #include #include #include #include #include #include #include #include "snippets/c/sie-dat.h" static struct vm vm; static pgd_t *guest_root; static void test_sie_dat(void) { uint64_t test_page_gpa, test_page_hpa; uint8_t *test_page_hva, expected_val; bool contents_match; /* guest will tell us the guest physical address of the test buffer */ sie(&vm); assert(snippet_is_force_exit_value(&vm)); test_page_gpa = snippet_get_force_exit_value(&vm); test_page_hpa = virt_to_pte_phys(guest_root, (void*)test_page_gpa); test_page_hva = __va(test_page_hpa); report_info("test buffer gpa=0x%lx hva=%p", test_page_gpa, test_page_hva); /* guest will now write to the test buffer and we verify the contents */ sie(&vm); assert(snippet_is_force_exit(&vm)); contents_match = true; for (unsigned int i = 0; i < GUEST_TEST_PAGE_COUNT; i++) { expected_val = 42 + i; if (test_page_hva[i * PAGE_SIZE] != expected_val) { report_fail("page %u mismatch actual_val=%x expected_val=%x", i, test_page_hva[i], expected_val); contents_match = false; } } report(contents_match, "test buffer contents match"); /* the guest will now write to an unmapped address and we check that this causes a segment translation exception */ report_prefix_push("guest write to unmapped"); expect_pgm_int(); sie(&vm); check_pgm_int_code(PGM_INT_CODE_SEGMENT_TRANSLATION); report((lowcore.trans_exc_id & PAGE_MASK) == (GUEST_TOTAL_PAGE_COUNT * PAGE_SIZE), "TEID address match"); report_prefix_pop(); } static void setup_guest(void) { extern const char SNIPPET_NAME_START(c, sie_dat)[]; extern const char SNIPPET_NAME_END(c, sie_dat)[]; uint64_t guest_max_addr; pgd_t *root; setup_vm(); root = (pgd_t *)(stctg(1) & PAGE_MASK); snippet_setup_guest(&vm, false); /* allocate a region-1 table */ guest_root = pgd_alloc_one(); /* map guest memory 1:1 */ guest_max_addr = GUEST_TOTAL_PAGE_COUNT * PAGE_SIZE; for (uint64_t i = 0; i < guest_max_addr; i += PAGE_SIZE) install_page(guest_root, virt_to_pte_phys(root, vm.guest_mem + i), (void *)i); /* set up storage limit supression - leave mso and msl intact they are ignored anyways */ vm.sblk->cpuflags |= CPUSTAT_SM; /* set up the guest asce */ vm.save_area.guest.asce = __pa(guest_root) | ASCE_DT_REGION1 | REGION_TABLE_LENGTH; snippet_init(&vm, SNIPPET_NAME_START(c, sie_dat), SNIPPET_LEN(c, sie_dat), SNIPPET_UNPACK_OFF); } int main(void) { report_prefix_push("sie-dat"); if (!sclp_facilities.has_sief2) { report_skip("SIEF2 facility unavailable"); goto done; } setup_guest(); test_sie_dat(); sie_guest_destroy(&vm); done: report_prefix_pop(); return report_summary(); }