2 * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
8 static char* parse_addrspec(u64
*val
, u64
*len
, char *s
)
17 if (*s
>= '0' && *s
<= '9')
18 tmp
= 16*tmp
+ (*s
- '0');
19 else if ((*s
>= 'A' && *s
<= 'F') ||
20 (*s
>= 'a' && *s
<= 'f'))
21 tmp
= 16*tmp
+ 10 + ((*s
& ~0x20) - 'A');
22 else if (*s
== '.' && parsed
)
25 return ERR_PTR(-EINVAL
);
34 s
= __extract_hex(s
+1, len
);
42 return (parsed
== 1 ? s
: ERR_PTR(-EINVAL
));
50 static void __display_storage_instruct(struct virt_sys
*sys
, u64 guest_addr
,
61 /* walk the page tables to find the real page frame */
62 ret
= virt2phy_current(guest_addr
, &host_addr
);
64 con_printf(sys
->con
, "DISPLAY: Specified address is not part of "
65 "guest configuration (RC=%d,%d)\n", -EFAULT
, ret
);
72 end_addr
= guest_addr
+ mlen
;
74 while(guest_addr
< end_addr
) {
76 * FIXME: make sure crossing page-boundary doesn't break
79 ilen
= disassm((unsigned char*) host_addr
, buf
, 64);
81 if ((host_addr
& PAGE_MASK
) >= (PAGE_SIZE
-ilen
)) {
82 con_printf(sys
->con
, "DISPLAY: Instruction spans page "
83 "boundary - not supported\n");
87 /* load the dword at the address, and shift it to the LSB part */
88 val
= *((u64
*)host_addr
) >> 8*(sizeof(u64
) - ilen
);
90 con_printf(sys
->con
, "R%016llX %0*llX%*s %s\n", guest_addr
,
91 2*ilen
, val
, /* inst hex dump */
92 12-2*ilen
, "", /* spacer */
100 static void __display_storage_numeric(struct virt_sys
*sys
, u64 guest_addr
,
112 guest_addr
&= ~((u64
) 0x3);
114 /* walk the page tables to find the real page frame */
115 ret
= virt2phy_current(guest_addr
, &host_addr
);
120 mlen
= (mlen
>> 2) + !!(mlen
& 0x3);
124 while(mlen
&& !ret
) {
125 this_len
= (mlen
> 4) ? 4 : mlen
;
130 bp
+= snprintf(bp
, 80, "R%016llX ", guest_addr
);
133 bp
+= snprintf(bp
, 80 - (bp
- buf
), "%08X ",
140 /* loop if we're not crossing a page, or if we're done */
141 if (((guest_addr
& PAGE_MASK
) != 0) || !mlen
)
145 * We will attempt to walk further along guest
146 * storage, and are about to cross a page boundary,
147 * walk the page tables to find the real page frame
149 ret
= virt2phy_current(guest_addr
, &host_addr
);
154 con_printf(sys
->con
, "%s\n", buf
);
159 con_printf(sys
->con
, "DISPLAY: The address %016llX is not part of "
160 "guest configuration (RC=%d,%d)\n", guest_addr
, -EFAULT
, ret
);
166 *! \tok{\sc Display} \tok{\sc STOrage}
167 *! \begin{stack} \\ \deftok{N} \\ \tok{I} \end{stack}
169 *! \begin{stack} \\ \tok{.} <length> \end{stack}
173 *! Displays a portion of guest's storage.
176 *! \item[addr] is the guest storage address.
177 *! \item[length] is the number of bytes to display. If not specified, 4 is
183 *! \item[N] display guest storage in numeric format.
184 *! \item[I] display guest storage in instruction format.
189 *! \item Currently, the instruction display does not support page-boundary
198 static int cmd_display_storage(struct virt_sys
*sys
, char *cmd
, int len
)
202 enum display_fmt fmt
;
204 SHELL_CMD_AUTH(sys
, G
);
223 cmd
= parse_addrspec(&guest_addr
, &mlen
, cmd
);
225 con_printf(sys
->con
, "DISPLAY: Invalid addr-spec\n");
229 if (fmt
== FMT_INSTRUCT
)
230 __display_storage_instruct(sys
, guest_addr
, mlen
);
232 __display_storage_numeric(sys
, guest_addr
, mlen
);
240 *! \tok{\sc Display} \tok{\sc SIECB}
244 *! Displays hexdump of the guest's SIE control block.
246 static int cmd_display_siecb(struct virt_sys
*sys
, char *cmd
, int len
)
251 SHELL_CMD_AUTH(sys
, E
);
253 val
= (u32
*) &sys
->task
->cpu
->sie_cb
;
255 con_printf(sys
->con
, "SIECB FOR %s AT %p\n",
256 sys
->directory
->userid
, val
);
257 for(i
=0; i
<(sizeof(struct sie_cb
)/sizeof(u32
)); i
+=4)
258 con_printf(sys
->con
, "%03lX %08X %08X %08X %08X\n",
259 i
*sizeof(u32
), val
[i
], val
[i
+1], val
[i
+2],
268 *! \tok{\sc Display} \tok{\sc Gpr}
272 *! Displays the guest's general purpose registers
274 static int cmd_display_gpr(struct virt_sys
*sys
, char *cmd
, int len
)
276 SHELL_CMD_AUTH(sys
, G
);
278 con_printf(sys
->con
, "GR 0 = %016llX %016llX\n",
279 sys
->task
->cpu
->regs
.gpr
[0],
280 sys
->task
->cpu
->regs
.gpr
[1]);
281 con_printf(sys
->con
, "GR 2 = %016llX %016llX\n",
282 sys
->task
->cpu
->regs
.gpr
[2],
283 sys
->task
->cpu
->regs
.gpr
[3]);
284 con_printf(sys
->con
, "GR 4 = %016llX %016llX\n",
285 sys
->task
->cpu
->regs
.gpr
[4],
286 sys
->task
->cpu
->regs
.gpr
[5]);
287 con_printf(sys
->con
, "GR 6 = %016llX %016llX\n",
288 sys
->task
->cpu
->regs
.gpr
[6],
289 sys
->task
->cpu
->regs
.gpr
[7]);
290 con_printf(sys
->con
, "GR 8 = %016llX %016llX\n",
291 sys
->task
->cpu
->regs
.gpr
[8],
292 sys
->task
->cpu
->regs
.gpr
[9]);
293 con_printf(sys
->con
, "GR 10 = %016llX %016llX\n",
294 sys
->task
->cpu
->regs
.gpr
[10],
295 sys
->task
->cpu
->regs
.gpr
[11]);
296 con_printf(sys
->con
, "GR 12 = %016llX %016llX\n",
297 sys
->task
->cpu
->regs
.gpr
[12],
298 sys
->task
->cpu
->regs
.gpr
[13]);
299 con_printf(sys
->con
, "GR 14 = %016llX %016llX\n",
300 sys
->task
->cpu
->regs
.gpr
[14],
301 sys
->task
->cpu
->regs
.gpr
[15]);
308 *! \tok{\sc Display} \tok{\sc FPCR}
312 *! Displays the guest's floating point control register
314 static int cmd_display_fpcr(struct virt_sys
*sys
, char *cmd
, int len
)
316 SHELL_CMD_AUTH(sys
, G
);
318 con_printf(sys
->con
, "FPCR = %08X\n", sys
->task
->cpu
->regs
.fpcr
);
325 *! \tok{\sc Display} \tok{\sc Fpr}
329 *! Displays the guest's floating point registers
331 static int cmd_display_fpr(struct virt_sys
*sys
, char *cmd
, int len
)
333 SHELL_CMD_AUTH(sys
, G
);
335 con_printf(sys
->con
, "FR 0 = %016llX %016llX\n",
336 sys
->task
->cpu
->regs
.fpr
[0],
337 sys
->task
->cpu
->regs
.fpr
[1]);
338 con_printf(sys
->con
, "FR 2 = %016llX %016llX\n",
339 sys
->task
->cpu
->regs
.fpr
[2],
340 sys
->task
->cpu
->regs
.fpr
[3]);
341 con_printf(sys
->con
, "FR 4 = %016llX %016llX\n",
342 sys
->task
->cpu
->regs
.fpr
[4],
343 sys
->task
->cpu
->regs
.fpr
[5]);
344 con_printf(sys
->con
, "FR 6 = %016llX %016llX\n",
345 sys
->task
->cpu
->regs
.fpr
[6],
346 sys
->task
->cpu
->regs
.fpr
[7]);
347 con_printf(sys
->con
, "FR 8 = %016llX %016llX\n",
348 sys
->task
->cpu
->regs
.fpr
[8],
349 sys
->task
->cpu
->regs
.fpr
[9]);
350 con_printf(sys
->con
, "FR 10 = %016llX %016llX\n",
351 sys
->task
->cpu
->regs
.fpr
[10],
352 sys
->task
->cpu
->regs
.fpr
[11]);
353 con_printf(sys
->con
, "FR 12 = %016llX %016llX\n",
354 sys
->task
->cpu
->regs
.fpr
[12],
355 sys
->task
->cpu
->regs
.fpr
[13]);
356 con_printf(sys
->con
, "FR 14 = %016llX %016llX\n",
357 sys
->task
->cpu
->regs
.fpr
[14],
358 sys
->task
->cpu
->regs
.fpr
[15]);
365 *! \tok{\sc Display} \tok{\sc Cr}
369 *! Displays the guest's control registers
371 static int cmd_display_cr(struct virt_sys
*sys
, char *cmd
, int len
)
373 SHELL_CMD_AUTH(sys
, G
);
375 con_printf(sys
->con
, "CR 0 = %016llX %016llX\n",
376 sys
->task
->cpu
->sie_cb
.gcr
[0],
377 sys
->task
->cpu
->sie_cb
.gcr
[1]);
378 con_printf(sys
->con
, "CR 2 = %016llX %016llX\n",
379 sys
->task
->cpu
->sie_cb
.gcr
[2],
380 sys
->task
->cpu
->sie_cb
.gcr
[3]);
381 con_printf(sys
->con
, "CR 4 = %016llX %016llX\n",
382 sys
->task
->cpu
->sie_cb
.gcr
[4],
383 sys
->task
->cpu
->sie_cb
.gcr
[5]);
384 con_printf(sys
->con
, "CR 6 = %016llX %016llX\n",
385 sys
->task
->cpu
->sie_cb
.gcr
[6],
386 sys
->task
->cpu
->sie_cb
.gcr
[7]);
387 con_printf(sys
->con
, "CR 8 = %016llX %016llX\n",
388 sys
->task
->cpu
->sie_cb
.gcr
[8],
389 sys
->task
->cpu
->sie_cb
.gcr
[9]);
390 con_printf(sys
->con
, "CR 10 = %016llX %016llX\n",
391 sys
->task
->cpu
->sie_cb
.gcr
[10],
392 sys
->task
->cpu
->sie_cb
.gcr
[11]);
393 con_printf(sys
->con
, "CR 12 = %016llX %016llX\n",
394 sys
->task
->cpu
->sie_cb
.gcr
[12],
395 sys
->task
->cpu
->sie_cb
.gcr
[13]);
396 con_printf(sys
->con
, "CR 14 = %016llX %016llX\n",
397 sys
->task
->cpu
->sie_cb
.gcr
[14],
398 sys
->task
->cpu
->sie_cb
.gcr
[15]);
405 *! \tok{\sc Display} \tok{\sc Ar}
409 *! Displays the guest's access registers
411 static int cmd_display_ar(struct virt_sys
*sys
, char *cmd
, int len
)
413 SHELL_CMD_AUTH(sys
, G
);
415 con_printf(sys
->con
, "AR 0 = %08X %08X\n",
416 sys
->task
->cpu
->regs
.ar
[0],
417 sys
->task
->cpu
->regs
.ar
[1]);
418 con_printf(sys
->con
, "AR 2 = %08X %08X\n",
419 sys
->task
->cpu
->regs
.ar
[2],
420 sys
->task
->cpu
->regs
.ar
[3]);
421 con_printf(sys
->con
, "AR 4 = %08X %08X\n",
422 sys
->task
->cpu
->regs
.ar
[4],
423 sys
->task
->cpu
->regs
.ar
[5]);
424 con_printf(sys
->con
, "AR 6 = %08X %08X\n",
425 sys
->task
->cpu
->regs
.ar
[6],
426 sys
->task
->cpu
->regs
.ar
[7]);
427 con_printf(sys
->con
, "AR 8 = %08X %08X\n",
428 sys
->task
->cpu
->regs
.ar
[8],
429 sys
->task
->cpu
->regs
.ar
[9]);
430 con_printf(sys
->con
, "AR 10 = %08X %08X\n",
431 sys
->task
->cpu
->regs
.ar
[10],
432 sys
->task
->cpu
->regs
.ar
[11]);
433 con_printf(sys
->con
, "AR 12 = %08X %08X\n",
434 sys
->task
->cpu
->regs
.ar
[12],
435 sys
->task
->cpu
->regs
.ar
[13]);
436 con_printf(sys
->con
, "AR 14 = %08X %08X\n",
437 sys
->task
->cpu
->regs
.ar
[14],
438 sys
->task
->cpu
->regs
.ar
[15]);
442 static void __d_psw(struct virt_sys
*sys
, int zarch
, char *name
,
443 u64 obase
, u64 nbase
, u32
*odata
, u32
*ndata
, int idx
)
446 con_printf(sys
->con
, "%s %04X %3llX OLD %08X %08X %08X %08X\n",
447 name
, 0xffff, obase
+(idx
*16),
448 odata
[0+(idx
*4)], odata
[1+(idx
*4)],
449 odata
[2+(idx
*4)], odata
[3+(idx
*4)]);
450 con_printf(sys
->con
, " %3llX NEW %08X %08X %08X %08X\n",
452 ndata
[0+(idx
*4)], ndata
[1+(idx
*4)],
453 ndata
[2+(idx
*4)], ndata
[3+(idx
*4)]);
455 con_printf(sys
->con
, "%s %04X %3llX OLD %08X %08X\n",
456 name
, 0xffff, obase
+(idx
*8),
457 odata
[0+(idx
*2)], odata
[1+(idx
*2)]);
458 con_printf(sys
->con
, " %3llX NEW %08X %08X\n",
460 ndata
[0+(idx
*2)], ndata
[1+(idx
*2)]);
478 *! \tok{\sc Display} \tok{\sc PSW}
482 *! Displays the guest's PSW.
485 *! If the guest is in ESA/390 mode, the 8-byte PSW is displayed.
487 *! If the guest is in z/Architecture mode, the 16-byte PSW is displayed.
490 static int cmd_display_psw(struct virt_sys
*sys
, char *cmd
, int len
)
492 u32 odata
[6*sizeof(struct psw
)/sizeof(u32
)];
493 u32 ndata
[6*sizeof(struct psw
)/sizeof(u32
)];
500 SHELL_CMD_AUTH(sys
, G
);
502 if (!strcasecmp(cmd
, "ALL"))
504 else if (!strcasecmp(cmd
, "RST"))
506 else if (!strcasecmp(cmd
, "EXT"))
508 else if (!strcasecmp(cmd
, "SVC"))
510 else if (!strcasecmp(cmd
, "PRG"))
512 else if (!strcasecmp(cmd
, "MCH"))
514 else if (!strcasecmp(cmd
, "I/O"))
519 zarch
= VCPU_ZARCH(sys
->task
->cpu
);
521 if (disp
& D_PSW_CUR
) {
522 u32
*ptr
= (u32
*) &sys
->task
->cpu
->sie_cb
.gpsw
;
524 con_printf(sys
->con
, "PSW = %08X %08X %08X %08X\n",
525 ptr
[0], ptr
[1], ptr
[2], ptr
[3]);
527 con_printf(sys
->con
, "PSW = %08X %08X\n",
539 glen
= sizeof(struct psw
) * 6;
540 oret
= memcpy_from_guest(obase
, odata
, &glen
);
541 glen
= sizeof(struct psw
) * 6;
542 nret
= memcpy_from_guest(nbase
, ndata
, &glen
);
545 con_printf(sys
->con
, "Failed to fetch old/new PSWs from "
547 return oret
? oret
: nret
;
550 if (disp
& D_PSW_RST
)
551 __d_psw(sys
, zarch
, "RST", obase
, nbase
, odata
, ndata
, 0);
552 if (disp
& D_PSW_EXT
)
553 __d_psw(sys
, zarch
, "EXT", obase
, nbase
, odata
, ndata
, 1);
554 if (disp
& D_PSW_SVC
)
555 __d_psw(sys
, zarch
, "SVC", obase
, nbase
, odata
, ndata
, 2);
556 if (disp
& D_PSW_PRG
)
557 __d_psw(sys
, zarch
, "PRG", obase
, nbase
, odata
, ndata
, 3);
558 if (disp
& D_PSW_MCH
)
559 __d_psw(sys
, zarch
, "MCH", obase
, nbase
, odata
, ndata
, 4);
561 __d_psw(sys
, zarch
, "I/O", obase
, nbase
, odata
, ndata
, 5);
566 static void __do_display_schib(struct console
*con
, struct virt_device
*vdev
)
568 con_printf(con
, "%05X %04X %08X %d %02X %02X %02X %02X %02X "
569 "---- %02X %02X %02X%02X%02X%02X %02X%02X%02X%02X\n",
570 vdev
->sch
, vdev
->pmcw
.dev_num
, vdev
->pmcw
.interrupt_param
,
571 vdev
->pmcw
.isc
, ((vdev
->pmcw
.e
<< 7) |
572 (vdev
->pmcw
.lm
<< 5) |
573 (vdev
->pmcw
.mm
<< 3) |
574 (vdev
->pmcw
.d
<< 2) |
575 (vdev
->pmcw
.t
<< 1) |
577 vdev
->pmcw
.lpm
, vdev
->pmcw
.pnom
, vdev
->pmcw
.lpum
,
580 vdev
->pmcw
.pom
, vdev
->pmcw
.pam
,
581 vdev
->pmcw
.chpid
[0], vdev
->pmcw
.chpid
[1],
582 vdev
->pmcw
.chpid
[2], vdev
->pmcw
.chpid
[3],
583 vdev
->pmcw
.chpid
[4], vdev
->pmcw
.chpid
[5],
584 vdev
->pmcw
.chpid
[6], vdev
->pmcw
.chpid
[7]);
590 *! \tok{\sc Display} \tok{\sc SCHIB}
591 *! \begin{stack} \tok{ALL} \\ <schib> \end{stack}
595 *! Displays the guest's subchannel control block information
597 static int cmd_display_schib(struct virt_sys
*sys
, char *cmd
, int len
)
599 struct virt_device
*vdev
;
603 SHELL_CMD_AUTH(sys
, G
);
605 if (strcasecmp(cmd
, "ALL")) {
606 cmd
= __extract_hex(cmd
, &sch
);
610 /* sch number must be: X'0001____' */
611 if ((sch
& 0xffff0000) != 0x00010000)
618 /* find the virtual device */
620 for_each_vdev(sys
, vdev
) {
621 if ((vdev
->sch
== (u32
) sch
) || all
) {
622 if (!all
|| all
== 1) {
623 con_printf(sys
->con
, "SCHIB DEV INT-PARM ISC FLG LP "
624 "PNO LPU PI MBI PO PA CHPID0-3 CHPID4-7\n");
628 __do_display_schib(sys
->con
, vdev
);
638 static struct cpcmd cmd_tbl_display
[] = {
639 {"AR", cmd_display_ar
, NULL
},
640 {"A", cmd_display_ar
, NULL
},
642 {"CR", cmd_display_cr
, NULL
},
643 {"C", cmd_display_cr
, NULL
},
645 {"FPCR", cmd_display_fpcr
, NULL
},
647 {"FPR", cmd_display_fpr
, NULL
},
648 {"FP", cmd_display_fpr
, NULL
},
649 {"F", cmd_display_fpr
, NULL
},
651 {"GPR", cmd_display_gpr
, NULL
},
652 {"GP", cmd_display_gpr
, NULL
},
653 {"G", cmd_display_gpr
, NULL
},
655 {"PSW", cmd_display_psw
, NULL
},
657 {"SCHIB", cmd_display_schib
, NULL
},
659 {"SIECB", cmd_display_siecb
, NULL
},
661 {"STORAGE", cmd_display_storage
, NULL
},
662 {"STORAG", cmd_display_storage
, NULL
},
663 {"STORA", cmd_display_storage
, NULL
},
664 {"STOR", cmd_display_storage
, NULL
},
665 {"STO", cmd_display_storage
, NULL
},