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