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 <errno.h>
25 
26 #include "gx.h"
27 
28 extern vcpuid_t max_vcpuid;
29 extern int guest_bitness;
30 
31 static void
prnt_32regs(struct xg_gdb_regs32 * r32p)32 prnt_32regs(struct xg_gdb_regs32 *r32p)
33 {
34     printf("eip:%08x esp:%08x flags:%08x\n", r32p->eip, r32p->esp,
35            r32p->eflags);
36     printf("eax:%08x ebx:%08x ecx:%08x edx:%08x\n", r32p->eax,
37            r32p->ebx, r32p->ecx, r32p->edx);
38     printf("esi:%08x edi:%08x ebp:%08x\n", r32p->esi, r32p->edi,
39            r32p->ebp);
40     printf("cs:%x ds:%x fs:%x gs:%x\n", r32p->cs, r32p->ds, r32p->fs,
41            r32p->gs);
42     printf("\n");
43 }
44 
45 static void
prnt_64regs(struct xg_gdb_regs64 * r64p)46 prnt_64regs(struct xg_gdb_regs64 *r64p)
47 {
48     printf("rip:"XGF64" rsp:"XGF64" flags:"XGF64"\n", r64p->rip, r64p->rsp,
49            r64p->rflags);
50     printf("rax:"XGF64" rbx:"XGF64" rcx:"XGF64"\n", r64p->rax, r64p->rbx,
51            r64p->rcx);
52     printf("rdx:"XGF64" rsi:"XGF64" rdi:"XGF64"\n", r64p->rdx, r64p->rsi,
53            r64p->rdi);
54     printf("r08:"XGF64" r09:"XGF64" r10:"XGF64"\n", r64p->r8, r64p->r9,
55            r64p->r10);
56     printf("r11:"XGF64" r12:"XGF64" r13:"XGF64"\n", r64p->r11, r64p->r12,
57            r64p->r13);
58     printf("r14:"XGF64" r15:"XGF64" rbp:"XGF64"\n", r64p->r14, r64p->r15,
59            r64p->rbp);
60     printf("cs:"XGF64" ds:"XGF64" fs:"XGF64" gs:"XGF64"\n", r64p->cs,
61            r64p->ds, r64p->fs, r64p->gs);
62     printf("\n");
63 }
64 
65 
66 static void
prnt_call_trace32(uint32_t ip,uint32_t sp)67 prnt_call_trace32(uint32_t ip, uint32_t sp)
68 {
69     int stack_max=10;        /* try to print upto 10 entries if possible */
70     uint32_t loopmax=0, val;
71 
72     printf("Call Trace:\n");
73     printf("   [%08x]\n", ip);
74 
75     while(stack_max > 0) {
76         if (xg_read_mem((uint64_t)sp, (char *)&val, sizeof(val),0) != 0)
77             return;
78         if (val > 0x0c000000) {              /* kernel addr */
79             printf("   [%08x]\n", val);
80             --stack_max;
81         }
82         sp += sizeof(sp);
83         if (++loopmax > 10000)               /* don't go forever */
84             break;
85     }
86 }
87 
88 static void
prnt_call_trace64(uint64_t ip,uint64_t sp)89 prnt_call_trace64(uint64_t ip, uint64_t sp)
90 {
91     int stack_max=10;        /* try to print upto 10 entries if possible */
92     uint64_t loopmax=0, val;
93 
94     printf("Call Trace:\n");
95     printf("   ["XGF64"]\n", ip);
96 
97     while(stack_max > 0) {
98         if (xg_read_mem(sp, (char *)&val, sizeof(val),0) != 0)
99             return;
100         if (val > 0xffffffff80000000UL) {    /* kernel addr */
101             printf("   ["XGF64"]\n", val);
102             --stack_max;
103         }
104         sp += sizeof(sp);
105         if (++loopmax > 10000)               /* don't go forever */
106             break;
107     }
108 }
109 
110 static int
prnt_vcpu_context(vcpuid_t vcpuid)111 prnt_vcpu_context(vcpuid_t vcpuid)
112 {
113     union xg_gdb_regs gregs;
114     int rc;
115 
116     printf("\n--> VCPU:%d\n", vcpuid);
117     rc = xg_regs_read(XG_GPRS, vcpuid, &gregs, guest_bitness);
118     if (rc) {
119         gxprt("ERROR: failed to read regs. errno:%d\n", errno);
120         return 1;
121     }
122     if (guest_bitness==32) {
123         prnt_32regs(&gregs.gregs_32);
124         prnt_call_trace32(gregs.gregs_32.eip, gregs.gregs_32.esp);
125     } else {
126         prnt_64regs(&gregs.gregs_64);
127         prnt_call_trace64(gregs.gregs_64.rip, gregs.gregs_64.rsp);
128     }
129     return 0;
130 }
131 
132 /* vcpuid is already checked to be <= max_vcpuid */
133 int
gx_local_cmd(domid_t domid,vcpuid_t vcpuid)134 gx_local_cmd(domid_t domid, vcpuid_t vcpuid)
135 {
136     printf("===> Context for DOMID:%d\n", domid);
137     if (vcpuid == -1) {
138         int i;
139         for (i=0; i <= max_vcpuid; i++)
140             prnt_vcpu_context(i);
141     } else
142         prnt_vcpu_context(vcpuid);
143     return 0;
144 }
145