1 /*
2 * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public
14 * License along with this program; If not, see <http://www.gnu.org/licenses/>.
15 */
16
17
18 /* This file to impelement functions that run interactively and don't
19 * involve remote gdb. Eg, print vcpu context and exit. */
20
21 #include <stdio.h>
22 #include <stdint.h>
23 #include <stdarg.h>
24 #include <inttypes.h>
25 #include <errno.h>
26
27 #include "gx.h"
28
29 extern vcpuid_t max_vcpuid;
30 extern int guest_bitness;
31
32 static void
prnt_32regs(struct xg_gdb_regs32 * r32p)33 prnt_32regs(struct xg_gdb_regs32 *r32p)
34 {
35 printf("eip:%08x esp:%08x flags:%08x\n", r32p->eip, r32p->esp,
36 r32p->eflags);
37 printf("eax:%08x ebx:%08x ecx:%08x edx:%08x\n", r32p->eax,
38 r32p->ebx, r32p->ecx, r32p->edx);
39 printf("esi:%08x edi:%08x ebp:%08x\n", r32p->esi, r32p->edi,
40 r32p->ebp);
41 printf("cs:%x ds:%x fs:%x gs:%x\n", r32p->cs, r32p->ds, r32p->fs,
42 r32p->gs);
43 printf("\n");
44 }
45
46 static void
prnt_64regs(struct xg_gdb_regs64 * r64p)47 prnt_64regs(struct xg_gdb_regs64 *r64p)
48 {
49 printf("rip:%016"PRIx64" rsp:%016"PRIx64" flags:%08x\n", r64p->rip, r64p->rsp,
50 r64p->eflags);
51 printf("rax:%016"PRIx64" rbx:%016"PRIx64" rcx:%016"PRIx64"\n", r64p->rax, r64p->rbx,
52 r64p->rcx);
53 printf("rdx:%016"PRIx64" rsi:%016"PRIx64" rdi:%016"PRIx64"\n", r64p->rdx, r64p->rsi,
54 r64p->rdi);
55 printf("r08:%016"PRIx64" r09:%016"PRIx64" r10:%016"PRIx64"\n", r64p->r8, r64p->r9,
56 r64p->r10);
57 printf("r11:%016"PRIx64" r12:%016"PRIx64" r13:%016"PRIx64"\n", r64p->r11, r64p->r12,
58 r64p->r13);
59 printf("r14:%016"PRIx64" r15:%016"PRIx64" rbp:%016"PRIx64"\n", r64p->r14, r64p->r15,
60 r64p->rbp);
61 printf("cs:%08x ds:%08x fs:%08x gs:%08x\n", r64p->cs,
62 r64p->ds, r64p->fs, r64p->gs);
63 printf("\n");
64 }
65
66
67 static void
prnt_call_trace32(uint32_t ip,uint32_t sp)68 prnt_call_trace32(uint32_t ip, uint32_t sp)
69 {
70 int stack_max=10; /* try to print upto 10 entries if possible */
71 uint32_t loopmax=0, val;
72
73 printf("Call Trace:\n");
74 printf(" [%08x]\n", ip);
75
76 while(stack_max > 0) {
77 if (xg_read_mem((uint64_t)sp, (char *)&val, sizeof(val),0) != 0)
78 return;
79 if (val > 0x0c000000) { /* kernel addr */
80 printf(" [%08x]\n", val);
81 --stack_max;
82 }
83 sp += sizeof(sp);
84 if (++loopmax > 10000) /* don't go forever */
85 break;
86 }
87 }
88
89 static void
prnt_call_trace64(uint64_t ip,uint64_t sp)90 prnt_call_trace64(uint64_t ip, uint64_t sp)
91 {
92 int stack_max=10; /* try to print upto 10 entries if possible */
93 uint64_t loopmax=0, val;
94
95 printf("Call Trace:\n");
96 printf(" [%016"PRIx64"]\n", ip);
97
98 while(stack_max > 0) {
99 if (xg_read_mem(sp, (char *)&val, sizeof(val),0) != 0)
100 return;
101 if (val > 0xffffffff80000000UL) { /* kernel addr */
102 printf(" [%016"PRIx64"]\n", val);
103 --stack_max;
104 }
105 sp += sizeof(sp);
106 if (++loopmax > 10000) /* don't go forever */
107 break;
108 }
109 }
110
111 static int
prnt_vcpu_context(vcpuid_t vcpuid)112 prnt_vcpu_context(vcpuid_t vcpuid)
113 {
114 union xg_gdb_regs gregs;
115 int rc;
116
117 printf("\n--> VCPU:%d\n", vcpuid);
118 rc = xg_regs_read(XG_GPRS, vcpuid, &gregs, guest_bitness);
119 if (rc) {
120 gxprt("ERROR: failed to read regs. errno:%d\n", errno);
121 return 1;
122 }
123 if (guest_bitness==32) {
124 prnt_32regs(&gregs.gregs_32);
125 prnt_call_trace32(gregs.gregs_32.eip, gregs.gregs_32.esp);
126 } else {
127 prnt_64regs(&gregs.gregs_64);
128 prnt_call_trace64(gregs.gregs_64.rip, gregs.gregs_64.rsp);
129 }
130 return 0;
131 }
132
133 /* vcpuid is already checked to be <= max_vcpuid */
134 int
gx_local_cmd(domid_t domid,vcpuid_t vcpuid)135 gx_local_cmd(domid_t domid, vcpuid_t vcpuid)
136 {
137 printf("===> Context for DOMID:%d\n", domid);
138 if (vcpuid == -1) {
139 int i;
140 for (i=0; i <= max_vcpuid; i++)
141 prnt_vcpu_context(i);
142 } else
143 prnt_vcpu_context(vcpuid);
144 return 0;
145 }
146