4 * Copyright IBM, Corp. 2012
7 * Christian Borntraeger <borntraeger@de.ibm.com>
8 * Heinz Graalfs <graalfs@linux.vnet.ibm.com>
10 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
11 * option) any later version. See the COPYING file in the top-level directory.
16 #include "sysemu/kvm.h"
17 #include "exec/memory.h"
19 #include "hw/s390x/sclp.h"
21 static inline S390SCLPDevice
*get_event_facility(void)
23 ObjectProperty
*op
= object_property_find(qdev_get_machine(),
24 "s390-sclp-event-facility",
30 /* Provide information about the configuration, CPUs and storage */
31 static void read_SCP_info(SCCB
*sccb
)
33 ReadInfo
*read_info
= (ReadInfo
*) sccb
;
36 while ((ram_size
>> (20 + shift
)) > 65535) {
39 read_info
->rnmax
= cpu_to_be16(ram_size
>> (20 + shift
));
40 read_info
->rnsize
= 1 << shift
;
41 sccb
->h
.response_code
= cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION
);
44 static void sclp_execute(SCCB
*sccb
, uint64_t code
)
46 S390SCLPDevice
*sdev
= get_event_facility();
49 case SCLP_CMDW_READ_SCP_INFO
:
50 case SCLP_CMDW_READ_SCP_INFO_FORCED
:
54 sdev
->sclp_command_handler(sdev
->ef
, sccb
, code
);
59 int sclp_service_call(uint32_t sccb
, uint64_t code
)
64 hwaddr sccb_len
= sizeof(SCCB
);
66 /* first some basic checks on program checks */
67 if (cpu_physical_memory_is_io(sccb
)) {
71 if (sccb
& ~0x7ffffff8ul
) {
72 r
= -PGM_SPECIFICATION
;
77 * we want to work on a private copy of the sccb, to prevent guests
78 * from playing dirty tricks by modifying the memory content after
79 * the host has checked the values
81 cpu_physical_memory_read(sccb
, &work_sccb
, sccb_len
);
83 /* Valid sccb sizes */
84 if (be16_to_cpu(work_sccb
.h
.length
) < sizeof(SCCBHeader
) ||
85 be16_to_cpu(work_sccb
.h
.length
) > SCCB_SIZE
) {
86 r
= -PGM_SPECIFICATION
;
90 sclp_execute((SCCB
*)&work_sccb
, code
);
92 cpu_physical_memory_write(sccb
, &work_sccb
,
93 be16_to_cpu(work_sccb
.h
.length
));
95 sclp_service_interrupt(sccb
);
101 void sclp_service_interrupt(uint32_t sccb
)
103 S390SCLPDevice
*sdev
= get_event_facility();
104 uint32_t param
= sccb
& ~3;
106 /* Indicate whether an event is still pending */
107 param
|= sdev
->event_pending(sdev
->ef
) ? 1 : 0;
110 /* No need to send an interrupt, there's nothing to be notified about */
113 s390_sclp_extint(param
);
116 /* qemu object creation and initialization functions */
118 void s390_sclp_init(void)
120 DeviceState
*dev
= qdev_create(NULL
, "s390-sclp-event-facility");
122 object_property_add_child(qdev_get_machine(), "s390-sclp-event-facility",
124 qdev_init_nofail(dev
);
127 static int s390_sclp_dev_init(SysBusDevice
*dev
)
130 S390SCLPDevice
*sdev
= (S390SCLPDevice
*)dev
;
131 S390SCLPDeviceClass
*sclp
= SCLP_S390_DEVICE_GET_CLASS(dev
);
133 r
= sclp
->init(sdev
);
135 assert(sdev
->event_pending
);
136 assert(sdev
->sclp_command_handler
);
142 static void s390_sclp_device_class_init(ObjectClass
*klass
, void *data
)
144 SysBusDeviceClass
*dc
= SYS_BUS_DEVICE_CLASS(klass
);
146 dc
->init
= s390_sclp_dev_init
;
149 static const TypeInfo s390_sclp_device_info
= {
150 .name
= TYPE_DEVICE_S390_SCLP
,
151 .parent
= TYPE_SYS_BUS_DEVICE
,
152 .instance_size
= sizeof(S390SCLPDevice
),
153 .class_init
= s390_sclp_device_class_init
,
154 .class_size
= sizeof(S390SCLPDeviceClass
),
158 static void s390_sclp_register_types(void)
160 type_register_static(&s390_sclp_device_info
);
163 type_init(s390_sclp_register_types
)