128ccfb1eSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */ 228ccfb1eSJanosch Frank /* 328ccfb1eSJanosch Frank * Guest 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> 12*5bf29e09SClaudio 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> 1828ccfb1eSJanosch Frank #include <asm/page.h> 1928ccfb1eSJanosch Frank #include <asm/sigp.h> 2028ccfb1eSJanosch Frank #include <asm/pgtable.h> 2128ccfb1eSJanosch Frank #include <asm/asm-offsets.h> 2228ccfb1eSJanosch Frank #include <asm/interrupt.h> 2328ccfb1eSJanosch Frank #include <asm/facility.h> 2428ccfb1eSJanosch Frank #include <asm/uv.h> 2528ccfb1eSJanosch Frank #include <asm-generic/barrier.h> 2628ccfb1eSJanosch Frank 2728ccfb1eSJanosch Frank static struct uv_cb_qui uvcb_qui; 2828ccfb1eSJanosch Frank static struct uv_cb_init uvcb_init; 2928ccfb1eSJanosch Frank static struct uv_cb_cgc uvcb_cgc; 3028ccfb1eSJanosch Frank static struct uv_cb_csc uvcb_csc; 3128ccfb1eSJanosch Frank 3228ccfb1eSJanosch Frank extern int diag308_load_reset(u64 code); 3328ccfb1eSJanosch Frank 3428ccfb1eSJanosch Frank struct cmd_list{ 3528ccfb1eSJanosch Frank const char *name; 3628ccfb1eSJanosch Frank uint16_t cmd; 3728ccfb1eSJanosch Frank uint16_t len; 3828ccfb1eSJanosch Frank int call_bit; 3928ccfb1eSJanosch Frank }; 4028ccfb1eSJanosch Frank 4128ccfb1eSJanosch Frank static void cpu_loop(void) 4228ccfb1eSJanosch Frank { 4328ccfb1eSJanosch Frank for (;;) {} 4428ccfb1eSJanosch Frank } 4528ccfb1eSJanosch Frank 4628ccfb1eSJanosch Frank static struct cmd_list cmds[] = { 4728ccfb1eSJanosch Frank { "init", UVC_CMD_INIT_UV, sizeof(struct uv_cb_init), BIT_UVC_CMD_INIT_UV }, 4828ccfb1eSJanosch Frank { "create conf", UVC_CMD_CREATE_SEC_CONF, sizeof(struct uv_cb_cgc), BIT_UVC_CMD_CREATE_SEC_CONF }, 4928ccfb1eSJanosch Frank { "destroy conf", UVC_CMD_DESTROY_SEC_CONF, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CONF }, 5028ccfb1eSJanosch Frank { "create cpu", UVC_CMD_CREATE_SEC_CPU, sizeof(struct uv_cb_csc), BIT_UVC_CMD_CREATE_SEC_CPU }, 5128ccfb1eSJanosch Frank { "destroy cpu", UVC_CMD_DESTROY_SEC_CPU, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CPU }, 5228ccfb1eSJanosch Frank { "conv to", UVC_CMD_CONV_TO_SEC_STOR, sizeof(struct uv_cb_cts), BIT_UVC_CMD_CONV_TO_SEC_STOR }, 5328ccfb1eSJanosch Frank { "conv from", UVC_CMD_CONV_FROM_SEC_STOR, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_CONV_FROM_SEC_STOR }, 5428ccfb1eSJanosch Frank { "set sec conf", UVC_CMD_SET_SEC_CONF_PARAMS, sizeof(struct uv_cb_ssc), BIT_UVC_CMD_SET_SEC_PARMS }, 5528ccfb1eSJanosch Frank { "unpack", UVC_CMD_UNPACK_IMG, sizeof(struct uv_cb_unp), BIT_UVC_CMD_UNPACK_IMG }, 5628ccfb1eSJanosch Frank { "verify", UVC_CMD_VERIFY_IMG, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_VERIFY_IMG }, 5728ccfb1eSJanosch Frank { "cpu reset", UVC_CMD_CPU_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET }, 5828ccfb1eSJanosch Frank { "cpu initial reset", UVC_CMD_CPU_RESET_INITIAL, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET_INITIAL }, 595630c446SJanosch Frank { "conf clear reset", UVC_CMD_PREPARE_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_PREPARE_RESET }, 6028ccfb1eSJanosch Frank { "cpu clear reset", UVC_CMD_CPU_RESET_CLEAR, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET }, 6128ccfb1eSJanosch Frank { "cpu set state", UVC_CMD_CPU_SET_STATE, sizeof(struct uv_cb_cpu_set_state), BIT_UVC_CMD_CPU_SET_STATE }, 6228ccfb1eSJanosch Frank { "pin shared", UVC_CMD_PIN_PAGE_SHARED, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_PIN_PAGE_SHARED }, 6328ccfb1eSJanosch Frank { "unpin shared", UVC_CMD_UNPIN_PAGE_SHARED, sizeof(struct uv_cb_cts), BIT_UVC_CMD_UNPIN_PAGE_SHARED }, 6428ccfb1eSJanosch Frank { NULL, 0, 0 }, 6528ccfb1eSJanosch Frank }; 6628ccfb1eSJanosch Frank 6728ccfb1eSJanosch Frank static void test_priv(void) 6828ccfb1eSJanosch Frank { 6928ccfb1eSJanosch Frank struct uv_cb_header uvcb = {}; 7028ccfb1eSJanosch Frank uint16_t pgm; 7128ccfb1eSJanosch Frank int i; 7228ccfb1eSJanosch Frank 7328ccfb1eSJanosch Frank report_prefix_push("privileged"); 7428ccfb1eSJanosch Frank for (i = 0; cmds[i].name; i++) { 7528ccfb1eSJanosch Frank expect_pgm_int(); 7628ccfb1eSJanosch Frank uvcb.cmd = cmds[i].cmd; 7728ccfb1eSJanosch Frank uvcb.len = cmds[i].len; 7828ccfb1eSJanosch Frank enter_pstate(); 7928ccfb1eSJanosch Frank uv_call(0, (uint64_t)&uvcb); 8028ccfb1eSJanosch Frank pgm = clear_pgm_int(); 8128ccfb1eSJanosch Frank report(pgm == PGM_INT_CODE_PRIVILEGED_OPERATION, "%s", cmds[i].name); 8228ccfb1eSJanosch Frank } 8328ccfb1eSJanosch Frank report_prefix_pop(); 8428ccfb1eSJanosch Frank } 8528ccfb1eSJanosch Frank 8628ccfb1eSJanosch Frank static void test_config_destroy(void) 8728ccfb1eSJanosch Frank { 8828ccfb1eSJanosch Frank int rc; 8928ccfb1eSJanosch Frank struct uv_cb_nodata uvcb = { 9028ccfb1eSJanosch Frank .header.cmd = UVC_CMD_DESTROY_SEC_CONF, 9128ccfb1eSJanosch Frank .header.len = sizeof(uvcb), 9228ccfb1eSJanosch Frank .handle = uvcb_cgc.guest_handle, 9328ccfb1eSJanosch Frank }; 9428ccfb1eSJanosch Frank 9528ccfb1eSJanosch Frank report_prefix_push("dsc"); 9628ccfb1eSJanosch Frank uvcb.header.len -= 8; 9728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 9828ccfb1eSJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, 9928ccfb1eSJanosch Frank "hdr invalid length"); 10028ccfb1eSJanosch Frank uvcb.header.len += 8; 10128ccfb1eSJanosch Frank 10228ccfb1eSJanosch Frank uvcb.handle += 1; 10328ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 10428ccfb1eSJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_GHANDLE, "invalid handle"); 10528ccfb1eSJanosch Frank uvcb.handle -= 1; 10628ccfb1eSJanosch Frank 10728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 10828ccfb1eSJanosch Frank report(rc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "success"); 10928ccfb1eSJanosch Frank report_prefix_pop(); 11028ccfb1eSJanosch Frank } 11128ccfb1eSJanosch Frank 11228ccfb1eSJanosch Frank static void test_cpu_destroy(void) 11328ccfb1eSJanosch Frank { 11428ccfb1eSJanosch Frank int rc; 11528ccfb1eSJanosch Frank struct uv_cb_nodata uvcb = { 11628ccfb1eSJanosch Frank .header.len = sizeof(uvcb), 11728ccfb1eSJanosch Frank .header.cmd = UVC_CMD_DESTROY_SEC_CPU, 11828ccfb1eSJanosch Frank .handle = uvcb_csc.cpu_handle, 11928ccfb1eSJanosch Frank }; 12028ccfb1eSJanosch Frank 12128ccfb1eSJanosch Frank report_prefix_push("dcpu"); 12228ccfb1eSJanosch Frank 12328ccfb1eSJanosch Frank uvcb.header.len -= 8; 12428ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 12528ccfb1eSJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, 12628ccfb1eSJanosch Frank "hdr invalid length"); 12728ccfb1eSJanosch Frank uvcb.header.len += 8; 12828ccfb1eSJanosch Frank 129*5bf29e09SClaudio Imbrenda if (!machine_is_z15()) { 13028ccfb1eSJanosch Frank uvcb.handle += 1; 13128ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 13228ccfb1eSJanosch Frank report(rc == 1 && uvcb.header.rc == UVC_RC_INV_CHANDLE, "invalid handle"); 13328ccfb1eSJanosch Frank uvcb.handle -= 1; 134c73cc92dSJanosch Frank } 13528ccfb1eSJanosch Frank 13628ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 13728ccfb1eSJanosch Frank report(rc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "success"); 13828ccfb1eSJanosch Frank 13928ccfb1eSJanosch Frank report_prefix_pop(); 14028ccfb1eSJanosch Frank } 14128ccfb1eSJanosch Frank 14228ccfb1eSJanosch Frank static void test_cpu_create(void) 14328ccfb1eSJanosch Frank { 14428ccfb1eSJanosch Frank int rc; 14528ccfb1eSJanosch Frank unsigned long tmp; 14628ccfb1eSJanosch Frank 14728ccfb1eSJanosch Frank report_prefix_push("csc"); 14828ccfb1eSJanosch Frank uvcb_csc.header.len = sizeof(uvcb_csc); 14928ccfb1eSJanosch Frank uvcb_csc.header.cmd = UVC_CMD_CREATE_SEC_CPU; 15028ccfb1eSJanosch Frank uvcb_csc.guest_handle = uvcb_cgc.guest_handle; 15128ccfb1eSJanosch Frank uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len); 15228ccfb1eSJanosch Frank uvcb_csc.state_origin = (unsigned long)memalign(PAGE_SIZE, PAGE_SIZE); 15328ccfb1eSJanosch Frank 15428ccfb1eSJanosch Frank uvcb_csc.header.len -= 8; 15528ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 15628ccfb1eSJanosch Frank report(uvcb_csc.header.rc == UVC_RC_INV_LEN && rc == 1 && 15728ccfb1eSJanosch Frank !uvcb_csc.cpu_handle, "hdr invalid length"); 15828ccfb1eSJanosch Frank uvcb_csc.header.len += 8; 15928ccfb1eSJanosch Frank 16028ccfb1eSJanosch Frank uvcb_csc.guest_handle += 1; 16128ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 16228ccfb1eSJanosch Frank report(uvcb_csc.header.rc == UVC_RC_INV_GHANDLE && rc == 1, 16328ccfb1eSJanosch Frank "invalid guest handle"); 16428ccfb1eSJanosch Frank uvcb_csc.guest_handle -= 1; 16528ccfb1eSJanosch Frank 16628ccfb1eSJanosch Frank uvcb_csc.num = uvcb_qui.max_guest_cpus + 1; 16728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 16828ccfb1eSJanosch Frank report(uvcb_csc.header.rc == 0x103 && rc == 1, 16928ccfb1eSJanosch Frank "invalid cpu #"); 17028ccfb1eSJanosch Frank uvcb_csc.num = 0; 17128ccfb1eSJanosch Frank 17228ccfb1eSJanosch Frank tmp = uvcb_csc.stor_origin; 17328ccfb1eSJanosch Frank uvcb_csc.stor_origin = get_max_ram_size() + PAGE_SIZE; 17428ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 17528ccfb1eSJanosch Frank report(uvcb_csc.header.rc == 0x105 && rc == 1, 17628ccfb1eSJanosch Frank "cpu stor inaccessible"); 17728ccfb1eSJanosch Frank uvcb_csc.stor_origin = tmp; 17828ccfb1eSJanosch Frank 17928ccfb1eSJanosch Frank tmp = uvcb_csc.stor_origin; 18028ccfb1eSJanosch Frank uvcb_csc.stor_origin = 0; 18128ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 18228ccfb1eSJanosch Frank report(uvcb_csc.header.rc == 0x106 && rc == 1, 18328ccfb1eSJanosch Frank "cpu stor in lowcore"); 18428ccfb1eSJanosch Frank uvcb_csc.stor_origin = tmp; 18528ccfb1eSJanosch Frank 18628ccfb1eSJanosch Frank tmp = uvcb_csc.state_origin; 18728ccfb1eSJanosch Frank uvcb_csc.state_origin = get_max_ram_size() + PAGE_SIZE; 18828ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 18928ccfb1eSJanosch Frank report(uvcb_csc.header.rc == 0x107 && rc == 1, 19028ccfb1eSJanosch Frank "SIE SD inaccessible"); 19128ccfb1eSJanosch Frank uvcb_csc.state_origin = tmp; 19228ccfb1eSJanosch Frank 19328ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 19428ccfb1eSJanosch Frank report(rc == 0 && uvcb_csc.header.rc == UVC_RC_EXECUTED && 19528ccfb1eSJanosch Frank uvcb_csc.cpu_handle, "success"); 19628ccfb1eSJanosch Frank 19728ccfb1eSJanosch Frank tmp = uvcb_csc.stor_origin; 19828ccfb1eSJanosch Frank uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len); 19928ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_csc); 20028ccfb1eSJanosch Frank report(rc == 1 && uvcb_csc.header.rc == 0x104, "already defined"); 20128ccfb1eSJanosch Frank uvcb_csc.stor_origin = tmp; 20228ccfb1eSJanosch Frank report_prefix_pop(); 20328ccfb1eSJanosch Frank } 20428ccfb1eSJanosch Frank 20528ccfb1eSJanosch Frank static void test_config_create(void) 20628ccfb1eSJanosch Frank { 20728ccfb1eSJanosch Frank int rc; 20828ccfb1eSJanosch Frank unsigned long vsize, tmp; 20928ccfb1eSJanosch Frank static struct uv_cb_cgc uvcb; 21028ccfb1eSJanosch Frank 21128ccfb1eSJanosch Frank uvcb_cgc.header.cmd = UVC_CMD_CREATE_SEC_CONF; 21228ccfb1eSJanosch Frank uvcb_cgc.header.len = sizeof(uvcb_cgc); 21328ccfb1eSJanosch Frank report_prefix_push("cgc"); 21428ccfb1eSJanosch Frank 21528ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = 0; 21628ccfb1eSJanosch Frank uvcb_cgc.guest_stor_len = 42 * (1UL << 20); 21728ccfb1eSJanosch Frank vsize = uvcb_qui.conf_base_virt_stor_len + 21828ccfb1eSJanosch Frank ((uvcb_cgc.guest_stor_len / (1UL << 20)) * uvcb_qui.conf_virt_var_stor_len); 21928ccfb1eSJanosch Frank 22028ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len); 22128ccfb1eSJanosch Frank uvcb_cgc.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize); 22228ccfb1eSJanosch Frank uvcb_cgc.guest_asce = (uint64_t)memalign(PAGE_SIZE, 4 * PAGE_SIZE) | ASCE_DT_SEGMENT | REGION_TABLE_LENGTH | ASCE_P; 22328ccfb1eSJanosch Frank uvcb_cgc.guest_sca = (uint64_t)memalign(PAGE_SIZE * 4, PAGE_SIZE * 4); 22428ccfb1eSJanosch Frank 22528ccfb1eSJanosch Frank uvcb_cgc.header.len -= 8; 22628ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 22728ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == UVC_RC_INV_LEN && rc == 1 && 22828ccfb1eSJanosch Frank !uvcb_cgc.guest_handle, "hdr invalid length"); 22928ccfb1eSJanosch Frank uvcb_cgc.header.len += 8; 23028ccfb1eSJanosch Frank 23128ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = uvcb_qui.max_guest_stor_addr + (1UL << 20) * 2 + 1; 23228ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 23328ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x101 && rc == 1, 23428ccfb1eSJanosch Frank "MSO > max guest addr"); 23528ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = 0; 23628ccfb1eSJanosch Frank 23728ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = uvcb_qui.max_guest_stor_addr - (1UL << 20); 23828ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 23928ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x102 && rc == 1, 24028ccfb1eSJanosch Frank "MSO + MSL > max guest addr"); 24128ccfb1eSJanosch Frank uvcb_cgc.guest_stor_origin = 0; 24228ccfb1eSJanosch Frank 24328ccfb1eSJanosch Frank uvcb_cgc.guest_asce &= ~ASCE_P; 24428ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 24528ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x105 && rc == 1, 24628ccfb1eSJanosch Frank "ASCE private bit missing"); 24728ccfb1eSJanosch Frank uvcb_cgc.guest_asce |= ASCE_P; 24828ccfb1eSJanosch Frank 24928ccfb1eSJanosch Frank uvcb_cgc.guest_asce |= 0x20; 25028ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 25128ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x105 && rc == 1, 25228ccfb1eSJanosch Frank "ASCE bit 58 set"); 25328ccfb1eSJanosch Frank uvcb_cgc.guest_asce &= ~0x20; 25428ccfb1eSJanosch Frank 25528ccfb1eSJanosch Frank tmp = uvcb_cgc.conf_base_stor_origin; 25628ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = get_max_ram_size() + 8; 25728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 25828ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x108 && rc == 1, 25928ccfb1eSJanosch Frank "base storage origin > available memory"); 26028ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = tmp; 26128ccfb1eSJanosch Frank 26228ccfb1eSJanosch Frank tmp = uvcb_cgc.conf_base_stor_origin; 26328ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = 0x1000; 26428ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 26528ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x109 && rc == 1, 26628ccfb1eSJanosch Frank "base storage origin contains lowcore"); 26728ccfb1eSJanosch Frank uvcb_cgc.conf_base_stor_origin = tmp; 26828ccfb1eSJanosch Frank 26928ccfb1eSJanosch Frank if (smp_query_num_cpus() == 1) { 27028ccfb1eSJanosch Frank sigp_retry(1, SIGP_SET_PREFIX, 27128ccfb1eSJanosch Frank uvcb_cgc.conf_var_stor_origin + PAGE_SIZE, NULL); 27228ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 27328ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x10e && rc == 1 && 27428ccfb1eSJanosch Frank !uvcb_cgc.guest_handle, "variable storage area contains lowcore"); 27528ccfb1eSJanosch Frank sigp_retry(1, SIGP_SET_PREFIX, 0x0, NULL); 27628ccfb1eSJanosch Frank } 27728ccfb1eSJanosch Frank 27828ccfb1eSJanosch Frank tmp = uvcb_cgc.guest_sca; 27928ccfb1eSJanosch Frank uvcb_cgc.guest_sca = 0; 28028ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 28128ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x10c && rc == 1, 28228ccfb1eSJanosch Frank "sca == 0"); 28328ccfb1eSJanosch Frank uvcb_cgc.guest_sca = tmp; 28428ccfb1eSJanosch Frank 28528ccfb1eSJanosch Frank tmp = uvcb_cgc.guest_sca; 28628ccfb1eSJanosch Frank uvcb_cgc.guest_sca = get_max_ram_size() + + PAGE_SIZE * 4; 28728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 28828ccfb1eSJanosch Frank report(uvcb_cgc.header.rc == 0x10d && rc == 1, 28928ccfb1eSJanosch Frank "sca inaccessible"); 29028ccfb1eSJanosch Frank uvcb_cgc.guest_sca = tmp; 29128ccfb1eSJanosch Frank 29228ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 29328ccfb1eSJanosch Frank report(rc == 0 && uvcb_cgc.header.rc == UVC_RC_EXECUTED, "successful"); 29428ccfb1eSJanosch Frank 29528ccfb1eSJanosch Frank uvcb_cgc.header.rc = 0; 29628ccfb1eSJanosch Frank uvcb_cgc.header.rrc = 0; 29728ccfb1eSJanosch Frank tmp = uvcb_cgc.guest_handle; 29828ccfb1eSJanosch Frank uvcb_cgc.guest_handle = 0; 29928ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_cgc); 30028ccfb1eSJanosch Frank report(uvcb_cgc.header.rc >= 0x100 && rc == 1, "reuse uvcb"); 30128ccfb1eSJanosch Frank uvcb_cgc.guest_handle = tmp; 30228ccfb1eSJanosch Frank 30328ccfb1eSJanosch Frank /* Copy over most data from uvcb_cgc, so we have the ASCE that was used. */ 30428ccfb1eSJanosch Frank memcpy(&uvcb, &uvcb_cgc, sizeof(uvcb)); 30528ccfb1eSJanosch Frank 30628ccfb1eSJanosch Frank /* Reset the header and handle */ 30728ccfb1eSJanosch Frank uvcb.header.rc = 0; 30828ccfb1eSJanosch Frank uvcb.header.rrc = 0; 30928ccfb1eSJanosch Frank uvcb.guest_handle = 0; 31028ccfb1eSJanosch Frank 31128ccfb1eSJanosch Frank /* Use new storage areas. */ 31228ccfb1eSJanosch Frank uvcb.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len); 31328ccfb1eSJanosch Frank uvcb.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize); 31428ccfb1eSJanosch Frank 31528ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb); 31628ccfb1eSJanosch Frank report(uvcb.header.rc >= 0x104 && rc == 1 && !uvcb.guest_handle, 31728ccfb1eSJanosch Frank "reuse ASCE"); 31828ccfb1eSJanosch Frank free((void *)uvcb.conf_base_stor_origin); 31928ccfb1eSJanosch Frank free((void *)uvcb.conf_var_stor_origin); 32028ccfb1eSJanosch Frank 32128ccfb1eSJanosch Frank /* Missing: 106, 10a, a0b */ 32228ccfb1eSJanosch Frank report_prefix_pop(); 32328ccfb1eSJanosch Frank } 32428ccfb1eSJanosch Frank 32528ccfb1eSJanosch Frank static void test_init(void) 32628ccfb1eSJanosch Frank { 32728ccfb1eSJanosch Frank int rc; 32828ccfb1eSJanosch Frank uint64_t mem; 32928ccfb1eSJanosch Frank struct psw psw; 33028ccfb1eSJanosch Frank 33128ccfb1eSJanosch Frank /* Donated storage needs to be over 2GB */ 33228ccfb1eSJanosch Frank mem = (uint64_t)memalign(1UL << 31, uvcb_qui.uv_base_stor_len); 33328ccfb1eSJanosch Frank 33428ccfb1eSJanosch Frank uvcb_init.header.len = sizeof(uvcb_init); 33528ccfb1eSJanosch Frank uvcb_init.header.cmd = UVC_CMD_INIT_UV; 33628ccfb1eSJanosch Frank uvcb_init.stor_origin = mem; 33728ccfb1eSJanosch Frank uvcb_init.stor_len = uvcb_qui.uv_base_stor_len; 33828ccfb1eSJanosch Frank 33928ccfb1eSJanosch Frank report_prefix_push("init"); 34028ccfb1eSJanosch Frank uvcb_init.header.len -= 8; 34128ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 34228ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == UVC_RC_INV_LEN, 34328ccfb1eSJanosch Frank "hdr invalid length"); 34428ccfb1eSJanosch Frank uvcb_init.header.len += 8; 34528ccfb1eSJanosch Frank 34628ccfb1eSJanosch Frank uvcb_init.stor_len -= 8; 34728ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 34828ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x103, 34928ccfb1eSJanosch Frank "storage invalid length"); 35028ccfb1eSJanosch Frank uvcb_init.stor_len += 8; 35128ccfb1eSJanosch Frank 35228ccfb1eSJanosch Frank uvcb_init.stor_origin = get_max_ram_size() + 8; 35328ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 35428ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x104, 35528ccfb1eSJanosch Frank "storage origin invalid"); 35628ccfb1eSJanosch Frank uvcb_init.stor_origin = mem; 35728ccfb1eSJanosch Frank 35828ccfb1eSJanosch Frank uvcb_init.stor_origin = get_max_ram_size() - 8; 35928ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 36028ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x105, 36128ccfb1eSJanosch Frank "storage + length invalid"); 36228ccfb1eSJanosch Frank uvcb_init.stor_origin = mem; 36328ccfb1eSJanosch Frank 36428ccfb1eSJanosch Frank uvcb_init.stor_origin = 1UL << 30; 36528ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 36628ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x108, 36728ccfb1eSJanosch Frank "storage below 2GB"); 36828ccfb1eSJanosch Frank uvcb_init.stor_origin = mem; 36928ccfb1eSJanosch Frank 37028ccfb1eSJanosch Frank psw.mask = extract_psw_mask(); 37128ccfb1eSJanosch Frank psw.addr = (unsigned long)cpu_loop; 37228ccfb1eSJanosch Frank smp_cpu_setup(1, psw); 37328ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 37428ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x102, 37528ccfb1eSJanosch Frank "too many running cpus"); 37628ccfb1eSJanosch Frank smp_cpu_stop(1); 37728ccfb1eSJanosch Frank 37828ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 37928ccfb1eSJanosch Frank report(rc == 0 && uvcb_init.header.rc == UVC_RC_EXECUTED, "successful"); 38028ccfb1eSJanosch Frank 38128ccfb1eSJanosch Frank mem = (uint64_t)memalign(1UL << 31, uvcb_qui.uv_base_stor_len); 38228ccfb1eSJanosch Frank rc = uv_call(0, (uint64_t)&uvcb_init); 38328ccfb1eSJanosch Frank report(rc == 1 && uvcb_init.header.rc == 0x101, "double init"); 38428ccfb1eSJanosch Frank free((void *)mem); 38528ccfb1eSJanosch Frank 38628ccfb1eSJanosch Frank report_prefix_pop(); 38728ccfb1eSJanosch Frank } 38828ccfb1eSJanosch Frank 38928ccfb1eSJanosch Frank static void test_query(void) 39028ccfb1eSJanosch Frank { 391cde26b62SJanosch Frank int i = 0, cc; 39228ccfb1eSJanosch Frank 39328ccfb1eSJanosch Frank uvcb_qui.header.cmd = UVC_CMD_QUI; 39428ccfb1eSJanosch Frank uvcb_qui.header.len = sizeof(uvcb_qui); 39528ccfb1eSJanosch Frank 39628ccfb1eSJanosch Frank report_prefix_push("query"); 39728ccfb1eSJanosch Frank uvcb_qui.header.len = 0xa0; 39828ccfb1eSJanosch Frank uv_call(0, (uint64_t)&uvcb_qui); 39928ccfb1eSJanosch Frank report(uvcb_qui.header.rc == UVC_RC_INV_LEN, "length"); 40028ccfb1eSJanosch Frank 40128ccfb1eSJanosch Frank uvcb_qui.header.len = 0xa8; 40228ccfb1eSJanosch Frank uv_call(0, (uint64_t)&uvcb_qui); 40328ccfb1eSJanosch Frank report(uvcb_qui.header.rc == 0x100, "insf length"); 40428ccfb1eSJanosch Frank 40528ccfb1eSJanosch Frank uvcb_qui.header.len = sizeof(uvcb_qui); 406cde26b62SJanosch Frank cc = uv_call(0, (uint64_t)&uvcb_qui); 407cde26b62SJanosch Frank report((!cc && uvcb_qui.header.rc == UVC_RC_EXECUTED) || 408cde26b62SJanosch Frank (cc == 1 && uvcb_qui.header.rc == 0x100), 409cde26b62SJanosch Frank "successful query"); 41028ccfb1eSJanosch Frank 41128ccfb1eSJanosch Frank for (i = 0; cmds[i].name; i++) 41228ccfb1eSJanosch Frank report(uv_query_test_call(cmds[i].call_bit), "%s", cmds[i].name); 41328ccfb1eSJanosch Frank 41428ccfb1eSJanosch Frank report_prefix_pop(); 41528ccfb1eSJanosch Frank } 41628ccfb1eSJanosch Frank 41728ccfb1eSJanosch Frank static struct cmd_list invalid_cmds[] = { 41828ccfb1eSJanosch Frank { "bogus", 0x4242, sizeof(struct uv_cb_header), -1}, 41928ccfb1eSJanosch Frank { "share", UVC_CMD_SET_SHARED_ACCESS, sizeof(struct uv_cb_share), BIT_UVC_CMD_SET_SHARED_ACCESS }, 42028ccfb1eSJanosch Frank { "unshare", UVC_CMD_REMOVE_SHARED_ACCESS, sizeof(struct uv_cb_share), BIT_UVC_CMD_REMOVE_SHARED_ACCESS }, 42128ccfb1eSJanosch Frank { NULL, 0, 0 }, 42228ccfb1eSJanosch Frank }; 42328ccfb1eSJanosch Frank 42428ccfb1eSJanosch Frank static void test_invalid(void) 42528ccfb1eSJanosch Frank { 42628ccfb1eSJanosch Frank struct uv_cb_header hdr = {}; 42728ccfb1eSJanosch Frank int i, cc; 42828ccfb1eSJanosch Frank 42928ccfb1eSJanosch Frank report_prefix_push("invalid"); 43028ccfb1eSJanosch Frank for (i = 0; invalid_cmds[i].name; i++) { 43128ccfb1eSJanosch Frank hdr.cmd = invalid_cmds[i].cmd; 43228ccfb1eSJanosch Frank hdr.len = invalid_cmds[i].len; 43328ccfb1eSJanosch Frank cc = uv_call(0, (uint64_t)&hdr); 43428ccfb1eSJanosch Frank report(cc == 1 && hdr.rc == UVC_RC_INV_CMD && 43528ccfb1eSJanosch Frank (invalid_cmds[i].call_bit == -1 || !uv_query_test_call(invalid_cmds[i].call_bit)), 43628ccfb1eSJanosch Frank "%s", invalid_cmds[i].name); 43728ccfb1eSJanosch Frank } 43828ccfb1eSJanosch Frank report_prefix_pop(); 43928ccfb1eSJanosch Frank } 44028ccfb1eSJanosch Frank 44128ccfb1eSJanosch Frank static void test_clear(void) 44228ccfb1eSJanosch Frank { 44328ccfb1eSJanosch Frank uint64_t *tmp = (void *)uvcb_init.stor_origin; 44428ccfb1eSJanosch Frank 44528ccfb1eSJanosch Frank diag308_load_reset(1); 44628ccfb1eSJanosch Frank sclp_console_setup(); 44728ccfb1eSJanosch Frank report(!*tmp, "memory cleared after reset 1"); 44828ccfb1eSJanosch Frank } 44928ccfb1eSJanosch Frank 45028ccfb1eSJanosch Frank static void setup_vmem(void) 45128ccfb1eSJanosch Frank { 452136d73e3SJanosch Frank uint64_t asce; 45328ccfb1eSJanosch Frank 4540a5b31d2SSean Christopherson setup_mmu(get_max_ram_size(), NULL); 455136d73e3SJanosch Frank /* 456136d73e3SJanosch Frank * setup_mmu() will enable DAT and set the primary address 457136d73e3SJanosch Frank * space but we need to have a valid home space since UV calls 458136d73e3SJanosch Frank * take home space virtual addresses. 459136d73e3SJanosch Frank * 460136d73e3SJanosch Frank * Hence we just copy the primary asce into the home space. 461136d73e3SJanosch Frank */ 46228ccfb1eSJanosch Frank asce = stctg(1); 46328ccfb1eSJanosch Frank lctlg(13, asce); 46428ccfb1eSJanosch Frank } 46528ccfb1eSJanosch Frank 46628ccfb1eSJanosch Frank int main(void) 46728ccfb1eSJanosch Frank { 46828ccfb1eSJanosch Frank bool has_uvc = test_facility(158); 46928ccfb1eSJanosch Frank 47028ccfb1eSJanosch Frank report_prefix_push("uvc"); 47128ccfb1eSJanosch Frank if (!has_uvc) { 47228ccfb1eSJanosch Frank report_skip("Ultravisor call facility is not available"); 47328ccfb1eSJanosch Frank goto done; 47428ccfb1eSJanosch Frank } 47528ccfb1eSJanosch Frank 47628ccfb1eSJanosch Frank test_priv(); 47728ccfb1eSJanosch Frank test_invalid(); 47828ccfb1eSJanosch Frank test_query(); 47928ccfb1eSJanosch Frank test_init(); 48028ccfb1eSJanosch Frank 48128ccfb1eSJanosch Frank setup_vmem(); 48228ccfb1eSJanosch Frank test_config_create(); 48328ccfb1eSJanosch Frank test_cpu_create(); 48428ccfb1eSJanosch Frank test_cpu_destroy(); 48528ccfb1eSJanosch Frank test_config_destroy(); 48628ccfb1eSJanosch Frank test_clear(); 48728ccfb1eSJanosch Frank 48828ccfb1eSJanosch Frank done: 48928ccfb1eSJanosch Frank return report_summary(); 49028ccfb1eSJanosch Frank } 491