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"
18 #include "sysemu/sysemu.h"
20 #include "hw/s390x/sclp.h"
22 static inline S390SCLPDevice
*get_event_facility(void)
24 ObjectProperty
*op
= object_property_find(qdev_get_machine(),
25 "s390-sclp-event-facility",
31 /* Provide information about the configuration, CPUs and storage */
32 static void read_SCP_info(SCCB
*sccb
)
34 ReadInfo
*read_info
= (ReadInfo
*) sccb
;
45 read_info
->entries_cpu
= cpu_to_be16(cpu_count
);
46 read_info
->offset_cpu
= cpu_to_be16(offsetof(ReadInfo
, entries
));
47 read_info
->highest_cpu
= cpu_to_be16(max_cpus
);
49 for (i
= 0; i
< cpu_count
; i
++) {
50 read_info
->entries
[i
].address
= i
;
51 read_info
->entries
[i
].type
= 0;
54 read_info
->facilities
= cpu_to_be64(SCLP_HAS_CPU_INFO
);
56 while ((ram_size
>> (20 + shift
)) > 65535) {
59 read_info
->rnmax
= cpu_to_be16(ram_size
>> (20 + shift
));
60 read_info
->rnsize
= 1 << shift
;
61 sccb
->h
.response_code
= cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION
);
64 /* Provide information about the CPU */
65 static void sclp_read_cpu_info(SCCB
*sccb
)
67 ReadCpuInfo
*cpu_info
= (ReadCpuInfo
*) sccb
;
76 cpu_info
->nr_configured
= cpu_to_be16(cpu_count
);
77 cpu_info
->offset_configured
= cpu_to_be16(offsetof(ReadCpuInfo
, entries
));
78 cpu_info
->nr_standby
= cpu_to_be16(0);
80 /* The standby offset is 16-byte for each CPU */
81 cpu_info
->offset_standby
= cpu_to_be16(cpu_info
->offset_configured
82 + cpu_info
->nr_configured
*sizeof(CPUEntry
));
84 for (i
= 0; i
< cpu_count
; i
++) {
85 cpu_info
->entries
[i
].address
= i
;
86 cpu_info
->entries
[i
].type
= 0;
89 sccb
->h
.response_code
= cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION
);
92 static void sclp_execute(SCCB
*sccb
, uint64_t code
)
94 S390SCLPDevice
*sdev
= get_event_facility();
96 switch (code
& SCLP_CMD_CODE_MASK
) {
97 case SCLP_CMDW_READ_SCP_INFO
:
98 case SCLP_CMDW_READ_SCP_INFO_FORCED
:
101 case SCLP_CMDW_READ_CPU_INFO
:
102 sclp_read_cpu_info(sccb
);
105 sdev
->sclp_command_handler(sdev
->ef
, sccb
, code
);
110 int sclp_service_call(uint32_t sccb
, uint64_t code
)
115 hwaddr sccb_len
= sizeof(SCCB
);
117 /* first some basic checks on program checks */
118 if (cpu_physical_memory_is_io(sccb
)) {
122 if (sccb
& ~0x7ffffff8ul
) {
123 r
= -PGM_SPECIFICATION
;
128 * we want to work on a private copy of the sccb, to prevent guests
129 * from playing dirty tricks by modifying the memory content after
130 * the host has checked the values
132 cpu_physical_memory_read(sccb
, &work_sccb
, sccb_len
);
134 /* Valid sccb sizes */
135 if (be16_to_cpu(work_sccb
.h
.length
) < sizeof(SCCBHeader
) ||
136 be16_to_cpu(work_sccb
.h
.length
) > SCCB_SIZE
) {
137 r
= -PGM_SPECIFICATION
;
141 sclp_execute((SCCB
*)&work_sccb
, code
);
143 cpu_physical_memory_write(sccb
, &work_sccb
,
144 be16_to_cpu(work_sccb
.h
.length
));
146 sclp_service_interrupt(sccb
);
152 void sclp_service_interrupt(uint32_t sccb
)
154 S390SCLPDevice
*sdev
= get_event_facility();
155 uint32_t param
= sccb
& ~3;
157 /* Indicate whether an event is still pending */
158 param
|= sdev
->event_pending(sdev
->ef
) ? 1 : 0;
161 /* No need to send an interrupt, there's nothing to be notified about */
164 s390_sclp_extint(param
);
167 /* qemu object creation and initialization functions */
169 void s390_sclp_init(void)
171 DeviceState
*dev
= qdev_create(NULL
, "s390-sclp-event-facility");
173 object_property_add_child(qdev_get_machine(), "s390-sclp-event-facility",
175 qdev_init_nofail(dev
);
178 static int s390_sclp_dev_init(SysBusDevice
*dev
)
181 S390SCLPDevice
*sdev
= (S390SCLPDevice
*)dev
;
182 S390SCLPDeviceClass
*sclp
= SCLP_S390_DEVICE_GET_CLASS(dev
);
184 r
= sclp
->init(sdev
);
186 assert(sdev
->event_pending
);
187 assert(sdev
->sclp_command_handler
);
193 static void s390_sclp_device_class_init(ObjectClass
*klass
, void *data
)
195 SysBusDeviceClass
*dc
= SYS_BUS_DEVICE_CLASS(klass
);
197 dc
->init
= s390_sclp_dev_init
;
200 static const TypeInfo s390_sclp_device_info
= {
201 .name
= TYPE_DEVICE_S390_SCLP
,
202 .parent
= TYPE_SYS_BUS_DEVICE
,
203 .instance_size
= sizeof(S390SCLPDevice
),
204 .class_init
= s390_sclp_device_class_init
,
205 .class_size
= sizeof(S390SCLPDeviceClass
),
209 static void s390_sclp_register_types(void)
211 type_register_static(&s390_sclp_device_info
);
214 type_init(s390_sclp_register_types
)