blob: 7ee8945f18347ec564e75351914115efea6e397f [file] [log] [blame]
/*
* Release pages hypercall tests (DIAG 10)
*
* Copyright (c) 2018 IBM Corp
*
* Authors:
* Janosch Frank <frankja@linux.vnet.ibm.com>
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License version 2.
*/
#include <libcflat.h>
#include <asm/asm-offsets.h>
#include <asm/interrupt.h>
#include <asm/page.h>
static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
const unsigned long page0 = (unsigned long)pagebuf;
const unsigned long page1 = (unsigned long)(pagebuf + PAGE_SIZE);
/* Tells the host to release pages from guest real addresses start to
* end. Parameters have to be page aligned, instruction is privileged.
*/
static inline void diag10(unsigned long start, unsigned long end)
{
asm volatile (
"diag %0,%1,0x10\n"
: : "a" (start), "a" (end));
}
/* Try freeing the prefix */
static void test_prefix(void)
{
report_prefix_push("lowcore freeing");
report_prefix_push("0x0000/0x0000");
expect_pgm_int();
diag10(0, 0);
check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
report_prefix_pop();
report_prefix_push("0x1000/0x1000");
expect_pgm_int();
diag10(0x1000, 0x1000);
check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
report_prefix_pop();
report_prefix_push("0x0000/0x1000");
expect_pgm_int();
diag10(0, 0x1000);
check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
report_prefix_pop();
report_prefix_pop();
}
static void test_params(void)
{
report_prefix_push("start/end");
/* end < start */
report_prefix_push("end < start");
expect_pgm_int();
diag10(page1, page0);
check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
report_prefix_pop();
/* Unaligned start */
report_prefix_push("unaligned start");
expect_pgm_int();
diag10((unsigned long) pagebuf + 42, page1);
check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
report_prefix_pop();
/* Unaligned end */
report_prefix_push("unaligned end");
expect_pgm_int();
diag10(page0, (unsigned long) pagebuf + PAGE_SIZE + 42);
check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
report_prefix_pop();
report_prefix_pop();
}
static void test_priv(void)
{
report_prefix_push("privileged");
expect_pgm_int();
enter_pstate();
diag10(page0, page0);
check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
report_prefix_pop();
}
int main(void)
{
report_prefix_push("diag10");
test_prefix();
test_params();
test_priv();
return report_summary();
}