xref: /openbmc/qemu/hw/s390x/sclpcpu.c (revision 3f2a357b95845ea0bf7463eff6661e43b97d1afc)
149204458SJason J. Herne /*
249204458SJason J. Herne  * SCLP event type
349204458SJason J. Herne  *    Signal CPU - Trigger SCLP interrupt for system CPU configure or
449204458SJason J. Herne  *    de-configure
549204458SJason J. Herne  *
649204458SJason J. Herne  * Copyright IBM, Corp. 2013
749204458SJason J. Herne  *
849204458SJason J. Herne  * Authors:
949204458SJason J. Herne  *  Thang Pham <thang.pham@us.ibm.com>
1049204458SJason J. Herne  *
1149204458SJason J. Herne  * This work is licensed under the terms of the GNU GPL, version 2 or (at your
1249204458SJason J. Herne  * option) any later version.  See the COPYING file in the top-level directory.
1349204458SJason J. Herne  *
1449204458SJason J. Herne  */
150b8fa32fSMarkus Armbruster 
169615495aSPeter Maydell #include "qemu/osdep.h"
1749204458SJason J. Herne #include "hw/s390x/sclp.h"
180b8fa32fSMarkus Armbruster #include "qemu/module.h"
1949204458SJason J. Herne #include "hw/s390x/event-facility.h"
2049204458SJason J. Herne #include "sysemu/cpus.h"
2149204458SJason J. Herne 
2249204458SJason J. Herne typedef struct ConfigMgtData {
2349204458SJason J. Herne     EventBufferHeader ebh;
2449204458SJason J. Herne     uint8_t reserved;
2549204458SJason J. Herne     uint8_t event_qualifier;
2649204458SJason J. Herne } QEMU_PACKED ConfigMgtData;
2749204458SJason J. Herne 
2849204458SJason J. Herne #define EVENT_QUAL_CPU_CHANGE  1
2949204458SJason J. Herne 
raise_irq_cpu_hotplug(void)3049204458SJason J. Herne void raise_irq_cpu_hotplug(void)
3149204458SJason J. Herne {
32073f57aeSDavid Hildenbrand     Object *obj = object_resolve_path_type("", TYPE_SCLP_CPU_HOTPLUG, NULL);
33073f57aeSDavid Hildenbrand 
34073f57aeSDavid Hildenbrand     SCLP_EVENT(obj)->event_pending = true;
35073f57aeSDavid Hildenbrand 
36073f57aeSDavid Hildenbrand     /* Trigger SCLP read operation */
37073f57aeSDavid Hildenbrand     sclp_service_interrupt(0);
3849204458SJason J. Herne }
3949204458SJason J. Herne 
send_mask(void)401ffed98fSClaudio Imbrenda static sccb_mask_t send_mask(void)
4149204458SJason J. Herne {
4249204458SJason J. Herne     return SCLP_EVENT_MASK_CONFIG_MGT_DATA;
4349204458SJason J. Herne }
4449204458SJason J. Herne 
receive_mask(void)451ffed98fSClaudio Imbrenda static sccb_mask_t receive_mask(void)
4649204458SJason J. Herne {
4749204458SJason J. Herne     return 0;
4849204458SJason J. Herne }
4949204458SJason J. Herne 
read_event_data(SCLPEvent * event,EventBufferHeader * evt_buf_hdr,int * slen)5049204458SJason J. Herne static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
5149204458SJason J. Herne                            int *slen)
5249204458SJason J. Herne {
5349204458SJason J. Herne     ConfigMgtData *cdata = (ConfigMgtData *) evt_buf_hdr;
5449204458SJason J. Herne     if (*slen < sizeof(ConfigMgtData)) {
5549204458SJason J. Herne         return 0;
5649204458SJason J. Herne     }
5749204458SJason J. Herne 
5849204458SJason J. Herne     /* Event is no longer pending */
5949204458SJason J. Herne     if (!event->event_pending) {
6049204458SJason J. Herne         return 0;
6149204458SJason J. Herne     }
6249204458SJason J. Herne     event->event_pending = false;
6349204458SJason J. Herne 
6449204458SJason J. Herne     /* Event header data */
6549204458SJason J. Herne     cdata->ebh.length = cpu_to_be16(sizeof(ConfigMgtData));
6649204458SJason J. Herne     cdata->ebh.type = SCLP_EVENT_CONFIG_MGT_DATA;
6749204458SJason J. Herne     cdata->ebh.flags |= SCLP_EVENT_BUFFER_ACCEPTED;
6849204458SJason J. Herne 
6949204458SJason J. Herne     /* Trigger a rescan of CPUs by setting event qualifier */
7049204458SJason J. Herne     cdata->event_qualifier = EVENT_QUAL_CPU_CHANGE;
7149204458SJason J. Herne     *slen -= sizeof(ConfigMgtData);
7249204458SJason J. Herne 
7349204458SJason J. Herne     return 1;
7449204458SJason J. Herne }
7549204458SJason J. Herne 
sclp_cpu_class_init(ObjectClass * oc,void * data)76*83f1ab12SPhilippe Mathieu-Daudé static void sclp_cpu_class_init(ObjectClass *oc, void *data)
7749204458SJason J. Herne {
7849204458SJason J. Herne     SCLPEventClass *k = SCLP_EVENT_CLASS(oc);
79183f6b8dSCornelia Huck     DeviceClass *dc = DEVICE_CLASS(oc);
8049204458SJason J. Herne 
8149204458SJason J. Herne     k->get_send_mask = send_mask;
8249204458SJason J. Herne     k->get_receive_mask = receive_mask;
8349204458SJason J. Herne     k->read_event_data = read_event_data;
84183f6b8dSCornelia Huck     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
857aa4d85dSCornelia Huck     /*
867aa4d85dSCornelia Huck      * Reason: raise_irq_cpu_hotplug() depends on an unique
877aa4d85dSCornelia Huck      * TYPE_SCLP_CPU_HOTPLUG device, which is already created
887aa4d85dSCornelia Huck      * by the sclp event facility
897aa4d85dSCornelia Huck      */
907aa4d85dSCornelia Huck     dc->user_creatable = false;
9149204458SJason J. Herne }
9249204458SJason J. Herne 
9349204458SJason J. Herne static const TypeInfo sclp_cpu_info = {
9435925a7aSDavid Hildenbrand     .name          = TYPE_SCLP_CPU_HOTPLUG,
9549204458SJason J. Herne     .parent        = TYPE_SCLP_EVENT,
9649204458SJason J. Herne     .instance_size = sizeof(SCLPEvent),
97*83f1ab12SPhilippe Mathieu-Daudé     .class_init    = sclp_cpu_class_init,
9849204458SJason J. Herne     .class_size    = sizeof(SCLPEventClass),
9949204458SJason J. Herne };
10049204458SJason J. Herne 
sclp_cpu_register_types(void)10149204458SJason J. Herne static void sclp_cpu_register_types(void)
10249204458SJason J. Herne {
10349204458SJason J. Herne     type_register_static(&sclp_cpu_info);
10449204458SJason J. Herne }
10549204458SJason J. Herne 
10649204458SJason J. Herne type_init(sclp_cpu_register_types)
107