1435c758dSShalini Chellathurai Saroja /* 2435c758dSShalini Chellathurai Saroja * SPDX-License-Identifier: GPL-2.0-or-later 3435c758dSShalini Chellathurai Saroja * 4435c758dSShalini Chellathurai Saroja * SCLP event type 11 - Control-Program Identification (CPI): 5435c758dSShalini Chellathurai Saroja * CPI is used to send program identifiers from the guest to the 6435c758dSShalini Chellathurai Saroja * Service-Call Logical Processor (SCLP). It is not sent by the SCLP. 7435c758dSShalini Chellathurai Saroja * 8435c758dSShalini Chellathurai Saroja * Control-program identifiers provide data about the guest operating 9435c758dSShalini Chellathurai Saroja * system. The control-program identifiers are: system type, system name, 10435c758dSShalini Chellathurai Saroja * system level and sysplex name. 11435c758dSShalini Chellathurai Saroja * 12435c758dSShalini Chellathurai Saroja * In Linux, all the control-program identifiers are user configurable. The 13435c758dSShalini Chellathurai Saroja * system type, system name, and sysplex name use EBCDIC characters from 14435c758dSShalini Chellathurai Saroja * this set: capital A-Z, 0-9, $, @, #, and blank. In Linux, the system 15435c758dSShalini Chellathurai Saroja * type, system name and sysplex name are arbitrary free-form texts. 16435c758dSShalini Chellathurai Saroja * 17435c758dSShalini Chellathurai Saroja * In Linux, the 8-byte hexadecimal system-level has the format 18435c758dSShalini Chellathurai Saroja * 0x<a><b><cc><dd><eeee><ff><gg><hh>, where: 19435c758dSShalini Chellathurai Saroja * <a>: is a 4-bit digit, its most significant bit indicates hypervisor use 20435c758dSShalini Chellathurai Saroja * <b>: is one digit that represents Linux distributions as follows 21435c758dSShalini Chellathurai Saroja * 0: generic Linux 22435c758dSShalini Chellathurai Saroja * 1: Red Hat Enterprise Linux 23435c758dSShalini Chellathurai Saroja * 2: SUSE Linux Enterprise Server 24435c758dSShalini Chellathurai Saroja * 3: Canonical Ubuntu 25435c758dSShalini Chellathurai Saroja * 4: Fedora 26435c758dSShalini Chellathurai Saroja * 5: openSUSE Leap 27435c758dSShalini Chellathurai Saroja * 6: Debian GNU/Linux 28435c758dSShalini Chellathurai Saroja * 7: Red Hat Enterprise Linux CoreOS 29435c758dSShalini Chellathurai Saroja * <cc>: are two digits for a distribution-specific encoding of the major 30435c758dSShalini Chellathurai Saroja * version of the distribution 31435c758dSShalini Chellathurai Saroja * <dd>: are two digits for a distribution-specific encoding of the minor 32435c758dSShalini Chellathurai Saroja * version of the distribution 33435c758dSShalini Chellathurai Saroja * <eeee>: are four digits for the patch level of the distribution 34435c758dSShalini Chellathurai Saroja * <ff>: are two digits for the major version of the kernel 35435c758dSShalini Chellathurai Saroja * <gg>: are two digits for the minor version of the kernel 36435c758dSShalini Chellathurai Saroja * <hh>: are two digits for the stable version of the kernel 37435c758dSShalini Chellathurai Saroja * (e.g. 74872343805430528, when converted to hex is 0x010a000000060b00). On 38435c758dSShalini Chellathurai Saroja * machines prior to z16, some of the values are not available to display. 39435c758dSShalini Chellathurai Saroja * 40435c758dSShalini Chellathurai Saroja * Sysplex refers to a cluster of logical partitions that communicates and 41435c758dSShalini Chellathurai Saroja * co-operates with each other. 42435c758dSShalini Chellathurai Saroja * 43435c758dSShalini Chellathurai Saroja * The CPI feature is supported since 10.1. 44435c758dSShalini Chellathurai Saroja * 45435c758dSShalini Chellathurai Saroja * Copyright IBM, Corp. 2024 46435c758dSShalini Chellathurai Saroja * 47435c758dSShalini Chellathurai Saroja * Authors: 48435c758dSShalini Chellathurai Saroja * Shalini Chellathurai Saroja <shalini@linux.ibm.com> 49435c758dSShalini Chellathurai Saroja * 50435c758dSShalini Chellathurai Saroja */ 51435c758dSShalini Chellathurai Saroja 52435c758dSShalini Chellathurai Saroja #include "qemu/osdep.h" 53f345978fSShalini Chellathurai Saroja #include "qemu/timer.h" 54435c758dSShalini Chellathurai Saroja #include "hw/s390x/event-facility.h" 55f345978fSShalini Chellathurai Saroja #include "hw/s390x/ebcdic.h" 56f345978fSShalini Chellathurai Saroja #include "qapi/qapi-visit-machine.h" 57*c61927baSShalini Chellathurai Saroja #include "migration/vmstate.h" 58435c758dSShalini Chellathurai Saroja 59435c758dSShalini Chellathurai Saroja typedef struct Data { 60435c758dSShalini Chellathurai Saroja uint8_t id_format; 61435c758dSShalini Chellathurai Saroja uint8_t reserved0; 62435c758dSShalini Chellathurai Saroja uint8_t system_type[8]; 63435c758dSShalini Chellathurai Saroja uint64_t reserved1; 64435c758dSShalini Chellathurai Saroja uint8_t system_name[8]; 65435c758dSShalini Chellathurai Saroja uint64_t reserved2; 66435c758dSShalini Chellathurai Saroja uint64_t system_level; 67435c758dSShalini Chellathurai Saroja uint64_t reserved3; 68435c758dSShalini Chellathurai Saroja uint8_t sysplex_name[8]; 69435c758dSShalini Chellathurai Saroja uint8_t reserved4[16]; 70435c758dSShalini Chellathurai Saroja } QEMU_PACKED Data; 71435c758dSShalini Chellathurai Saroja 72435c758dSShalini Chellathurai Saroja typedef struct ControlProgramIdMsg { 73435c758dSShalini Chellathurai Saroja EventBufferHeader ebh; 74435c758dSShalini Chellathurai Saroja Data data; 75435c758dSShalini Chellathurai Saroja } QEMU_PACKED ControlProgramIdMsg; 76435c758dSShalini Chellathurai Saroja 77435c758dSShalini Chellathurai Saroja static bool can_handle_event(uint8_t type) 78435c758dSShalini Chellathurai Saroja { 79435c758dSShalini Chellathurai Saroja return type == SCLP_EVENT_CTRL_PGM_ID; 80435c758dSShalini Chellathurai Saroja } 81435c758dSShalini Chellathurai Saroja 82435c758dSShalini Chellathurai Saroja static sccb_mask_t send_mask(void) 83435c758dSShalini Chellathurai Saroja { 84435c758dSShalini Chellathurai Saroja return 0; 85435c758dSShalini Chellathurai Saroja } 86435c758dSShalini Chellathurai Saroja 87435c758dSShalini Chellathurai Saroja /* Enable SCLP to accept buffers of event type CPI from the control-program. */ 88435c758dSShalini Chellathurai Saroja static sccb_mask_t receive_mask(void) 89435c758dSShalini Chellathurai Saroja { 90435c758dSShalini Chellathurai Saroja return SCLP_EVENT_MASK_CTRL_PGM_ID; 91435c758dSShalini Chellathurai Saroja } 92435c758dSShalini Chellathurai Saroja 93435c758dSShalini Chellathurai Saroja static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr) 94435c758dSShalini Chellathurai Saroja { 95435c758dSShalini Chellathurai Saroja ControlProgramIdMsg *cpim = container_of(evt_buf_hdr, ControlProgramIdMsg, 96435c758dSShalini Chellathurai Saroja ebh); 97f345978fSShalini Chellathurai Saroja SCLPEventCPI *e = SCLP_EVENT_CPI(event); 98f345978fSShalini Chellathurai Saroja 99f345978fSShalini Chellathurai Saroja ascii_put(e->system_type, (char *)cpim->data.system_type, 100f345978fSShalini Chellathurai Saroja sizeof(cpim->data.system_type)); 101f345978fSShalini Chellathurai Saroja ascii_put(e->system_name, (char *)cpim->data.system_name, 102f345978fSShalini Chellathurai Saroja sizeof(cpim->data.system_name)); 103f345978fSShalini Chellathurai Saroja ascii_put(e->sysplex_name, (char *)cpim->data.sysplex_name, 104f345978fSShalini Chellathurai Saroja sizeof(cpim->data.sysplex_name)); 105f345978fSShalini Chellathurai Saroja e->system_level = ldq_be_p(&cpim->data.system_level); 106f345978fSShalini Chellathurai Saroja e->timestamp = qemu_clock_get_ns(QEMU_CLOCK_HOST); 107435c758dSShalini Chellathurai Saroja 108435c758dSShalini Chellathurai Saroja cpim->ebh.flags = SCLP_EVENT_BUFFER_ACCEPTED; 109435c758dSShalini Chellathurai Saroja return SCLP_RC_NORMAL_COMPLETION; 110435c758dSShalini Chellathurai Saroja } 111435c758dSShalini Chellathurai Saroja 112f345978fSShalini Chellathurai Saroja static char *get_system_type(Object *obj, Error **errp) 113f345978fSShalini Chellathurai Saroja { 114f345978fSShalini Chellathurai Saroja SCLPEventCPI *e = SCLP_EVENT_CPI(obj); 115f345978fSShalini Chellathurai Saroja 116f345978fSShalini Chellathurai Saroja return g_strndup((char *) e->system_type, sizeof(e->system_type)); 117f345978fSShalini Chellathurai Saroja } 118f345978fSShalini Chellathurai Saroja 119f345978fSShalini Chellathurai Saroja static char *get_system_name(Object *obj, Error **errp) 120f345978fSShalini Chellathurai Saroja { 121f345978fSShalini Chellathurai Saroja SCLPEventCPI *e = SCLP_EVENT_CPI(obj); 122f345978fSShalini Chellathurai Saroja 123f345978fSShalini Chellathurai Saroja return g_strndup((char *) e->system_name, sizeof(e->system_name)); 124f345978fSShalini Chellathurai Saroja } 125f345978fSShalini Chellathurai Saroja 126f345978fSShalini Chellathurai Saroja static char *get_sysplex_name(Object *obj, Error **errp) 127f345978fSShalini Chellathurai Saroja { 128f345978fSShalini Chellathurai Saroja SCLPEventCPI *e = SCLP_EVENT_CPI(obj); 129f345978fSShalini Chellathurai Saroja 130f345978fSShalini Chellathurai Saroja return g_strndup((char *) e->sysplex_name, sizeof(e->sysplex_name)); 131f345978fSShalini Chellathurai Saroja } 132f345978fSShalini Chellathurai Saroja 133f345978fSShalini Chellathurai Saroja static void get_system_level(Object *obj, Visitor *v, const char *name, 134f345978fSShalini Chellathurai Saroja void *opaque, Error **errp) 135f345978fSShalini Chellathurai Saroja { 136f345978fSShalini Chellathurai Saroja SCLPEventCPI *e = SCLP_EVENT_CPI(obj); 137f345978fSShalini Chellathurai Saroja 138f345978fSShalini Chellathurai Saroja visit_type_uint64(v, name, &e->system_level, errp); 139f345978fSShalini Chellathurai Saroja } 140f345978fSShalini Chellathurai Saroja 141f345978fSShalini Chellathurai Saroja static void get_timestamp(Object *obj, Visitor *v, const char *name, 142f345978fSShalini Chellathurai Saroja void *opaque, Error **errp) 143f345978fSShalini Chellathurai Saroja { 144f345978fSShalini Chellathurai Saroja SCLPEventCPI *e = SCLP_EVENT_CPI(obj); 145f345978fSShalini Chellathurai Saroja 146f345978fSShalini Chellathurai Saroja visit_type_uint64(v, name, &e->timestamp, errp); 147f345978fSShalini Chellathurai Saroja } 148f345978fSShalini Chellathurai Saroja 149*c61927baSShalini Chellathurai Saroja static const VMStateDescription vmstate_sclpcpi = { 150*c61927baSShalini Chellathurai Saroja .name = "s390_control_program_id", 151*c61927baSShalini Chellathurai Saroja .version_id = 0, 152*c61927baSShalini Chellathurai Saroja .fields = (const VMStateField[]) { 153*c61927baSShalini Chellathurai Saroja VMSTATE_UINT8_ARRAY(system_type, SCLPEventCPI, 8), 154*c61927baSShalini Chellathurai Saroja VMSTATE_UINT8_ARRAY(system_name, SCLPEventCPI, 8), 155*c61927baSShalini Chellathurai Saroja VMSTATE_UINT64(system_level, SCLPEventCPI), 156*c61927baSShalini Chellathurai Saroja VMSTATE_UINT8_ARRAY(sysplex_name, SCLPEventCPI, 8), 157*c61927baSShalini Chellathurai Saroja VMSTATE_UINT64(timestamp, SCLPEventCPI), 158*c61927baSShalini Chellathurai Saroja VMSTATE_END_OF_LIST() 159*c61927baSShalini Chellathurai Saroja } 160*c61927baSShalini Chellathurai Saroja }; 161*c61927baSShalini Chellathurai Saroja 162435c758dSShalini Chellathurai Saroja static void cpi_class_init(ObjectClass *klass, const void *data) 163435c758dSShalini Chellathurai Saroja { 164435c758dSShalini Chellathurai Saroja DeviceClass *dc = DEVICE_CLASS(klass); 165435c758dSShalini Chellathurai Saroja SCLPEventClass *k = SCLP_EVENT_CLASS(klass); 166435c758dSShalini Chellathurai Saroja 167435c758dSShalini Chellathurai Saroja dc->user_creatable = false; 168*c61927baSShalini Chellathurai Saroja dc->vmsd = &vmstate_sclpcpi; 169435c758dSShalini Chellathurai Saroja 170435c758dSShalini Chellathurai Saroja k->can_handle_event = can_handle_event; 171435c758dSShalini Chellathurai Saroja k->get_send_mask = send_mask; 172435c758dSShalini Chellathurai Saroja k->get_receive_mask = receive_mask; 173435c758dSShalini Chellathurai Saroja k->write_event_data = write_event_data; 174f345978fSShalini Chellathurai Saroja 175f345978fSShalini Chellathurai Saroja object_class_property_add_str(klass, "system_type", get_system_type, NULL); 176f345978fSShalini Chellathurai Saroja object_class_property_set_description(klass, "system_type", 177f345978fSShalini Chellathurai Saroja "operating system e.g. \"LINUX \""); 178f345978fSShalini Chellathurai Saroja 179f345978fSShalini Chellathurai Saroja object_class_property_add_str(klass, "system_name", get_system_name, NULL); 180f345978fSShalini Chellathurai Saroja object_class_property_set_description(klass, "system_name", 181f345978fSShalini Chellathurai Saroja "user configurable name of the VM e.g. \"TESTVM \""); 182f345978fSShalini Chellathurai Saroja 183f345978fSShalini Chellathurai Saroja object_class_property_add_str(klass, "sysplex_name", get_sysplex_name, 184f345978fSShalini Chellathurai Saroja NULL); 185f345978fSShalini Chellathurai Saroja object_class_property_set_description(klass, "sysplex_name", 186f345978fSShalini Chellathurai Saroja "name of the cluster which the VM belongs to, if any" 187f345978fSShalini Chellathurai Saroja " e.g. \"PLEX \""); 188f345978fSShalini Chellathurai Saroja 189f345978fSShalini Chellathurai Saroja object_class_property_add(klass, "system_level", "uint64", get_system_level, 190f345978fSShalini Chellathurai Saroja NULL, NULL, NULL); 191f345978fSShalini Chellathurai Saroja object_class_property_set_description(klass, "system_level", 192f345978fSShalini Chellathurai Saroja "distribution and kernel version in Linux e.g. 74872343805430528"); 193f345978fSShalini Chellathurai Saroja 194f345978fSShalini Chellathurai Saroja object_class_property_add(klass, "timestamp", "uint64", get_timestamp, 195f345978fSShalini Chellathurai Saroja NULL, NULL, NULL); 196f345978fSShalini Chellathurai Saroja object_class_property_set_description(klass, "timestamp", 197f345978fSShalini Chellathurai Saroja "latest update of CPI data in nanoseconds since the UNIX EPOCH"); 198435c758dSShalini Chellathurai Saroja } 199435c758dSShalini Chellathurai Saroja 200435c758dSShalini Chellathurai Saroja static const TypeInfo sclp_cpi_info = { 201435c758dSShalini Chellathurai Saroja .name = TYPE_SCLP_EVENT_CPI, 202435c758dSShalini Chellathurai Saroja .parent = TYPE_SCLP_EVENT, 203435c758dSShalini Chellathurai Saroja .instance_size = sizeof(SCLPEventCPI), 204435c758dSShalini Chellathurai Saroja .class_init = cpi_class_init, 205435c758dSShalini Chellathurai Saroja }; 206435c758dSShalini Chellathurai Saroja 207435c758dSShalini Chellathurai Saroja static void sclp_cpi_register_types(void) 208435c758dSShalini Chellathurai Saroja { 209435c758dSShalini Chellathurai Saroja type_register_static(&sclp_cpi_info); 210435c758dSShalini Chellathurai Saroja } 211435c758dSShalini Chellathurai Saroja 212435c758dSShalini Chellathurai Saroja type_init(sclp_cpi_register_types) 213