loader: remove shouting from ORB's variable name
[hvf.git] / cp / shell / cmd_display.c
blobc5caf3067f2807d3088113888a7eccd65308bcf9
1 /*
2 * (C) Copyright 2007-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
5 * details.
6 */
8 static char* parse_addrspec(u64 *val, u64 *len, char *s)
10 u64 tmp;
11 bool parsed = false;
13 tmp = 0;
14 while(!(*s == '\0' ||
15 *s == ' ' ||
16 *s == '\t')) {
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)
23 break;
24 else
25 return ERR_PTR(-EINVAL);
27 s++;
28 parsed = true;
31 if (len) {
32 *len = 0;
33 if (*s == '.') {
34 s = __extract_hex(s+1, len);
35 if (IS_ERR(s))
36 parsed = false;
40 *val = tmp;
42 return (parsed ? s : ERR_PTR(-EINVAL));
45 enum display_fmt {
46 FMT_NUMERIC = 0,
47 FMT_INSTRUCT,
50 static void __display_storage_instruct(struct virt_sys *sys, u64 guest_addr,
51 u64 mlen)
53 int ret;
54 char buf[64];
55 int ilen;
56 u64 val;
57 u64 host_addr;
59 u64 end_addr;
61 /* walk the page tables to find the real page frame */
62 ret = virt2phy_current(guest_addr, &host_addr);
63 if (ret) {
64 con_printf(sys->con, "DISPLAY: Specified address is not part of "
65 "guest configuration (RC=%d,%d)\n", -EFAULT, ret);
66 return;
69 if (!mlen)
70 mlen = 1;
72 end_addr = guest_addr + mlen;
74 while(guest_addr < end_addr) {
76 * FIXME: make sure crossing page-boundary doesn't break
77 * give us garbage
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");
84 break;
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%016lX %0*lX%*s %s\n", guest_addr,
91 2*ilen, val, /* inst hex dump */
92 12-2*ilen, "", /* spacer */
93 buf);
95 host_addr += ilen;
96 guest_addr += ilen;
100 static void __display_storage_numeric(struct virt_sys *sys, u64 guest_addr,
101 u64 mlen)
103 char buf[80];
104 char *bp;
106 u64 host_addr;
107 int this_len;
109 int ret;
111 /* round down */
112 guest_addr &= ~((u64) 0x3);
114 /* walk the page tables to find the real page frame */
115 ret = virt2phy_current(guest_addr, &host_addr);
116 if (ret)
117 goto fault;
119 if (mlen > 4)
120 mlen = (mlen >> 2) + !!(mlen & 0x3);
121 else
122 mlen = 1;
124 while(mlen && !ret) {
125 this_len = (mlen > 4) ? 4 : mlen;
127 mlen -= this_len;
129 bp = buf;
130 bp += snprintf(bp, 80, "R%016lX ", guest_addr);
132 while(this_len) {
133 bp += snprintf(bp, 80 - (bp - buf), "%08X ",
134 *(u32*)host_addr);
136 guest_addr += 4;
137 host_addr += 4;
138 this_len--;
140 /* loop if we're not crossing a page, or if we're done */
141 if (((guest_addr & PAGE_MASK) != 0) || !mlen)
142 continue;
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);
150 if (ret)
151 break;
154 con_printf(sys->con, "%s\n", buf);
157 fault:
158 if (ret)
159 con_printf(sys->con, "DISPLAY: The address %016lX is not part of "
160 "guest configuration (RC=%d,%d)\n", guest_addr, -EFAULT, ret);
164 *!!! DISPLAY STORAGE
165 *!! SYNTAX
166 *! \tok{\sc Display} \tok{\sc STOrage}
167 *! \begin{stack} \\ \deftok{N} \\ \tok{I} \end{stack}
168 *! <addr>
169 *! \begin{stack} \\ \tok{.} <length> \end{stack}
170 *!! XATNYS
171 *!! AUTH G
172 *!! PURPOSE
173 *! Displays a portion of guest's storage.
174 *!! OPERANDS
175 *! \cbstart
176 *! \item[addr] is the guest storage address.
177 *! \item[length] is the number of bytes to display. If not specified, 4 is
178 *! assumed.
179 *! \cbend
180 *!! SDNAREPO
181 *!! OPTIONS
182 *! \cbstart
183 *! \item[N] display guest storage in numeric format.
184 *! \item[I] display guest storage in instruction format.
185 *! \cbend
186 *!! SNOITPO
187 *!! NOTES
188 *! \cbstart
189 *! \item Currently, the instruction display does not support page-boundary
190 *! crossing.
191 *! \cbend
192 *!! SETON
193 *!! EXAMPLES
194 *! D STO 200\\
195 *! D STO N200.10\\
196 *! D STO I1234.200
198 static int cmd_display_storage(struct virt_sys *sys, char *cmd, int len)
200 u64 guest_addr;
201 u64 mlen = 0;
202 enum display_fmt fmt;
204 SHELL_CMD_AUTH(sys, G);
206 switch (cmd[0]) {
207 case 'N': case 'n':
208 /* numeric */
209 cmd++;
210 fmt = FMT_NUMERIC;
211 break;
212 case 'I': case 'i':
213 /* instruction */
214 cmd++;
215 fmt = FMT_INSTRUCT;
216 break;
217 default:
218 /* numeric */
219 fmt = FMT_NUMERIC;
220 break;
223 cmd = parse_addrspec(&guest_addr, &mlen, cmd);
224 if (IS_ERR(cmd)) {
225 con_printf(sys->con, "DISPLAY: Invalid addr-spec\n");
226 return 0;
229 if (fmt == FMT_INSTRUCT)
230 __display_storage_instruct(sys, guest_addr, mlen);
231 else
232 __display_storage_numeric(sys, guest_addr, mlen);
234 return 0;
238 *!!! DISPLAY SIECB
239 *!! SYNTAX
240 *! \tok{\sc Display} \tok{\sc SIECB}
241 *!! XATNYS
242 *!! AUTH E
243 *!! PURPOSE
244 *! Displays hexdump of the guest's SIE control block.
246 static int cmd_display_siecb(struct virt_sys *sys, char *cmd, int len)
248 u32 *val;
249 int i;
251 SHELL_CMD_AUTH(sys, E);
253 val = (u32*) &sys->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],
260 val[i+3]);
262 return 0;
266 *!!! DISPLAY GPR
267 *!! SYNTAX
268 *! \tok{\sc Display} \tok{\sc Gpr}
269 *!! XATNYS
270 *!! AUTH G
271 *!! PURPOSE
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 = %016lX %016lX\n",
279 sys->cpu->regs.gpr[0],
280 sys->cpu->regs.gpr[1]);
281 con_printf(sys->con, "GR 2 = %016lX %016lX\n",
282 sys->cpu->regs.gpr[2],
283 sys->cpu->regs.gpr[3]);
284 con_printf(sys->con, "GR 4 = %016lX %016lX\n",
285 sys->cpu->regs.gpr[4],
286 sys->cpu->regs.gpr[5]);
287 con_printf(sys->con, "GR 6 = %016lX %016lX\n",
288 sys->cpu->regs.gpr[6],
289 sys->cpu->regs.gpr[7]);
290 con_printf(sys->con, "GR 8 = %016lX %016lX\n",
291 sys->cpu->regs.gpr[8],
292 sys->cpu->regs.gpr[9]);
293 con_printf(sys->con, "GR 10 = %016lX %016lX\n",
294 sys->cpu->regs.gpr[10],
295 sys->cpu->regs.gpr[11]);
296 con_printf(sys->con, "GR 12 = %016lX %016lX\n",
297 sys->cpu->regs.gpr[12],
298 sys->cpu->regs.gpr[13]);
299 con_printf(sys->con, "GR 14 = %016lX %016lX\n",
300 sys->cpu->regs.gpr[14],
301 sys->cpu->regs.gpr[15]);
302 return 0;
306 *!!! DISPLAY FPCR
307 *!! SYNTAX
308 *! \tok{\sc Display} \tok{\sc FPCR}
309 *!! XATNYS
310 *!! AUTH G
311 *!! PURPOSE
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->cpu->regs.fpcr);
319 return 0;
323 *!!! DISPLAY FPR
324 *!! SYNTAX
325 *! \tok{\sc Display} \tok{\sc Fpr}
326 *!! XATNYS
327 *!! AUTH G
328 *!! PURPOSE
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 = %016lX %016lX\n",
336 sys->cpu->regs.fpr[0],
337 sys->cpu->regs.fpr[1]);
338 con_printf(sys->con, "FR 2 = %016lX %016lX\n",
339 sys->cpu->regs.fpr[2],
340 sys->cpu->regs.fpr[3]);
341 con_printf(sys->con, "FR 4 = %016lX %016lX\n",
342 sys->cpu->regs.fpr[4],
343 sys->cpu->regs.fpr[5]);
344 con_printf(sys->con, "FR 6 = %016lX %016lX\n",
345 sys->cpu->regs.fpr[6],
346 sys->cpu->regs.fpr[7]);
347 con_printf(sys->con, "FR 8 = %016lX %016lX\n",
348 sys->cpu->regs.fpr[8],
349 sys->cpu->regs.fpr[9]);
350 con_printf(sys->con, "FR 10 = %016lX %016lX\n",
351 sys->cpu->regs.fpr[10],
352 sys->cpu->regs.fpr[11]);
353 con_printf(sys->con, "FR 12 = %016lX %016lX\n",
354 sys->cpu->regs.fpr[12],
355 sys->cpu->regs.fpr[13]);
356 con_printf(sys->con, "FR 14 = %016lX %016lX\n",
357 sys->cpu->regs.fpr[14],
358 sys->cpu->regs.fpr[15]);
359 return 0;
363 *!!! DISPLAY CR
364 *!! SYNTAX
365 *! \tok{\sc Display} \tok{\sc Cr}
366 *!! XATNYS
367 *!! AUTH G
368 *!! PURPOSE
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 = %016lX %016lX\n",
376 sys->cpu->sie_cb.gcr[0],
377 sys->cpu->sie_cb.gcr[1]);
378 con_printf(sys->con, "CR 2 = %016lX %016lX\n",
379 sys->cpu->sie_cb.gcr[2],
380 sys->cpu->sie_cb.gcr[3]);
381 con_printf(sys->con, "CR 4 = %016lX %016lX\n",
382 sys->cpu->sie_cb.gcr[4],
383 sys->cpu->sie_cb.gcr[5]);
384 con_printf(sys->con, "CR 6 = %016lX %016lX\n",
385 sys->cpu->sie_cb.gcr[6],
386 sys->cpu->sie_cb.gcr[7]);
387 con_printf(sys->con, "CR 8 = %016lX %016lX\n",
388 sys->cpu->sie_cb.gcr[8],
389 sys->cpu->sie_cb.gcr[9]);
390 con_printf(sys->con, "CR 10 = %016lX %016lX\n",
391 sys->cpu->sie_cb.gcr[10],
392 sys->cpu->sie_cb.gcr[11]);
393 con_printf(sys->con, "CR 12 = %016lX %016lX\n",
394 sys->cpu->sie_cb.gcr[12],
395 sys->cpu->sie_cb.gcr[13]);
396 con_printf(sys->con, "CR 14 = %016lX %016lX\n",
397 sys->cpu->sie_cb.gcr[14],
398 sys->cpu->sie_cb.gcr[15]);
399 return 0;
403 *!!! DISPLAY AR
404 *!! SYNTAX
405 *! \tok{\sc Display} \tok{\sc Ar}
406 *!! XATNYS
407 *!! AUTH G
408 *!! PURPOSE
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->cpu->regs.ar[0],
417 sys->cpu->regs.ar[1]);
418 con_printf(sys->con, "AR 2 = %08X %08X\n",
419 sys->cpu->regs.ar[2],
420 sys->cpu->regs.ar[3]);
421 con_printf(sys->con, "AR 4 = %08X %08X\n",
422 sys->cpu->regs.ar[4],
423 sys->cpu->regs.ar[5]);
424 con_printf(sys->con, "AR 6 = %08X %08X\n",
425 sys->cpu->regs.ar[6],
426 sys->cpu->regs.ar[7]);
427 con_printf(sys->con, "AR 8 = %08X %08X\n",
428 sys->cpu->regs.ar[8],
429 sys->cpu->regs.ar[9]);
430 con_printf(sys->con, "AR 10 = %08X %08X\n",
431 sys->cpu->regs.ar[10],
432 sys->cpu->regs.ar[11]);
433 con_printf(sys->con, "AR 12 = %08X %08X\n",
434 sys->cpu->regs.ar[12],
435 sys->cpu->regs.ar[13]);
436 con_printf(sys->con, "AR 14 = %08X %08X\n",
437 sys->cpu->regs.ar[14],
438 sys->cpu->regs.ar[15]);
439 return 0;
442 static void __d_psw(struct virt_sys *sys, int zarch, char *name,
443 u64 obase, u64 nbase, u32 *odata, u32 *ndata, int idx)
445 if (zarch) {
446 con_printf(sys->con, "%s %04X %3lX 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, " %3lX NEW %08X %08X %08X %08X\n",
451 nbase+(idx*16),
452 ndata[0+(idx*4)], ndata[1+(idx*4)],
453 ndata[2+(idx*4)], ndata[3+(idx*4)]);
454 } else {
455 con_printf(sys->con, "%s %04X %3lX OLD %08X %08X\n",
456 name, 0xffff, obase+(idx*8),
457 odata[0+(idx*2)], odata[1+(idx*2)]);
458 con_printf(sys->con, " %3lX NEW %08X %08X\n",
459 nbase+(idx*8),
460 ndata[0+(idx*2)], ndata[1+(idx*2)]);
464 enum {
465 D_PSW_CUR = 0x01,
466 D_PSW_EXT = 0x02,
467 D_PSW_SVC = 0x04,
468 D_PSW_PRG = 0x08,
469 D_PSW_MCH = 0x10,
470 D_PSW_IO = 0x20,
471 D_PSW_RST = 0x40,
473 D_PSW_ALL = 0x7f,
476 *!!! DISPLAY PSW
477 *!! SYNTAX
478 *! \tok{\sc Display} \tok{\sc PSW}
479 *!! XATNYS
480 *!! AUTH G
481 *!! PURPOSE
482 *! Displays the guest's PSW.
484 *! \cbstart
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.
488 *! \cbend
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)];
494 u64 obase, nbase;
495 u64 glen;
496 int oret, nret;
497 int disp = 0;
498 int zarch;
500 SHELL_CMD_AUTH(sys, G);
502 if (!strcasecmp(cmd, "ALL"))
503 disp = D_PSW_ALL;
504 else if (!strcasecmp(cmd, "RST"))
505 disp = D_PSW_RST;
506 else if (!strcasecmp(cmd, "EXT"))
507 disp = D_PSW_EXT;
508 else if (!strcasecmp(cmd, "SVC"))
509 disp = D_PSW_SVC;
510 else if (!strcasecmp(cmd, "PRG"))
511 disp = D_PSW_PRG;
512 else if (!strcasecmp(cmd, "MCH"))
513 disp = D_PSW_MCH;
514 else if (!strcasecmp(cmd, "I/O"))
515 disp = D_PSW_IO;
516 else
517 disp = D_PSW_CUR;
519 zarch = VCPU_ZARCH(sys->cpu);
521 if (disp & D_PSW_CUR) {
522 u32 *ptr = (u32*) &sys->cpu->sie_cb.gpsw;
523 if (zarch)
524 con_printf(sys->con, "PSW = %08X %08X %08X %08X\n",
525 ptr[0], ptr[1], ptr[2], ptr[3]);
526 else
527 con_printf(sys->con, "PSW = %08X %08X\n",
528 ptr[0], ptr[1]);
531 if (zarch) {
532 obase = 0x120;
533 nbase = 0x1A0;
534 } else {
535 obase = 0x18;
536 nbase = 0x58;
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);
544 if (oret || nret) {
545 con_printf(sys->con, "Failed to fetch old/new PSWs from "
546 "guest storage\n");
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);
560 if (disp & D_PSW_IO)
561 __d_psw(sys, zarch, "I/O", obase, nbase, odata, ndata, 5);
563 return 0;
566 static void __do_display_schib(struct virt_cons *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) |
576 (vdev->pmcw.v)),
577 vdev->pmcw.lpm, vdev->pmcw.pnom, vdev->pmcw.lpum,
578 vdev->pmcw.pim,
579 /* MBI */
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]);
588 *!!! DISPLAY SCHIB
589 *!! SYNTAX
590 *! \tok{\sc Display} \tok{\sc SCHIB}
591 *! \begin{stack} \tok{ALL} \\ <schib> \end{stack}
592 *!! XATNYS
593 *!! AUTH G
594 *!! PURPOSE
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;
600 u64 sch;
601 int all;
603 SHELL_CMD_AUTH(sys, G);
605 if (strcasecmp(cmd, "ALL")) {
606 cmd = __extract_hex(cmd, &sch);
607 if (IS_ERR(cmd))
608 return PTR_ERR(cmd);
610 /* sch number must be: X'0001____' */
611 if ((sch & 0xffff0000) != 0x00010000)
612 return -EINVAL;
614 all = 0;
615 } else
616 all = 1;
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");
625 all = (all ? 2 : 0);
628 __do_display_schib(sys->con, vdev);
630 if (!all)
631 break;
635 return 0;
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},
666 {"", NULL, NULL},