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
can_handle_event(uint8_t type)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
send_mask(void)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. */
receive_mask(void)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
write_event_data(SCLPEvent * event,EventBufferHeader * evt_buf_hdr)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
get_system_type(Object * obj,Error ** errp)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
get_system_name(Object * obj,Error ** errp)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
get_sysplex_name(Object * obj,Error ** errp)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
get_system_level(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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
get_timestamp(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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
cpi_class_init(ObjectClass * klass,const void * data)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
sclp_cpi_register_types(void)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