1 /* 2 * SCLP event type 3 * Signal CPU - Trigger SCLP interrupt for system CPU configure or 4 * de-configure 5 * 6 * Copyright IBM, Corp. 2013 7 * 8 * Authors: 9 * Thang Pham <thang.pham@us.ibm.com> 10 * 11 * This work is licensed under the terms of the GNU GPL, version 2 or (at your 12 * option) any later version. See the COPYING file in the top-level directory. 13 * 14 */ 15 #include "sysemu/sysemu.h" 16 #include "hw/s390x/sclp.h" 17 #include "hw/s390x/event-facility.h" 18 #include "cpu.h" 19 #include "sysemu/cpus.h" 20 #include "sysemu/kvm.h" 21 22 typedef struct ConfigMgtData { 23 EventBufferHeader ebh; 24 uint8_t reserved; 25 uint8_t event_qualifier; 26 } QEMU_PACKED ConfigMgtData; 27 28 static qemu_irq *irq_cpu_hotplug; /* Only used in this file */ 29 30 #define EVENT_QUAL_CPU_CHANGE 1 31 32 void raise_irq_cpu_hotplug(void) 33 { 34 qemu_irq_raise(*irq_cpu_hotplug); 35 } 36 37 static unsigned int send_mask(void) 38 { 39 return SCLP_EVENT_MASK_CONFIG_MGT_DATA; 40 } 41 42 static unsigned int receive_mask(void) 43 { 44 return 0; 45 } 46 47 static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, 48 int *slen) 49 { 50 ConfigMgtData *cdata = (ConfigMgtData *) evt_buf_hdr; 51 if (*slen < sizeof(ConfigMgtData)) { 52 return 0; 53 } 54 55 /* Event is no longer pending */ 56 if (!event->event_pending) { 57 return 0; 58 } 59 event->event_pending = false; 60 61 /* Event header data */ 62 cdata->ebh.length = cpu_to_be16(sizeof(ConfigMgtData)); 63 cdata->ebh.type = SCLP_EVENT_CONFIG_MGT_DATA; 64 cdata->ebh.flags |= SCLP_EVENT_BUFFER_ACCEPTED; 65 66 /* Trigger a rescan of CPUs by setting event qualifier */ 67 cdata->event_qualifier = EVENT_QUAL_CPU_CHANGE; 68 *slen -= sizeof(ConfigMgtData); 69 70 return 1; 71 } 72 73 static void trigger_signal(void *opaque, int n, int level) 74 { 75 SCLPEvent *event = opaque; 76 event->event_pending = true; 77 78 /* Trigger SCLP read operation */ 79 sclp_service_interrupt(0); 80 } 81 82 static int irq_cpu_hotplug_init(SCLPEvent *event) 83 { 84 irq_cpu_hotplug = qemu_allocate_irqs(trigger_signal, event, 1); 85 return 0; 86 } 87 88 static void cpu_class_init(ObjectClass *oc, void *data) 89 { 90 SCLPEventClass *k = SCLP_EVENT_CLASS(oc); 91 92 k->init = irq_cpu_hotplug_init; 93 k->get_send_mask = send_mask; 94 k->get_receive_mask = receive_mask; 95 k->read_event_data = read_event_data; 96 k->write_event_data = NULL; 97 } 98 99 static const TypeInfo sclp_cpu_info = { 100 .name = "sclp-cpu-hotplug", 101 .parent = TYPE_SCLP_EVENT, 102 .instance_size = sizeof(SCLPEvent), 103 .class_init = cpu_class_init, 104 .class_size = sizeof(SCLPEventClass), 105 }; 106 107 static void sclp_cpu_register_types(void) 108 { 109 type_register_static(&sclp_cpu_info); 110 } 111 112 type_init(sclp_cpu_register_types) 113