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"
21 #include "hw/s390x/event-facility.h"
23 static inline SCLPEventFacility
*get_event_facility(void)
25 ObjectProperty
*op
= object_property_find(qdev_get_machine(),
26 TYPE_SCLP_EVENT_FACILITY
,
32 /* Provide information about the configuration, CPUs and storage */
33 static void read_SCP_info(SCCB
*sccb
)
35 ReadInfo
*read_info
= (ReadInfo
*) sccb
;
46 read_info
->entries_cpu
= cpu_to_be16(cpu_count
);
47 read_info
->offset_cpu
= cpu_to_be16(offsetof(ReadInfo
, entries
));
48 read_info
->highest_cpu
= cpu_to_be16(max_cpus
);
50 for (i
= 0; i
< cpu_count
; i
++) {
51 read_info
->entries
[i
].address
= i
;
52 read_info
->entries
[i
].type
= 0;
55 read_info
->facilities
= cpu_to_be64(SCLP_HAS_CPU_INFO
);
57 while ((ram_size
>> (20 + shift
)) > 65535) {
60 read_info
->rnmax
= cpu_to_be16(ram_size
>> (20 + shift
));
61 read_info
->rnsize
= 1 << shift
;
62 sccb
->h
.response_code
= cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION
);
65 /* Provide information about the CPU */
66 static void sclp_read_cpu_info(SCCB
*sccb
)
68 ReadCpuInfo
*cpu_info
= (ReadCpuInfo
*) sccb
;
77 cpu_info
->nr_configured
= cpu_to_be16(cpu_count
);
78 cpu_info
->offset_configured
= cpu_to_be16(offsetof(ReadCpuInfo
, entries
));
79 cpu_info
->nr_standby
= cpu_to_be16(0);
81 /* The standby offset is 16-byte for each CPU */
82 cpu_info
->offset_standby
= cpu_to_be16(cpu_info
->offset_configured
83 + cpu_info
->nr_configured
*sizeof(CPUEntry
));
85 for (i
= 0; i
< cpu_count
; i
++) {
86 cpu_info
->entries
[i
].address
= i
;
87 cpu_info
->entries
[i
].type
= 0;
90 sccb
->h
.response_code
= cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION
);
93 static void sclp_execute(SCCB
*sccb
, uint32_t code
)
95 SCLPEventFacility
*ef
= get_event_facility();
96 SCLPEventFacilityClass
*efc
= EVENT_FACILITY_GET_CLASS(ef
);
98 switch (code
& SCLP_CMD_CODE_MASK
) {
99 case SCLP_CMDW_READ_SCP_INFO
:
100 case SCLP_CMDW_READ_SCP_INFO_FORCED
:
103 case SCLP_CMDW_READ_CPU_INFO
:
104 sclp_read_cpu_info(sccb
);
107 efc
->command_handler(ef
, sccb
, code
);
112 int sclp_service_call(CPUS390XState
*env
, uint64_t sccb
, uint32_t code
)
117 hwaddr sccb_len
= sizeof(SCCB
);
119 /* first some basic checks on program checks */
120 if (env
->psw
.mask
& PSW_MASK_PSTATE
) {
124 if (cpu_physical_memory_is_io(sccb
)) {
128 if ((sccb
& ~0x1fffUL
) == 0 || (sccb
& ~0x1fffUL
) == env
->psa
129 || (sccb
& ~0x7ffffff8UL
) != 0) {
130 r
= -PGM_SPECIFICATION
;
135 * we want to work on a private copy of the sccb, to prevent guests
136 * from playing dirty tricks by modifying the memory content after
137 * the host has checked the values
139 cpu_physical_memory_read(sccb
, &work_sccb
, sccb_len
);
141 /* Valid sccb sizes */
142 if (be16_to_cpu(work_sccb
.h
.length
) < sizeof(SCCBHeader
) ||
143 be16_to_cpu(work_sccb
.h
.length
) > SCCB_SIZE
) {
144 r
= -PGM_SPECIFICATION
;
148 sclp_execute((SCCB
*)&work_sccb
, code
);
150 cpu_physical_memory_write(sccb
, &work_sccb
,
151 be16_to_cpu(work_sccb
.h
.length
));
153 sclp_service_interrupt(sccb
);
159 void sclp_service_interrupt(uint32_t sccb
)
161 SCLPEventFacility
*ef
= get_event_facility();
162 SCLPEventFacilityClass
*efc
= EVENT_FACILITY_GET_CLASS(ef
);
164 uint32_t param
= sccb
& ~3;
166 /* Indicate whether an event is still pending */
167 param
|= efc
->event_pending(ef
) ? 1 : 0;
170 /* No need to send an interrupt, there's nothing to be notified about */
173 s390_sclp_extint(param
);
176 /* qemu object creation and initialization functions */
178 void s390_sclp_init(void)
180 DeviceState
*dev
= qdev_create(NULL
, TYPE_SCLP_EVENT_FACILITY
);
182 object_property_add_child(qdev_get_machine(), TYPE_SCLP_EVENT_FACILITY
,
184 qdev_init_nofail(dev
);