1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Release pages hypercall tests (DIAG 10) 4 * 5 * Copyright (c) 2018 IBM Corp 6 * 7 * Authors: 8 * Janosch Frank <frankja@linux.vnet.ibm.com> 9 */ 10 11 #include <libcflat.h> 12 #include <asm/asm-offsets.h> 13 #include <asm/interrupt.h> 14 #include <asm/page.h> 15 16 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2))); 17 const unsigned long page0 = (unsigned long)pagebuf; 18 const unsigned long page1 = (unsigned long)(pagebuf + PAGE_SIZE); 19 20 /* Tells the host to release pages from guest real addresses start to 21 * end. Parameters have to be page aligned, instruction is privileged. 22 */ 23 static inline void diag10(unsigned long start, unsigned long end) 24 { 25 asm volatile ( 26 "diag %0,%1,0x10\n" 27 : : "a" (start), "a" (end)); 28 } 29 30 /* Try freeing the prefix */ 31 static void test_prefix(void) 32 { 33 report_prefix_push("lowcore freeing"); 34 35 report_prefix_push("0x0000/0x0000"); 36 expect_pgm_int(); 37 diag10(0, 0); 38 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 39 report_prefix_pop(); 40 41 42 report_prefix_push("0x1000/0x1000"); 43 expect_pgm_int(); 44 diag10(0x1000, 0x1000); 45 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 46 report_prefix_pop(); 47 48 report_prefix_push("0x0000/0x1000"); 49 expect_pgm_int(); 50 diag10(0, 0x1000); 51 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 52 report_prefix_pop(); 53 54 report_prefix_pop(); 55 } 56 57 static void test_params(void) 58 { 59 report_prefix_push("start/end"); 60 61 /* end < start */ 62 report_prefix_push("end < start"); 63 expect_pgm_int(); 64 diag10(page1, page0); 65 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 66 report_prefix_pop(); 67 68 /* Unaligned start */ 69 report_prefix_push("unaligned start"); 70 expect_pgm_int(); 71 diag10((unsigned long) pagebuf + 42, page1); 72 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 73 report_prefix_pop(); 74 75 /* Unaligned end */ 76 report_prefix_push("unaligned end"); 77 expect_pgm_int(); 78 diag10(page0, (unsigned long) pagebuf + PAGE_SIZE + 42); 79 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 80 report_prefix_pop(); 81 82 report_prefix_pop(); 83 } 84 85 static void test_priv(void) 86 { 87 report_prefix_push("privileged"); 88 expect_pgm_int(); 89 enter_pstate(); 90 diag10(page0, page0); 91 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 92 report_prefix_pop(); 93 } 94 95 int main(void) 96 { 97 report_prefix_push("diag10"); 98 test_prefix(); 99 test_params(); 100 test_priv(); 101 return report_summary(); 102 } 103