128ccfb1eSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */ 228ccfb1eSJanosch Frank /* 318d05511SJanosch Frank * Host Ultravisor Call tests 428ccfb1eSJanosch Frank * 528ccfb1eSJanosch Frank * Copyright (c) 2021 IBM Corp 628ccfb1eSJanosch Frank * 728ccfb1eSJanosch Frank * Authors: 828ccfb1eSJanosch Frank * Janosch Frank <frankja@linux.ibm.com> 928ccfb1eSJanosch Frank */ 1028ccfb1eSJanosch Frank 1128ccfb1eSJanosch Frank #include <libcflat.h> 125bf29e09SClaudio Imbrenda #include <hardware.h> 1328ccfb1eSJanosch Frank #include <alloc.h> 1428ccfb1eSJanosch Frank #include <vmalloc.h> 1528ccfb1eSJanosch Frank #include <sclp.h> 1628ccfb1eSJanosch Frank #include <smp.h> 1728ccfb1eSJanosch Frank #include <uv.h> 1890704fe2SJanosch Frank #include <snippet.h> 1991d18441SJanosch Frank #include <mmu.h> 2028ccfb1eSJanosch Frank #include <asm/page.h> 2128ccfb1eSJanosch Frank #include <asm/pgtable.h> 2228ccfb1eSJanosch Frank #include <asm/asm-offsets.h> 2328ccfb1eSJanosch Frank #include <asm/interrupt.h> 2428ccfb1eSJanosch Frank #include <asm/facility.h> 2591d18441SJanosch Frank #include <asm/pgtable.h> 2628ccfb1eSJanosch Frank #include <asm/uv.h> 2728ccfb1eSJanosch Frank #include <asm-generic/barrier.h> 2828ccfb1eSJanosch Frank 2928ccfb1eSJanosch Frank static struct uv_cb_qui uvcb_qui; 3028ccfb1eSJanosch Frank static struct uv_cb_init uvcb_init; 3128ccfb1eSJanosch Frank static struct uv_cb_cgc uvcb_cgc; 3228ccfb1eSJanosch Frank static struct uv_cb_csc uvcb_csc; 3328ccfb1eSJanosch Frank 3428ccfb1eSJanosch Frank extern int diag308_load_reset(u64 code); 3528ccfb1eSJanosch Frank 3628ccfb1eSJanosch Frank struct cmd_list { 3728ccfb1eSJanosch Frank const char *name; 3828ccfb1eSJanosch Frank uint16_t cmd; 3928ccfb1eSJanosch Frank uint16_t len; 4028ccfb1eSJanosch Frank int call_bit; 4128ccfb1eSJanosch Frank }; 4228ccfb1eSJanosch Frank 4328ccfb1eSJanosch Frank static void cpu_loop(void) 4428ccfb1eSJanosch Frank { 4528ccfb1eSJanosch Frank for (;;) {} 4628ccfb1eSJanosch Frank } 4728ccfb1eSJanosch Frank 48b9ff8da5SJanosch Frank /* 49b9ff8da5SJanosch Frank * Checks if a memory area is protected as secure memory. 50b9ff8da5SJanosch Frank * Will return true if all pages are protected, false otherwise. 51b9ff8da5SJanosch Frank */ 52b9ff8da5SJanosch Frank static bool access_check_3d(uint8_t *access_ptr, uint64_t len) 53b9ff8da5SJanosch Frank { 54b9ff8da5SJanosch Frank assert(!(len & ~PAGE_MASK)); 55b9ff8da5SJanosch Frank assert(!((uint64_t)access_ptr & ~PAGE_MASK)); 56b9ff8da5SJanosch Frank 57b9ff8da5SJanosch Frank while (len) { 58b9ff8da5SJanosch Frank expect_pgm_int(); 59b9ff8da5SJanosch Frank READ_ONCE(*access_ptr); 60b9ff8da5SJanosch Frank if (clear_pgm_int() != PGM_INT_CODE_SECURE_STOR_ACCESS) 61b9ff8da5SJanosch Frank return false; 62b9ff8da5SJanosch Frank expect_pgm_int(); 63b9ff8da5SJanosch Frank WRITE_ONCE(*access_ptr, 42); 64b9ff8da5SJanosch Frank if (clear_pgm_int() != PGM_INT_CODE_SECURE_STOR_ACCESS) 65b9ff8da5SJanosch Frank return false; 66b9ff8da5SJanosch Frank 67b9ff8da5SJanosch Frank access_ptr += PAGE_SIZE; 68b9ff8da5SJanosch Frank len -= PAGE_SIZE; 69b9ff8da5SJanosch Frank } 70b9ff8da5SJanosch Frank 71b9ff8da5SJanosch Frank return true; 72b9ff8da5SJanosch Frank } 73b9ff8da5SJanosch Frank 7428ccfb1eSJanosch Frank static struct cmd_list cmds[] = { 7528ccfb1eSJanosch Frank { "init", UVC_CMD_INIT_UV, sizeof(struct uv_cb_init), BIT_UVC_CMD_INIT_UV }, 7628ccfb1eSJanosch Frank { "create conf", UVC_CMD_CREATE_SEC_CONF, sizeof(struct uv_cb_cgc), BIT_UVC_CMD_CREATE_SEC_CONF }, 7728ccfb1eSJanosch Frank { "destroy conf", UVC_CMD_DESTROY_SEC_CONF, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CONF }, 7828ccfb1eSJanosch Frank { "create cpu", UVC_CMD_CREATE_SEC_CPU, sizeof(struct uv_cb_csc), BIT_UVC_CMD_CREATE_SEC_CPU }, 7928ccfb1eSJanosch Frank { "destroy cpu", UVC_CMD_DESTROY_SEC_CPU, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CPU }, 8028ccfb1eSJanosch Frank { "conv to", UVC_CMD_CONV_TO_SEC_STOR, sizeof(struct uv_cb_cts), BIT_UVC_CMD_CONV_TO_SEC_STOR }, 8128ccfb1eSJanosch Frank { "conv from", UVC_CMD_CONV_FROM_SEC_STOR, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_CONV_FROM_SEC_STOR }, 8228ccfb1eSJanosch Frank { "set sec conf", UVC_CMD_SET_SEC_CONF_PARAMS, sizeof(struct uv_cb_ssc), BIT_UVC_CMD_SET_SEC_PARMS }, 8328ccfb1eSJanosch Frank { "unpack", UVC_CMD_UNPACK_IMG, sizeof(struct uv_cb_unp), BIT_UVC_CMD_UNPACK_IMG }, 8428ccfb1eSJanosch Frank { "verify", UVC_CMD_VERIFY_IMG, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_VERIFY_IMG }, 8528ccfb1eSJanosch Frank { "cpu reset", UVC_CMD_CPU_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET }, 8628ccfb1eSJanosch Frank { "cpu initial reset", UVC_CMD_CPU_RESET_INITIAL, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET_INITIAL }, 875630c446SJanosch Frank { "conf clear reset", UVC_CMD_PREPARE_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_PREPARE_RESET }, 8828ccfb1eSJanosch Frank { "cpu clear reset", UVC_CMD_CPU_RESET_CLEAR, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET }, 8928ccfb1eSJanosch Frank { "cpu set state", UVC_CMD_CPU_SET_STATE, sizeof(struct uv_cb_cpu_set_state), BIT_UVC_CMD_CPU_SET_STATE }, 9028ccfb1eSJanosch Frank { "pin shared", UVC_CMD_PIN_PAGE_SHARED, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_PIN_PAGE_SHARED }, 9128ccfb1eSJanosch Frank { "unpin shared", UVC_CMD_UNPIN_PAGE_SHARED, sizeof(struct uv_cb_cts), BIT_UVC_CMD_UNPIN_PAGE_SHARED }, 9228ccfb1eSJanosch Frank { NULL, 0, 0 }, 9328ccfb1eSJanosch Frank }; 9428ccfb1eSJanosch Frank 955078e7a7SJanosch Frank static void test_i3(void) 965078e7a7SJanosch Frank { 975078e7a7SJanosch Frank struct uv_cb_header uvcb = { 985078e7a7SJanosch Frank .cmd = UVC_CMD_INIT_UV, 995078e7a7SJanosch Frank .len = sizeof(struct uv_cb_init), 1005078e7a7SJanosch Frank }; 1015078e7a7SJanosch Frank unsigned long r1 = 0; 1025078e7a7SJanosch Frank int cc; 1035078e7a7SJanosch Frank 1045078e7a7SJanosch Frank report_prefix_push("i3"); 1055078e7a7SJanosch Frank expect_pgm_int(); 1065078e7a7SJanosch Frank asm volatile( 1075078e7a7SJanosch Frank "0: .insn rrf,0xB9A40000,%[r1],%[r2],4,2\n" 1085078e7a7SJanosch Frank " ipm %[cc]\n" 1095078e7a7SJanosch Frank " srl %[cc],28\n" 1105078e7a7SJanosch Frank : [cc] "=d" (cc) 1115078e7a7SJanosch Frank : [r1] "a" (r1), [r2] "a" (&uvcb) 1125078e7a7SJanosch Frank : "memory", "cc"); 1135078e7a7SJanosch Frank check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 1145078e7a7SJanosch Frank report_prefix_pop(); 1155078e7a7SJanosch Frank } 1165078e7a7SJanosch Frank 11728ccfb1eSJanosch Frank static void test_priv(void) 11828ccfb1eSJanosch Frank { 11928ccfb1eSJanosch Frank struct uv_cb_header uvcb = {}; 12028ccfb1eSJanosch Frank uint16_t pgm; 12128ccfb1eSJanosch Frank int i; 12228ccfb1eSJanosch Frank 12328ccfb1eSJanosch Frank report_prefix_push("privileged"); 12428ccfb1eSJanosch Frank for (i = 0; cmds[i].name; i++) { 12528ccfb1eSJanosch Frank expect_pgm_int(); 12628ccfb1eSJanosch Frank uvcb.cmd = cmds[i].cmd; 12728ccfb1eSJanosch Frank uvcb.len = cmds[i].len; 12828ccfb1eSJanosch Frank enter_pstate(); 129bf0e1689SJanosch Frank uv_call_once(0, (uint64_t)&uvcb); 13028ccfb1eSJanosch Frank pgm = clear_pgm_int(); 13128ccfb1eSJanosch Frank report(pgm == PGM_INT_CODE_PRIVILEGED_OPERATION, "%s", cmds[i].name); 13228ccfb1eSJanosch Frank } 13328ccfb1eSJanosch Frank report_prefix_pop(); 13428ccfb1eSJanosch Frank } 13528ccfb1eSJanosch Frank 136b744815eSJanosch Frank static void test_uv_uninitialized(void) 137b744815eSJanosch Frank { 138b744815eSJanosch Frank struct uv_cb_header uvcb = {}; 139b744815eSJanosch Frank int i; 140b744815eSJanosch Frank 141b744815eSJanosch Frank report_prefix_push("uninitialized"); 142b744815eSJanosch Frank 143b744815eSJanosch Frank for (i = 0; cmds[i].name; i++) { 144b744815eSJanosch Frank if (cmds[i].cmd == UVC_CMD_INIT_UV) 145b744815eSJanosch Frank continue; 146b744815eSJanosch Frank expect_pgm_int(); 147b744815eSJanosch Frank uvcb.cmd = cmds[i].cmd; 148b744815eSJanosch Frank uvcb.len = cmds[i].len; 149b744815eSJanosch Frank uv_call_once(0, (uint64_t)&uvcb); 150b744815eSJanosch Frank report(uvcb.rc == UVC_RC_INV_STATE, "%s", cmds[i].name); 151b744815eSJanosch Frank } 152b744815eSJanosch Frank report_prefix_pop(); 153b744815eSJanosch Frank } 154b744815eSJanosch Frank 15591d18441SJanosch Frank static void test_access(void) 15691d18441SJanosch Frank { 15791d18441SJanosch Frank struct uv_cb_header *uvcb; 15891d18441SJanosch Frank void *pages = alloc_pages(1); 15991d18441SJanosch Frank uint16_t pgm; 16091d18441SJanosch Frank int i; 16191d18441SJanosch Frank 16291d18441SJanosch Frank /* Put UVCB on second page which we will protect later */ 16391d18441SJanosch Frank uvcb = pages + PAGE_SIZE; 16491d18441SJanosch Frank 16591d18441SJanosch Frank report_prefix_push("access"); 16691d18441SJanosch Frank 16791d18441SJanosch Frank report_prefix_push("non-crossing"); 16891d18441SJanosch Frank protect_page(uvcb, PAGE_ENTRY_I); 16991d18441SJanosch Frank for (i = 0; cmds[i].name; i++) { 17091d18441SJanosch Frank expect_pgm_int(); 17191d18441SJanosch Frank mb(); 17291d18441SJanosch Frank uv_call_once(0, (uint64_t)uvcb); 17391d18441SJanosch Frank pgm = clear_pgm_int(); 17491d18441SJanosch Frank report(pgm == PGM_INT_CODE_PAGE_TRANSLATION, "%s", cmds[i].name); 17591d18441SJanosch Frank } 17691d18441SJanosch Frank report_prefix_pop(); 17791d18441SJanosch Frank 17891d18441SJanosch Frank report_prefix_push("crossing"); 17991d18441SJanosch Frank /* 18091d18441SJanosch Frank * Put the header into the readable page 1, everything after 18191d18441SJanosch Frank * the header will be on the second, invalid page. 18291d18441SJanosch Frank */ 18391d18441SJanosch Frank uvcb -= 1; 18491d18441SJanosch Frank for (i = 0; cmds[i].name; i++) { 18591d18441SJanosch Frank uvcb->cmd = cmds[i].cmd; 18691d18441SJanosch Frank uvcb->len = cmds[i].len; 18791d18441SJanosch Frank 18891d18441SJanosch Frank expect_pgm_int(); 18991d18441SJanosch Frank mb(); 19091d18441SJanosch Frank uv_call_once(0, (uint64_t)uvcb); 19191d18441SJanosch Frank pgm = clear_pgm_int(); 19291d18441SJanosch Frank report(pgm == PGM_INT_CODE_PAGE_TRANSLATION, "%s", cmds[i].name); 19391d18441SJanosch Frank } 19491d18441SJanosch Frank report_prefix_pop(); 19591d18441SJanosch Frank 19691d18441SJanosch Frank uvcb += 1; 19791d18441SJanosch Frank unprotect_page(uvcb, PAGE_ENTRY_I); 19891d18441SJanosch Frank 19991d18441SJanosch Frank free_pages(pages); 20091d18441SJanosch Frank report_prefix_pop(); 20191d18441SJanosch Frank } 20291d18441SJanosch Frank 20328ccfb1eSJanosch Frank static void test_config_destroy(void) 20428ccfb1eSJanosch Frank { 20528ccfb1eSJanosch Frank int rc; 20628ccfb1eSJanosch Frank struct uv_cb_nodata uvcb = { 20728ccfb1eSJanosch Frank .header.cmd = UVC_CMD_DESTROY_SEC_CONF, 20828ccfb1eSJanosch Frank .header.len = sizeof(uvcb), 20928ccfb1eSJanosch Frank .handle = uvcb_cgc.guest_handle, 21028ccfb1eSJanosch Frank }; 21128ccfb1eSJanosch Frank 21228ccfb1eSJanosch Frank report_prefix_push("dsc"); 21328ccfb1eSJanosch Frank uvcb.header.len -= 8; 21428ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 21528ccfb1eSJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, 21628ccfb1eSJanosch Frank "hdr invalid length"); 21728ccfb1eSJanosch Frank uvcb.header.len += 8; 21828ccfb1eSJanosch Frank 21928ccfb1eSJanosch Frank uvcb.handle += 1; 22028ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 22128ccfb1eSJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_GHANDLE, "invalid handle"); 22228ccfb1eSJanosch Frank uvcb.handle -= 1; 22328ccfb1eSJanosch Frank 22428ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 22528ccfb1eSJanosch Frank report(rc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "success"); 22628ccfb1eSJanosch Frank report_prefix_pop(); 22728ccfb1eSJanosch Frank } 22828ccfb1eSJanosch Frank 22928ccfb1eSJanosch Frank static void test_cpu_destroy(void) 23028ccfb1eSJanosch Frank { 23128ccfb1eSJanosch Frank int rc; 23228ccfb1eSJanosch Frank struct uv_cb_nodata uvcb = { 23328ccfb1eSJanosch Frank .header.len = sizeof(uvcb), 23428ccfb1eSJanosch Frank .header.cmd = UVC_CMD_DESTROY_SEC_CPU, 23528ccfb1eSJanosch Frank .handle = uvcb_csc.cpu_handle, 23628ccfb1eSJanosch Frank }; 23728ccfb1eSJanosch Frank 23828ccfb1eSJanosch Frank report_prefix_push("dcpu"); 23928ccfb1eSJanosch Frank 24028ccfb1eSJanosch Frank uvcb.header.len -= 8; 24128ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 24228ccfb1eSJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, 24328ccfb1eSJanosch Frank "hdr invalid length"); 24428ccfb1eSJanosch Frank uvcb.header.len += 8; 24528ccfb1eSJanosch Frank 2465bf29e09SClaudio Imbrenda if (!machine_is_z15()) { 24728ccfb1eSJanosch Frank uvcb.handle += 1; 24828ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 24928ccfb1eSJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_CHANDLE, "invalid handle"); 25028ccfb1eSJanosch Frank uvcb.handle -= 1; 251c73cc92dSJanosch Frank } 25228ccfb1eSJanosch Frank 25328ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 25428ccfb1eSJanosch Frank report(rc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "success"); 25528ccfb1eSJanosch Frank 25628ccfb1eSJanosch Frank report_prefix_pop(); 25728ccfb1eSJanosch Frank } 25828ccfb1eSJanosch Frank 259692447f2SJanosch Frank static void test_set_se_header(void) 260692447f2SJanosch Frank { 261692447f2SJanosch Frank struct uv_cb_ssc uvcb = { 262692447f2SJanosch Frank .header.cmd = UVC_CMD_SET_SEC_CONF_PARAMS, 263692447f2SJanosch Frank .header.len = sizeof(uvcb), 264692447f2SJanosch Frank .guest_handle = uvcb_cgc.guest_handle, 265692447f2SJanosch Frank .sec_header_origin = 0, 266692447f2SJanosch Frank .sec_header_len = 0x1000, 267692447f2SJanosch Frank }; 268692447f2SJanosch Frank void *pages = alloc_pages(1); 269692447f2SJanosch Frank void *inv; 270692447f2SJanosch Frank int rc; 271692447f2SJanosch Frank 272692447f2SJanosch Frank report_prefix_push("sscp"); 273692447f2SJanosch Frank 274692447f2SJanosch Frank uvcb.header.len -= 8; 275692447f2SJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 276692447f2SJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, 277692447f2SJanosch Frank "hdr invalid length"); 278692447f2SJanosch Frank uvcb.header.len += 8; 279692447f2SJanosch Frank 280692447f2SJanosch Frank uvcb.guest_handle += 1; 281692447f2SJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 282692447f2SJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_GHANDLE, "invalid handle"); 283692447f2SJanosch Frank uvcb.guest_handle -= 1; 284692447f2SJanosch Frank 285692447f2SJanosch Frank inv = pages + PAGE_SIZE; 286692447f2SJanosch Frank uvcb.sec_header_origin = (uint64_t)inv; 287692447f2SJanosch Frank protect_page(inv, PAGE_ENTRY_I); 288692447f2SJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 289692447f2SJanosch Frank report(rc == 1 && uvcb.header.rc == 0x103, 290692447f2SJanosch Frank "se hdr access exception"); 291692447f2SJanosch Frank 292692447f2SJanosch Frank /* 293692447f2SJanosch Frank * Shift the ptr so the first few DWORDs are accessible but 294692447f2SJanosch Frank * the following are on an invalid page. 295692447f2SJanosch Frank */ 296692447f2SJanosch Frank uvcb.sec_header_origin -= 0x20; 297692447f2SJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 298692447f2SJanosch Frank report(rc == 1 && uvcb.header.rc == 0x103, 299692447f2SJanosch Frank "se hdr access exception crossing"); 300692447f2SJanosch Frank unprotect_page(inv, PAGE_ENTRY_I); 301692447f2SJanosch Frank 302692447f2SJanosch Frank free_pages(pages); 303692447f2SJanosch Frank report_prefix_pop(); 304692447f2SJanosch Frank } 305692447f2SJanosch Frank 30628ccfb1eSJanosch Frank static void test_cpu_create(void) 30728ccfb1eSJanosch Frank { 30828ccfb1eSJanosch Frank int rc; 30928ccfb1eSJanosch Frank unsigned long tmp; 31028ccfb1eSJanosch Frank 31128ccfb1eSJanosch Frank report_prefix_push("csc"); 31228ccfb1eSJanosch Frank uvcb_csc.header.len = sizeof(uvcb_csc); 31328ccfb1eSJanosch Frank uvcb_csc.header.cmd = UVC_CMD_CREATE_SEC_CPU; 31428ccfb1eSJanosch Frank uvcb_csc.guest_handle = uvcb_cgc.guest_handle; 31528ccfb1eSJanosch Frank uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len); 31628ccfb1eSJanosch Frank uvcb_csc.state_origin = (unsigned long)memalign(PAGE_SIZE, PAGE_SIZE); 31728ccfb1eSJanosch Frank 31828ccfb1eSJanosch Frank uvcb_csc.header.len -= 8; 31928ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 32028ccfb1eSJanosch Frank report(uvcb_csc.header.rc == UVC_RC_INV_LEN && rc == 1 && 32128ccfb1eSJanosch Frank !uvcb_csc.cpu_handle, "hdr invalid length"); 32228ccfb1eSJanosch Frank uvcb_csc.header.len += 8; 32328ccfb1eSJanosch Frank 32428ccfb1eSJanosch Frank uvcb_csc.guest_handle += 1; 32528ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 32628ccfb1eSJanosch Frank report(uvcb_csc.header.rc == UVC_RC_INV_GHANDLE && rc == 1, 32728ccfb1eSJanosch Frank "invalid guest handle"); 32828ccfb1eSJanosch Frank uvcb_csc.guest_handle -= 1; 32928ccfb1eSJanosch Frank 33028ccfb1eSJanosch Frank uvcb_csc.num = uvcb_qui.max_guest_cpus + 1; 33128ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 33228ccfb1eSJanosch Frank report(uvcb_csc.header.rc == 0x103 && rc == 1, 33328ccfb1eSJanosch Frank "invalid cpu #"); 33428ccfb1eSJanosch Frank uvcb_csc.num = 0; 33528ccfb1eSJanosch Frank 33628ccfb1eSJanosch Frank tmp = uvcb_csc.stor_origin; 33728ccfb1eSJanosch Frank uvcb_csc.stor_origin = get_max_ram_size() + PAGE_SIZE; 33828ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 33928ccfb1eSJanosch Frank report(uvcb_csc.header.rc == 0x105 && rc == 1, 34028ccfb1eSJanosch Frank "cpu stor inaccessible"); 34128ccfb1eSJanosch Frank uvcb_csc.stor_origin = tmp; 34228ccfb1eSJanosch Frank 34328ccfb1eSJanosch Frank tmp = uvcb_csc.stor_origin; 34428ccfb1eSJanosch Frank uvcb_csc.stor_origin = 0; 34528ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 34628ccfb1eSJanosch Frank report(uvcb_csc.header.rc == 0x106 && rc == 1, 34728ccfb1eSJanosch Frank "cpu stor in lowcore"); 34828ccfb1eSJanosch Frank uvcb_csc.stor_origin = tmp; 34928ccfb1eSJanosch Frank 35028ccfb1eSJanosch Frank tmp = uvcb_csc.state_origin; 35128ccfb1eSJanosch Frank uvcb_csc.state_origin = get_max_ram_size() + PAGE_SIZE; 35228ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 35328ccfb1eSJanosch Frank report(uvcb_csc.header.rc == 0x107 && rc == 1, 35428ccfb1eSJanosch Frank "SIE SD inaccessible"); 35528ccfb1eSJanosch Frank uvcb_csc.state_origin = tmp; 35628ccfb1eSJanosch Frank 35728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 35828ccfb1eSJanosch Frank report(rc == 0 && uvcb_csc.header.rc == UVC_RC_EXECUTED && 35928ccfb1eSJanosch Frank uvcb_csc.cpu_handle, "success"); 36028ccfb1eSJanosch Frank 361b9ff8da5SJanosch Frank rc = access_check_3d((uint8_t *)uvcb_csc.stor_origin, 362b9ff8da5SJanosch Frank uvcb_qui.cpu_stor_len); 363b9ff8da5SJanosch Frank report(rc, "Storage protection"); 364b9ff8da5SJanosch Frank 36528ccfb1eSJanosch Frank tmp = uvcb_csc.stor_origin; 36628ccfb1eSJanosch Frank uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len); 36728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 36828ccfb1eSJanosch Frank report(rc == 1 && uvcb_csc.header.rc == 0x104, "already defined"); 36928ccfb1eSJanosch Frank uvcb_csc.stor_origin = tmp; 37028ccfb1eSJanosch Frank report_prefix_pop(); 37128ccfb1eSJanosch Frank } 37228ccfb1eSJanosch Frank 373*484ab8dcSJanosch Frank /* 374*484ab8dcSJanosch Frank * If the first bit of the rc is set we need to destroy the 375*484ab8dcSJanosch Frank * configuration before testing other create config errors. 376*484ab8dcSJanosch Frank */ 377*484ab8dcSJanosch Frank static void cgc_destroy_if_needed(struct uv_cb_cgc *uvcb) 378*484ab8dcSJanosch Frank { 379*484ab8dcSJanosch Frank uint16_t rc, rrc; 380*484ab8dcSJanosch Frank 381*484ab8dcSJanosch Frank if (uvcb->header.rc != UVC_RC_EXECUTED && 382*484ab8dcSJanosch Frank !(uvcb->header.rc & UVC_RC_DSTR_NEEDED_FLG)) 383*484ab8dcSJanosch Frank return; 384*484ab8dcSJanosch Frank 385*484ab8dcSJanosch Frank assert(uvcb->guest_handle); 386*484ab8dcSJanosch Frank assert(!uv_cmd_nodata(uvcb->guest_handle, UVC_CMD_DESTROY_SEC_CONF, 387*484ab8dcSJanosch Frank &rc, &rrc)); 388*484ab8dcSJanosch Frank 389*484ab8dcSJanosch Frank /* We need to zero it for the next test */ 390*484ab8dcSJanosch Frank uvcb->guest_handle = 0; 391*484ab8dcSJanosch Frank } 392*484ab8dcSJanosch Frank 393*484ab8dcSJanosch Frank static bool cgc_check_data(struct uv_cb_cgc *uvcb, uint16_t rc_expected) 394*484ab8dcSJanosch Frank { 395*484ab8dcSJanosch Frank /* This function purely checks for error rcs */ 396*484ab8dcSJanosch Frank if (uvcb->header.rc == UVC_RC_EXECUTED) 397*484ab8dcSJanosch Frank return false; 398*484ab8dcSJanosch Frank 399*484ab8dcSJanosch Frank /* 400*484ab8dcSJanosch Frank * We should only receive a handle when the rc is 1 or the 401*484ab8dcSJanosch Frank * first bit is set. 402*484ab8dcSJanosch Frank */ 403*484ab8dcSJanosch Frank if (!(uvcb->header.rc & UVC_RC_DSTR_NEEDED_FLG) && uvcb->guest_handle) 404*484ab8dcSJanosch Frank report_abort("Received a handle when we didn't expect one"); 405*484ab8dcSJanosch Frank 406*484ab8dcSJanosch Frank return (uvcb->header.rc & ~UVC_RC_DSTR_NEEDED_FLG) == rc_expected; 407*484ab8dcSJanosch Frank } 408*484ab8dcSJanosch Frank 40928ccfb1eSJanosch Frank static void test_config_create(void) 41028ccfb1eSJanosch Frank { 41128ccfb1eSJanosch Frank int rc; 41228ccfb1eSJanosch Frank unsigned long vsize, tmp; 41328ccfb1eSJanosch Frank static struct uv_cb_cgc uvcb; 41428ccfb1eSJanosch Frank 41528ccfb1eSJanosch Frank uvcb_cgc.header.cmd = UVC_CMD_CREATE_SEC_CONF; 41628ccfb1eSJanosch Frank uvcb_cgc.header.len = sizeof(uvcb_cgc); 41728ccfb1eSJanosch Frank report_prefix_push("cgc"); 41828ccfb1eSJanosch Frank 41928ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = 0; 42028ccfb1eSJanosch Frank uvcb_cgc.guest_stor_len = 42 * (1UL << 20); 42128ccfb1eSJanosch Frank vsize = uvcb_qui.conf_base_virt_stor_len + 42228ccfb1eSJanosch Frank ((uvcb_cgc.guest_stor_len / (1UL << 20)) * uvcb_qui.conf_virt_var_stor_len); 42328ccfb1eSJanosch Frank 42428ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len); 42528ccfb1eSJanosch Frank uvcb_cgc.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize); 42628ccfb1eSJanosch Frank uvcb_cgc.guest_asce = (uint64_t)memalign(PAGE_SIZE, 4 * PAGE_SIZE) | ASCE_DT_SEGMENT | REGION_TABLE_LENGTH | ASCE_P; 42728ccfb1eSJanosch Frank uvcb_cgc.guest_sca = (uint64_t)memalign(PAGE_SIZE * 4, PAGE_SIZE * 4); 42828ccfb1eSJanosch Frank 42928ccfb1eSJanosch Frank uvcb_cgc.header.len -= 8; 43028ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 43128ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == UVC_RC_INV_LEN && rc == 1 && 43228ccfb1eSJanosch Frank !uvcb_cgc.guest_handle, "hdr invalid length"); 433*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 43428ccfb1eSJanosch Frank uvcb_cgc.header.len += 8; 43528ccfb1eSJanosch Frank 43628ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = uvcb_qui.max_guest_stor_addr + (1UL << 20) * 2 + 1; 43728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 438*484ab8dcSJanosch Frank report(cgc_check_data(&uvcb_cgc, 0x101) && rc == 1, 43928ccfb1eSJanosch Frank "MSO > max guest addr"); 440*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 44128ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = 0; 44228ccfb1eSJanosch Frank 44328ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = uvcb_qui.max_guest_stor_addr - (1UL << 20); 44428ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 445*484ab8dcSJanosch Frank report(cgc_check_data(&uvcb_cgc, 0x102) && rc == 1, 44628ccfb1eSJanosch Frank "MSO + MSL > max guest addr"); 447*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 44828ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = 0; 44928ccfb1eSJanosch Frank 45028ccfb1eSJanosch Frank uvcb_cgc.guest_asce &= ~ASCE_P; 45128ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 452*484ab8dcSJanosch Frank report(cgc_check_data(&uvcb_cgc, 0x105) && rc == 1, 45328ccfb1eSJanosch Frank "ASCE private bit missing"); 454*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 45528ccfb1eSJanosch Frank uvcb_cgc.guest_asce |= ASCE_P; 45628ccfb1eSJanosch Frank 45728ccfb1eSJanosch Frank uvcb_cgc.guest_asce |= 0x20; 45828ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 459*484ab8dcSJanosch Frank report(cgc_check_data(&uvcb_cgc, 0x105) && rc == 1, 46028ccfb1eSJanosch Frank "ASCE bit 58 set"); 461*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 46228ccfb1eSJanosch Frank uvcb_cgc.guest_asce &= ~0x20; 46328ccfb1eSJanosch Frank 46428ccfb1eSJanosch Frank tmp = uvcb_cgc.conf_base_stor_origin; 46528ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = get_max_ram_size() + 8; 46628ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 467*484ab8dcSJanosch Frank report(cgc_check_data(&uvcb_cgc, 0x108) && rc == 1, 46828ccfb1eSJanosch Frank "base storage origin > available memory"); 469*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 47028ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = tmp; 47128ccfb1eSJanosch Frank 47228ccfb1eSJanosch Frank tmp = uvcb_cgc.conf_base_stor_origin; 47328ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = 0x1000; 47428ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 475*484ab8dcSJanosch Frank report(cgc_check_data(&uvcb_cgc, 0x109) && rc == 1, 476*484ab8dcSJanosch Frank "base storage origin contains lowcore %x", uvcb_cgc.header.rc); 477*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 47828ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = tmp; 47928ccfb1eSJanosch Frank 48028ccfb1eSJanosch Frank tmp = uvcb_cgc.guest_sca; 48128ccfb1eSJanosch Frank uvcb_cgc.guest_sca = 0; 48228ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 483*484ab8dcSJanosch Frank report(cgc_check_data(&uvcb_cgc, 0x10c) && rc == 1, 48428ccfb1eSJanosch Frank "sca == 0"); 485*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 48628ccfb1eSJanosch Frank uvcb_cgc.guest_sca = tmp; 48728ccfb1eSJanosch Frank 48828ccfb1eSJanosch Frank tmp = uvcb_cgc.guest_sca; 4895e83f9d0SJanosch Frank uvcb_cgc.guest_sca = get_max_ram_size() + PAGE_SIZE * 4; 49028ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 491*484ab8dcSJanosch Frank report(cgc_check_data(&uvcb_cgc, 0x10d) && rc == 1, 49228ccfb1eSJanosch Frank "sca inaccessible"); 493*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 49428ccfb1eSJanosch Frank uvcb_cgc.guest_sca = tmp; 49528ccfb1eSJanosch Frank 49628ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 49728ccfb1eSJanosch Frank report(rc == 0 && uvcb_cgc.header.rc == UVC_RC_EXECUTED, "successful"); 49828ccfb1eSJanosch Frank 499b9ff8da5SJanosch Frank rc = access_check_3d((uint8_t *)uvcb_cgc.conf_base_stor_origin, 500b9ff8da5SJanosch Frank uvcb_qui.conf_base_phys_stor_len); 501b9ff8da5SJanosch Frank report(rc, "Base storage protection"); 502b9ff8da5SJanosch Frank 503b9ff8da5SJanosch Frank rc = access_check_3d((uint8_t *)uvcb_cgc.conf_var_stor_origin, vsize); 504b9ff8da5SJanosch Frank report(rc, "Variable storage protection"); 505b9ff8da5SJanosch Frank 50628ccfb1eSJanosch Frank uvcb_cgc.header.rc = 0; 50728ccfb1eSJanosch Frank uvcb_cgc.header.rrc = 0; 50828ccfb1eSJanosch Frank tmp = uvcb_cgc.guest_handle; 50928ccfb1eSJanosch Frank uvcb_cgc.guest_handle = 0; 51028ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 51128ccfb1eSJanosch Frank report(uvcb_cgc.header.rc >= 0x100 && rc == 1, "reuse uvcb"); 512*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb_cgc); 51328ccfb1eSJanosch Frank uvcb_cgc.guest_handle = tmp; 51428ccfb1eSJanosch Frank 51528ccfb1eSJanosch Frank /* Copy over most data from uvcb_cgc, so we have the ASCE that was used. */ 51628ccfb1eSJanosch Frank memcpy(&uvcb, &uvcb_cgc, sizeof(uvcb)); 51728ccfb1eSJanosch Frank 51828ccfb1eSJanosch Frank /* Reset the header and handle */ 51928ccfb1eSJanosch Frank uvcb.header.rc = 0; 52028ccfb1eSJanosch Frank uvcb.header.rrc = 0; 52128ccfb1eSJanosch Frank uvcb.guest_handle = 0; 52228ccfb1eSJanosch Frank 52328ccfb1eSJanosch Frank /* Use new storage areas. */ 52428ccfb1eSJanosch Frank uvcb.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len); 52528ccfb1eSJanosch Frank uvcb.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize); 52628ccfb1eSJanosch Frank 52728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 52828ccfb1eSJanosch Frank report(uvcb.header.rc >= 0x104 && rc == 1 && !uvcb.guest_handle, 52928ccfb1eSJanosch Frank "reuse ASCE"); 530*484ab8dcSJanosch Frank cgc_destroy_if_needed(&uvcb); 53128ccfb1eSJanosch Frank free((void *)uvcb.conf_base_stor_origin); 53228ccfb1eSJanosch Frank free((void *)uvcb.conf_var_stor_origin); 53328ccfb1eSJanosch Frank 53428ccfb1eSJanosch Frank /* Missing: 106, 10a, a0b */ 53528ccfb1eSJanosch Frank report_prefix_pop(); 53628ccfb1eSJanosch Frank } 53728ccfb1eSJanosch Frank 53828ccfb1eSJanosch Frank static void test_init(void) 53928ccfb1eSJanosch Frank { 54028ccfb1eSJanosch Frank int rc; 5414033c512SJanosch Frank uint64_t tmp; 54228ccfb1eSJanosch Frank 5434033c512SJanosch Frank /* 5444033c512SJanosch Frank * Donated storage needs to be over 2GB, AREA_NORMAL does that 5454033c512SJanosch Frank * on s390x. 5464033c512SJanosch Frank */ 5474033c512SJanosch Frank tmp = (uint64_t)memalign_pages_flags(SZ_1M, uvcb_qui.uv_base_stor_len, AREA_NORMAL); 54828ccfb1eSJanosch Frank 54928ccfb1eSJanosch Frank uvcb_init.header.len = sizeof(uvcb_init); 55028ccfb1eSJanosch Frank uvcb_init.header.cmd = UVC_CMD_INIT_UV; 5514033c512SJanosch Frank uvcb_init.stor_origin = tmp; 55228ccfb1eSJanosch Frank uvcb_init.stor_len = uvcb_qui.uv_base_stor_len; 55328ccfb1eSJanosch Frank 55428ccfb1eSJanosch Frank report_prefix_push("init"); 55528ccfb1eSJanosch Frank uvcb_init.header.len -= 8; 55628ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 55728ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == UVC_RC_INV_LEN, 55828ccfb1eSJanosch Frank "hdr invalid length"); 55928ccfb1eSJanosch Frank uvcb_init.header.len += 8; 56028ccfb1eSJanosch Frank 56128ccfb1eSJanosch Frank uvcb_init.stor_len -= 8; 56228ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 56328ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x103, 56428ccfb1eSJanosch Frank "storage invalid length"); 56528ccfb1eSJanosch Frank uvcb_init.stor_len += 8; 56628ccfb1eSJanosch Frank 567fa61eb8eSJanosch Frank /* Storage origin is 1MB aligned, the length is 4KB aligned */ 568fa61eb8eSJanosch Frank uvcb_init.stor_origin = get_max_ram_size(); 56928ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 570fa61eb8eSJanosch Frank report(rc == 1 && (uvcb_init.header.rc == 0x104 || uvcb_init.header.rc == 0x105), 57128ccfb1eSJanosch Frank "storage origin invalid"); 5724033c512SJanosch Frank uvcb_init.stor_origin = tmp; 57328ccfb1eSJanosch Frank 574fa61eb8eSJanosch Frank if (uvcb_init.stor_len >= HPAGE_SIZE) { 575fa61eb8eSJanosch Frank uvcb_init.stor_origin = get_max_ram_size() - HPAGE_SIZE; 57628ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 57728ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x105, 57828ccfb1eSJanosch Frank "storage + length invalid"); 5794033c512SJanosch Frank uvcb_init.stor_origin = tmp; 580fa61eb8eSJanosch Frank } else { 581fa61eb8eSJanosch Frank report_skip("storage + length invalid, stor_len < HPAGE_SIZE"); 582fa61eb8eSJanosch Frank } 58328ccfb1eSJanosch Frank 58428ccfb1eSJanosch Frank uvcb_init.stor_origin = 1UL << 30; 58528ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 58628ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x108, 58728ccfb1eSJanosch Frank "storage below 2GB"); 5884033c512SJanosch Frank uvcb_init.stor_origin = tmp; 58928ccfb1eSJanosch Frank 590333011bbSJanosch Frank if (smp_query_num_cpus() > 1) { 591f514b4f7SClaudio Imbrenda smp_cpu_setup(1, PSW_WITH_CUR_MASK(cpu_loop)); 59228ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 59328ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x102, 59428ccfb1eSJanosch Frank "too many running cpus"); 59528ccfb1eSJanosch Frank smp_cpu_stop(1); 596333011bbSJanosch Frank } else { 597333011bbSJanosch Frank report_skip("Not enough cpus for 0x102 test"); 598333011bbSJanosch Frank } 59928ccfb1eSJanosch Frank 60028ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 60128ccfb1eSJanosch Frank report(rc == 0 && uvcb_init.header.rc == UVC_RC_EXECUTED, "successful"); 60228ccfb1eSJanosch Frank 6034033c512SJanosch Frank tmp = uvcb_init.stor_origin; 6044033c512SJanosch Frank uvcb_init.stor_origin = (uint64_t)memalign_pages_flags(HPAGE_SIZE, uvcb_qui.uv_base_stor_len, AREA_NORMAL); 60528ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 60628ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x101, "double init"); 6074033c512SJanosch Frank free((void *)uvcb_init.stor_origin); 6084033c512SJanosch Frank uvcb_init.stor_origin = tmp; 60928ccfb1eSJanosch Frank 61028ccfb1eSJanosch Frank report_prefix_pop(); 61128ccfb1eSJanosch Frank } 61228ccfb1eSJanosch Frank 61328ccfb1eSJanosch Frank static void test_query(void) 61428ccfb1eSJanosch Frank { 615cde26b62SJanosch Frank int i = 0, cc; 61628ccfb1eSJanosch Frank 61728ccfb1eSJanosch Frank uvcb_qui.header.cmd = UVC_CMD_QUI; 61828ccfb1eSJanosch Frank uvcb_qui.header.len = sizeof(uvcb_qui); 61928ccfb1eSJanosch Frank 62028ccfb1eSJanosch Frank report_prefix_push("query"); 62128ccfb1eSJanosch Frank uvcb_qui.header.len = 0xa0; 62228ccfb1eSJanosch Frank uv_call(0, (uint64_t)&uvcb_qui); 62328ccfb1eSJanosch Frank report(uvcb_qui.header.rc == UVC_RC_INV_LEN, "length"); 62428ccfb1eSJanosch Frank 62528ccfb1eSJanosch Frank uvcb_qui.header.len = 0xa8; 62628ccfb1eSJanosch Frank uv_call(0, (uint64_t)&uvcb_qui); 62728ccfb1eSJanosch Frank report(uvcb_qui.header.rc == 0x100, "insf length"); 62828ccfb1eSJanosch Frank 62928ccfb1eSJanosch Frank uvcb_qui.header.len = sizeof(uvcb_qui); 630cde26b62SJanosch Frank cc = uv_call(0, (uint64_t)&uvcb_qui); 631cde26b62SJanosch Frank report((!cc && uvcb_qui.header.rc == UVC_RC_EXECUTED) || 632cde26b62SJanosch Frank (cc == 1 && uvcb_qui.header.rc == 0x100), 633cde26b62SJanosch Frank "successful query"); 63428ccfb1eSJanosch Frank 63528ccfb1eSJanosch Frank for (i = 0; cmds[i].name; i++) 63628ccfb1eSJanosch Frank report(uv_query_test_call(cmds[i].call_bit), "%s", cmds[i].name); 63728ccfb1eSJanosch Frank 63828ccfb1eSJanosch Frank report_prefix_pop(); 63928ccfb1eSJanosch Frank } 64028ccfb1eSJanosch Frank 64128ccfb1eSJanosch Frank static struct cmd_list invalid_cmds[] = { 64228ccfb1eSJanosch Frank { "bogus", 0x4242, sizeof(struct uv_cb_header), -1}, 64328ccfb1eSJanosch Frank { "share", UVC_CMD_SET_SHARED_ACCESS, sizeof(struct uv_cb_share), BIT_UVC_CMD_SET_SHARED_ACCESS }, 64428ccfb1eSJanosch Frank { "unshare", UVC_CMD_REMOVE_SHARED_ACCESS, sizeof(struct uv_cb_share), BIT_UVC_CMD_REMOVE_SHARED_ACCESS }, 6456a87e02cSSteffen Eiden { "attest", UVC_CMD_ATTESTATION, sizeof(struct uv_cb_attest), BIT_UVC_CMD_ATTESTATION }, 64628ccfb1eSJanosch Frank { NULL, 0, 0 }, 64728ccfb1eSJanosch Frank }; 64828ccfb1eSJanosch Frank 64928ccfb1eSJanosch Frank static void test_invalid(void) 65028ccfb1eSJanosch Frank { 65128ccfb1eSJanosch Frank struct uv_cb_header hdr = {}; 65228ccfb1eSJanosch Frank int i, cc; 65328ccfb1eSJanosch Frank 65428ccfb1eSJanosch Frank report_prefix_push("invalid"); 65528ccfb1eSJanosch Frank for (i = 0; invalid_cmds[i].name; i++) { 65628ccfb1eSJanosch Frank hdr.cmd = invalid_cmds[i].cmd; 65728ccfb1eSJanosch Frank hdr.len = invalid_cmds[i].len; 65828ccfb1eSJanosch Frank cc = uv_call(0, (uint64_t)&hdr); 65928ccfb1eSJanosch Frank report(cc == 1 && hdr.rc == UVC_RC_INV_CMD && 66028ccfb1eSJanosch Frank (invalid_cmds[i].call_bit == -1 || !uv_query_test_call(invalid_cmds[i].call_bit)), 66128ccfb1eSJanosch Frank "%s", invalid_cmds[i].name); 66228ccfb1eSJanosch Frank } 66328ccfb1eSJanosch Frank report_prefix_pop(); 66428ccfb1eSJanosch Frank } 66528ccfb1eSJanosch Frank 666b744815eSJanosch Frank static void setup_test_clear(void) 667b744815eSJanosch Frank { 668b744815eSJanosch Frank unsigned long vsize; 669b744815eSJanosch Frank int rc; 670b744815eSJanosch Frank 671b744815eSJanosch Frank uvcb_cgc.header.cmd = UVC_CMD_CREATE_SEC_CONF; 672b744815eSJanosch Frank uvcb_cgc.header.len = sizeof(uvcb_cgc); 673b744815eSJanosch Frank 674b744815eSJanosch Frank uvcb_cgc.guest_stor_origin = 0; 675b744815eSJanosch Frank uvcb_cgc.guest_stor_len = 42 * (1UL << 20); 676b744815eSJanosch Frank vsize = uvcb_qui.conf_base_virt_stor_len + 677b744815eSJanosch Frank ((uvcb_cgc.guest_stor_len / (1UL << 20)) * uvcb_qui.conf_virt_var_stor_len); 678b744815eSJanosch Frank 679b744815eSJanosch Frank uvcb_cgc.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len); 680b744815eSJanosch Frank uvcb_cgc.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize); 681b744815eSJanosch Frank uvcb_cgc.guest_asce = (uint64_t)memalign(PAGE_SIZE, 4 * PAGE_SIZE) | ASCE_DT_SEGMENT | REGION_TABLE_LENGTH | ASCE_P; 682b744815eSJanosch Frank uvcb_cgc.guest_sca = (uint64_t)memalign(PAGE_SIZE * 4, PAGE_SIZE * 4); 683b744815eSJanosch Frank 684b744815eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 685b744815eSJanosch Frank assert(rc == 0); 686b744815eSJanosch Frank 687b744815eSJanosch Frank uvcb_csc.header.len = sizeof(uvcb_csc); 688b744815eSJanosch Frank uvcb_csc.header.cmd = UVC_CMD_CREATE_SEC_CPU; 689b744815eSJanosch Frank uvcb_csc.guest_handle = uvcb_cgc.guest_handle; 690b744815eSJanosch Frank uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len); 691b744815eSJanosch Frank uvcb_csc.state_origin = (unsigned long)memalign(PAGE_SIZE, PAGE_SIZE); 692b744815eSJanosch Frank 693b744815eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 694b744815eSJanosch Frank assert(rc == 0); 695b744815eSJanosch Frank } 696b744815eSJanosch Frank 69728ccfb1eSJanosch Frank static void test_clear(void) 69828ccfb1eSJanosch Frank { 699b744815eSJanosch Frank uint64_t *tmp; 700b744815eSJanosch Frank 701b744815eSJanosch Frank report_prefix_push("load normal reset"); 702b744815eSJanosch Frank 703b744815eSJanosch Frank /* 704b744815eSJanosch Frank * Setup a config and a cpu so we can check if a diag308 reset 705b744815eSJanosch Frank * clears the donated memory and makes the pages unsecure. 706b744815eSJanosch Frank */ 707b744815eSJanosch Frank setup_test_clear(); 70828ccfb1eSJanosch Frank 70928ccfb1eSJanosch Frank diag308_load_reset(1); 71028ccfb1eSJanosch Frank sclp_console_setup(); 711b744815eSJanosch Frank 712b744815eSJanosch Frank tmp = (void *)uvcb_init.stor_origin; 713b744815eSJanosch Frank report(!*tmp, "uv init donated memory cleared"); 714b744815eSJanosch Frank 715b744815eSJanosch Frank tmp = (void *)uvcb_cgc.conf_base_stor_origin; 716b744815eSJanosch Frank report(!*tmp, "config base donated memory cleared"); 717b744815eSJanosch Frank 718b744815eSJanosch Frank tmp = (void *)uvcb_cgc.conf_base_stor_origin; 719b744815eSJanosch Frank report(!*tmp, "config variable donated memory cleared"); 720b744815eSJanosch Frank 721b744815eSJanosch Frank tmp = (void *)uvcb_csc.stor_origin; 722b744815eSJanosch Frank report(!*tmp, "cpu donated memory cleared after reset 1"); 723b744815eSJanosch Frank 724b744815eSJanosch Frank /* Check if uninitialized after reset */ 725b744815eSJanosch Frank test_uv_uninitialized(); 726b744815eSJanosch Frank 727b744815eSJanosch Frank report_prefix_pop(); 72828ccfb1eSJanosch Frank } 72928ccfb1eSJanosch Frank 73028ccfb1eSJanosch Frank static void setup_vmem(void) 73128ccfb1eSJanosch Frank { 732136d73e3SJanosch Frank uint64_t asce; 73328ccfb1eSJanosch Frank 7340a5b31d2SSean Christopherson setup_mmu(get_max_ram_size(), NULL); 735136d73e3SJanosch Frank /* 736136d73e3SJanosch Frank * setup_mmu() will enable DAT and set the primary address 737136d73e3SJanosch Frank * space but we need to have a valid home space since UV calls 738136d73e3SJanosch Frank * take home space virtual addresses. 739136d73e3SJanosch Frank * 740136d73e3SJanosch Frank * Hence we just copy the primary asce into the home space. 741136d73e3SJanosch Frank */ 74228ccfb1eSJanosch Frank asce = stctg(1); 74328ccfb1eSJanosch Frank lctlg(13, asce); 74428ccfb1eSJanosch Frank } 74528ccfb1eSJanosch Frank 74628ccfb1eSJanosch Frank int main(void) 74728ccfb1eSJanosch Frank { 74828ccfb1eSJanosch Frank bool has_uvc = test_facility(158); 74928ccfb1eSJanosch Frank 75028ccfb1eSJanosch Frank report_prefix_push("uvc"); 75128ccfb1eSJanosch Frank if (!has_uvc) { 75228ccfb1eSJanosch Frank report_skip("Ultravisor call facility is not available"); 75328ccfb1eSJanosch Frank goto done; 75428ccfb1eSJanosch Frank } 7554762a72eSJanosch Frank if (!uv_os_is_host()) { 7564762a72eSJanosch Frank report_skip("This test needs to be run in a UV host environment"); 7574762a72eSJanosch Frank goto done; 7584762a72eSJanosch Frank } 75928ccfb1eSJanosch Frank 7605078e7a7SJanosch Frank test_i3(); 76128ccfb1eSJanosch Frank test_priv(); 76228ccfb1eSJanosch Frank test_invalid(); 763b744815eSJanosch Frank test_uv_uninitialized(); 76428ccfb1eSJanosch Frank test_query(); 76590704fe2SJanosch Frank 76690704fe2SJanosch Frank if (get_ram_size() < SNIPPET_PV_MIN_MEM_SIZE) { 76790704fe2SJanosch Frank report_skip("Not enough memory. This test needs about %ld MB of memory", 76890704fe2SJanosch Frank SNIPPET_PV_MIN_MEM_SIZE / SZ_1M); 76990704fe2SJanosch Frank goto done; 77090704fe2SJanosch Frank } 77190704fe2SJanosch Frank 77228ccfb1eSJanosch Frank test_init(); 77328ccfb1eSJanosch Frank 77428ccfb1eSJanosch Frank setup_vmem(); 77591d18441SJanosch Frank test_access(); 77691d18441SJanosch Frank 77728ccfb1eSJanosch Frank test_config_create(); 77828ccfb1eSJanosch Frank test_cpu_create(); 779692447f2SJanosch Frank test_set_se_header(); 78028ccfb1eSJanosch Frank test_cpu_destroy(); 78128ccfb1eSJanosch Frank test_config_destroy(); 78228ccfb1eSJanosch Frank test_clear(); 78328ccfb1eSJanosch Frank 78428ccfb1eSJanosch Frank done: 78528ccfb1eSJanosch Frank return report_summary(); 78628ccfb1eSJanosch Frank } 787