2 * S/390 misc helper routines
4 * Copyright (c) 2009 Ulrich Hecht
5 * Copyright (c) 2009 Alexander Graf
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "host-utils.h"
28 #include "qemu-timer.h"
30 #include <linux/kvm.h>
33 #if !defined(CONFIG_USER_ONLY)
34 #include "softmmu_exec.h"
38 /* #define DEBUG_HELPER */
40 #define HELPER_LOG(x...) qemu_log(x)
42 #define HELPER_LOG(x...)
45 /* raise an exception */
46 void HELPER(exception
)(CPUS390XState
*env
, uint32_t excp
)
48 HELPER_LOG("%s: exception %d\n", __func__
, excp
);
49 env
->exception_index
= excp
;
53 #ifndef CONFIG_USER_ONLY
54 void program_interrupt(CPUS390XState
*env
, uint32_t code
, int ilc
)
56 qemu_log_mask(CPU_LOG_INT
, "program interrupt at %#" PRIx64
"\n",
61 kvm_s390_interrupt(env
, KVM_S390_PROGRAM_INT
, code
);
64 env
->int_pgm_code
= code
;
65 env
->int_pgm_ilc
= ilc
;
66 env
->exception_index
= EXCP_PGM
;
72 * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc
74 int sclp_service_call(CPUS390XState
*env
, uint32_t sccb
, uint64_t code
)
80 printf("sclp(0x%x, 0x%" PRIx64
")\n", sccb
, code
);
84 if (!memory_region_is_ram(phys_page_find(sccb
>> TARGET_PAGE_BITS
)->mr
)) {
85 return -PGM_ADDRESSING
;
87 if (sccb
& ~0x7ffffff8ul
) {
88 return -PGM_SPECIFICATION
;
92 case SCLP_CMDW_READ_SCP_INFO
:
93 case SCLP_CMDW_READ_SCP_INFO_FORCED
:
94 while ((ram_size
>> (20 + shift
)) > 65535) {
97 stw_phys(sccb
+ SCP_MEM_CODE
, ram_size
>> (20 + shift
));
98 stb_phys(sccb
+ SCP_INCREMENT
, 1 << shift
);
99 stw_phys(sccb
+ SCP_RESPONSE_CODE
, 0x10);
101 s390_sclp_extint(sccb
& ~3);
105 printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64
"x\n", sccb
, code
);
114 /* SCLP service call */
115 uint32_t HELPER(servc
)(CPUS390XState
*env
, uint32_t r1
, uint64_t r2
)
119 r
= sclp_service_call(env
, r1
, r2
);
121 program_interrupt(env
, -r
, 4);
128 uint64_t HELPER(diag
)(CPUS390XState
*env
, uint32_t num
, uint64_t mem
,
136 r
= s390_virtio_hypercall(env
, mem
, code
);
152 program_interrupt(env
, PGM_OPERATION
, ILC_LATER_INC
);
159 void HELPER(stidp
)(CPUS390XState
*env
, uint64_t a1
)
161 cpu_stq_data(env
, a1
, env
->cpu_num
);
165 void HELPER(spx
)(CPUS390XState
*env
, uint64_t a1
)
169 prefix
= cpu_ldl_data(env
, a1
);
170 env
->psa
= prefix
& 0xfffff000;
171 qemu_log("prefix: %#x\n", prefix
);
172 tlb_flush_page(env
, 0);
173 tlb_flush_page(env
, TARGET_PAGE_SIZE
);
177 uint32_t HELPER(sck
)(uint64_t a1
)
179 /* XXX not implemented - is it necessary? */
184 static inline uint64_t clock_value(CPUS390XState
*env
)
188 time
= env
->tod_offset
+
189 time2tod(qemu_get_clock_ns(vm_clock
) - env
->tod_basetime
);
195 uint32_t HELPER(stck
)(CPUS390XState
*env
, uint64_t a1
)
197 cpu_stq_data(env
, a1
, clock_value(env
));
202 /* Store Clock Extended */
203 uint32_t HELPER(stcke
)(CPUS390XState
*env
, uint64_t a1
)
205 cpu_stb_data(env
, a1
, 0);
206 /* basically the same value as stck */
207 cpu_stq_data(env
, a1
+ 1, clock_value(env
) | env
->cpu_num
);
208 /* more fine grained than stck */
209 cpu_stq_data(env
, a1
+ 9, 0);
210 /* XXX programmable fields */
211 cpu_stw_data(env
, a1
+ 17, 0);
216 /* Set Clock Comparator */
217 void HELPER(sckc
)(CPUS390XState
*env
, uint64_t a1
)
219 uint64_t time
= cpu_ldq_data(env
, a1
);
225 /* difference between now and then */
226 time
-= clock_value(env
);
228 time
= (time
* 125) >> 9;
230 qemu_mod_timer(env
->tod_timer
, qemu_get_clock_ns(vm_clock
) + time
);
233 /* Store Clock Comparator */
234 void HELPER(stckc
)(CPUS390XState
*env
, uint64_t a1
)
237 cpu_stq_data(env
, a1
, 0);
241 void HELPER(spt
)(CPUS390XState
*env
, uint64_t a1
)
243 uint64_t time
= cpu_ldq_data(env
, a1
);
250 time
= (time
* 125) >> 9;
252 qemu_mod_timer(env
->cpu_timer
, qemu_get_clock_ns(vm_clock
) + time
);
255 /* Store CPU Timer */
256 void HELPER(stpt
)(CPUS390XState
*env
, uint64_t a1
)
259 cpu_stq_data(env
, a1
, 0);
262 /* Store System Information */
263 uint32_t HELPER(stsi
)(CPUS390XState
*env
, uint64_t a0
, uint32_t r0
,
269 if ((r0
& STSI_LEVEL_MASK
) <= STSI_LEVEL_3
&&
270 ((r0
& STSI_R0_RESERVED_MASK
) || (r1
& STSI_R1_RESERVED_MASK
))) {
271 /* valid function code, invalid reserved bits */
272 program_interrupt(env
, PGM_SPECIFICATION
, 2);
275 sel1
= r0
& STSI_R0_SEL1_MASK
;
276 sel2
= r1
& STSI_R1_SEL2_MASK
;
278 /* XXX: spec exception if sysib is not 4k-aligned */
280 switch (r0
& STSI_LEVEL_MASK
) {
282 if ((sel1
== 1) && (sel2
== 1)) {
283 /* Basic Machine Configuration */
284 struct sysib_111 sysib
;
286 memset(&sysib
, 0, sizeof(sysib
));
287 ebcdic_put(sysib
.manuf
, "QEMU ", 16);
288 /* same as machine type number in STORE CPU ID */
289 ebcdic_put(sysib
.type
, "QEMU", 4);
290 /* same as model number in STORE CPU ID */
291 ebcdic_put(sysib
.model
, "QEMU ", 16);
292 ebcdic_put(sysib
.sequence
, "QEMU ", 16);
293 ebcdic_put(sysib
.plant
, "QEMU", 4);
294 cpu_physical_memory_rw(a0
, (uint8_t *)&sysib
, sizeof(sysib
), 1);
295 } else if ((sel1
== 2) && (sel2
== 1)) {
296 /* Basic Machine CPU */
297 struct sysib_121 sysib
;
299 memset(&sysib
, 0, sizeof(sysib
));
300 /* XXX make different for different CPUs? */
301 ebcdic_put(sysib
.sequence
, "QEMUQEMUQEMUQEMU", 16);
302 ebcdic_put(sysib
.plant
, "QEMU", 4);
303 stw_p(&sysib
.cpu_addr
, env
->cpu_num
);
304 cpu_physical_memory_rw(a0
, (uint8_t *)&sysib
, sizeof(sysib
), 1);
305 } else if ((sel1
== 2) && (sel2
== 2)) {
306 /* Basic Machine CPUs */
307 struct sysib_122 sysib
;
309 memset(&sysib
, 0, sizeof(sysib
));
310 stl_p(&sysib
.capability
, 0x443afc29);
311 /* XXX change when SMP comes */
312 stw_p(&sysib
.total_cpus
, 1);
313 stw_p(&sysib
.active_cpus
, 1);
314 stw_p(&sysib
.standby_cpus
, 0);
315 stw_p(&sysib
.reserved_cpus
, 0);
316 cpu_physical_memory_rw(a0
, (uint8_t *)&sysib
, sizeof(sysib
), 1);
323 if ((sel1
== 2) && (sel2
== 1)) {
325 struct sysib_221 sysib
;
327 memset(&sysib
, 0, sizeof(sysib
));
328 /* XXX make different for different CPUs? */
329 ebcdic_put(sysib
.sequence
, "QEMUQEMUQEMUQEMU", 16);
330 ebcdic_put(sysib
.plant
, "QEMU", 4);
331 stw_p(&sysib
.cpu_addr
, env
->cpu_num
);
332 stw_p(&sysib
.cpu_id
, 0);
333 cpu_physical_memory_rw(a0
, (uint8_t *)&sysib
, sizeof(sysib
), 1);
334 } else if ((sel1
== 2) && (sel2
== 2)) {
336 struct sysib_222 sysib
;
338 memset(&sysib
, 0, sizeof(sysib
));
339 stw_p(&sysib
.lpar_num
, 0);
341 /* XXX change when SMP comes */
342 stw_p(&sysib
.total_cpus
, 1);
343 stw_p(&sysib
.conf_cpus
, 1);
344 stw_p(&sysib
.standby_cpus
, 0);
345 stw_p(&sysib
.reserved_cpus
, 0);
346 ebcdic_put(sysib
.name
, "QEMU ", 8);
347 stl_p(&sysib
.caf
, 1000);
348 stw_p(&sysib
.dedicated_cpus
, 0);
349 stw_p(&sysib
.shared_cpus
, 0);
350 cpu_physical_memory_rw(a0
, (uint8_t *)&sysib
, sizeof(sysib
), 1);
358 if ((sel1
== 2) && (sel2
== 2)) {
360 struct sysib_322 sysib
;
362 memset(&sysib
, 0, sizeof(sysib
));
364 /* XXX change when SMP comes */
365 stw_p(&sysib
.vm
[0].total_cpus
, 1);
366 stw_p(&sysib
.vm
[0].conf_cpus
, 1);
367 stw_p(&sysib
.vm
[0].standby_cpus
, 0);
368 stw_p(&sysib
.vm
[0].reserved_cpus
, 0);
369 ebcdic_put(sysib
.vm
[0].name
, "KVMguest", 8);
370 stl_p(&sysib
.vm
[0].caf
, 1000);
371 ebcdic_put(sysib
.vm
[0].cpi
, "KVM/Linux ", 16);
372 cpu_physical_memory_rw(a0
, (uint8_t *)&sysib
, sizeof(sysib
), 1);
378 case STSI_LEVEL_CURRENT
:
379 env
->regs
[0] = STSI_LEVEL_3
;
389 uint32_t HELPER(sigp
)(CPUS390XState
*env
, uint64_t order_code
, uint32_t r1
,
394 HELPER_LOG("%s: %016" PRIx64
" %08x %016" PRIx64
"\n",
395 __func__
, order_code
, r1
, cpu_addr
);
397 /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
398 as parameter (input). Status (output) is always R1. */
400 switch (order_code
) {
405 /* enumerate CPU status */
407 /* XXX implement when SMP comes */
410 env
->regs
[r1
] &= 0xffffffff00000000ULL
;
413 #if !defined(CONFIG_USER_ONLY)
415 qemu_system_reset_request();
419 qemu_system_shutdown_request();
425 fprintf(stderr
, "XXX unknown sigp: 0x%" PRIx64
"\n", order_code
);