source: trunk/packages/xen-3.1/xen-3.1/xen/arch/ia64/xen/gdbstub.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 21.0 KB
Line 
1/*
2 * ia64-specific cdb routines
3 * cdb xen/ia64 by Isaku Yamahta <yamahata at valinux co jp>
4 *                 VA Linux Systems Japan K.K.
5 *  some routines are stolen from kgdb/ia64.
6 */
7/*
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 */
20
21/*
22 * Copyright (C) 2000-2001 VERITAS Software Corporation.
23 */
24/*
25 *  Contributor:     Lake Stevens Instrument Division$
26 *  Written by:      Glenn Engel $
27 *  Updated by:      Amit Kale<akale@veritas.com>
28 *  Modified for 386 by Jim Kingdon, Cygnus Support.
29 *  Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
30 *
31 */
32
33
34#include <xen/lib.h>
35#include <xen/mm.h>
36#include <asm/byteorder.h>
37#include <asm/debugger.h>
38#include <asm/uaccess.h>
39
40#define USE_UNWIND
41
42#ifdef USE_UNWIND
43#include <asm/unwind.h>
44#endif
45
46/* Printk isn't particularly safe just after we've trapped to the
47   debugger. so avoid it. */
48#define dbg_printk(...)
49//#define dbg_printk(...)       printk(__VA_ARGS__)
50
51u16
52gdb_arch_signal_num(struct cpu_user_regs *regs, unsigned long cookie)
53{
54    /* XXX */
55    return 1;
56}
57
58void 
59gdb_arch_read_reg_array(struct cpu_user_regs *regs, struct gdb_context *ctx)
60{
61    gdb_send_reply("", ctx);
62}
63
64void 
65gdb_arch_write_reg_array(struct cpu_user_regs *regs, const char* buf,
66                         struct gdb_context *ctx)
67{
68    /* XXX TODO */
69    gdb_send_reply("E02", ctx);
70}
71
72/* Like copy_from_user, but safe to call with interrupts disabled.
73   Trust me, and don't look behind the curtain. */
74unsigned
75gdb_arch_copy_from_user(void *dest, const void *src, unsigned len)
76{
77        int val;
78        __asm__ __volatile__(
79                "cmp4.eq p6, p0 = r0, %1\n"
80                "(p6) br.cond.dptk 2f\n"
81                "[1:]\n"
82                ".xdata4 \"__ex_table\", 99f-., 2f-.;\n"
83                "[99:] ld1 %0 = [%3], 1\n"
84                ";;\n"
85                ".xdata4 \"__ex_table\", 99f-., 2f-.;\n"
86                "[99:] st1 [%2] = %0, 1\n"
87                "adds %1 = -1, %1\n"
88                ";;\n"
89                "cmp4.eq p0, p6 = r0, %1\n"
90                "(p6) br.cond.dptk 1b\n"
91                "[2:]\n"
92                : "=r"(val), "=r"(len), "=r"(dest), "=r"(src)
93                :  "1"(len), "2"(dest), "3"(src)
94                : "memory", "p6");
95        return len;
96}
97
98unsigned int 
99gdb_arch_copy_to_user(void *dest, const void *src, unsigned len)
100{
101    /* XXX  */
102    return len;
103}
104
105#define NUM_REGS 590
106#define REGISTER_BYTES (NUM_REGS*8+128*8)
107#define REGISTER_BYTE(N) (((N) * 8)                                                                     \
108        + ((N) <= IA64_FR0_REGNUM ?                                     \
109        0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM)))
110#define REGISTER_SIZE(N)                                               \
111        (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8)
112#define IA64_GR0_REGNUM         0
113#define IA64_FR0_REGNUM         128
114#define IA64_FR127_REGNUM       (IA64_FR0_REGNUM+127)
115#define IA64_PR0_REGNUM         256
116#define IA64_BR0_REGNUM         320
117#define IA64_VFP_REGNUM         328
118#define IA64_PR_REGNUM          330
119#define IA64_IP_REGNUM          331
120#define IA64_PSR_REGNUM         332
121#define IA64_CFM_REGNUM         333
122#define IA64_AR0_REGNUM         334
123#define IA64_NAT0_REGNUM        462
124#define IA64_NAT31_REGNUM       (IA64_NAT0_REGNUM+31)
125#define IA64_NAT32_REGNUM       (IA64_NAT0_REGNUM+32)
126#define IA64_RSC_REGNUM                 (IA64_AR0_REGNUM+16)
127#define IA64_BSP_REGNUM                 (IA64_AR0_REGNUM+17)
128#define IA64_BSPSTORE_REGNUM    (IA64_AR0_REGNUM+18)
129#define IA64_RNAT_REGNUM                (IA64_AR0_REGNUM+19)
130#define IA64_FCR_REGNUM                 (IA64_AR0_REGNUM+21)
131#define IA64_EFLAG_REGNUM               (IA64_AR0_REGNUM+24)
132#define IA64_CSD_REGNUM                 (IA64_AR0_REGNUM+25)
133#define IA64_SSD_REGNUM                 (IA64_AR0_REGNUM+26)
134#define IA64_CFLG_REGNUM                (IA64_AR0_REGNUM+27)
135#define IA64_FSR_REGNUM                 (IA64_AR0_REGNUM+28)
136#define IA64_FIR_REGNUM                 (IA64_AR0_REGNUM+29)
137#define IA64_FDR_REGNUM                 (IA64_AR0_REGNUM+30)
138#define IA64_CCV_REGNUM                 (IA64_AR0_REGNUM+32)
139#define IA64_UNAT_REGNUM                (IA64_AR0_REGNUM+36)
140#define IA64_FPSR_REGNUM                (IA64_AR0_REGNUM+40)
141#define IA64_ITC_REGNUM                 (IA64_AR0_REGNUM+44)
142#define IA64_PFS_REGNUM                 (IA64_AR0_REGNUM+64)
143#define IA64_LC_REGNUM                  (IA64_AR0_REGNUM+65)
144#define IA64_EC_REGNUM                  (IA64_AR0_REGNUM+66)
145
146#ifndef USE_UNWIND
147struct regs_to_cpu_user_resgs_index {
148        unsigned int reg;
149        unsigned int ptregoff;
150};
151
152#define ptoff(V)                ((unsigned int)&((struct cpu_user_regs*)0x0)->V)
153
154// gr
155static const struct regs_to_cpu_user_resgs_index
156gr_reg_to_cpu_user_regs_index[] = {
157        {IA64_GR0_REGNUM + 8,  ptoff(r8)},
158        {IA64_GR0_REGNUM + 9,  ptoff(r9)},
159        {IA64_GR0_REGNUM + 10, ptoff(r10)},
160        {IA64_GR0_REGNUM + 11, ptoff(r11)},
161        {IA64_GR0_REGNUM + 1,  ptoff(r1)},
162        {IA64_GR0_REGNUM + 12, ptoff(r12)},
163        {IA64_GR0_REGNUM + 13, ptoff(r13)},
164        {IA64_GR0_REGNUM + 15, ptoff(r15)},
165
166        {IA64_GR0_REGNUM + 14, ptoff(r14)},
167        {IA64_GR0_REGNUM + 2,  ptoff(r2)},
168        {IA64_GR0_REGNUM + 3,  ptoff(r3)},
169        {IA64_GR0_REGNUM + 16, ptoff(r16)},
170        {IA64_GR0_REGNUM + 17, ptoff(r17)},
171        {IA64_GR0_REGNUM + 18, ptoff(r18)},
172        {IA64_GR0_REGNUM + 19, ptoff(r19)},
173        {IA64_GR0_REGNUM + 20, ptoff(r20)},
174        {IA64_GR0_REGNUM + 21, ptoff(r21)},
175        {IA64_GR0_REGNUM + 22, ptoff(r22)},
176        {IA64_GR0_REGNUM + 23, ptoff(r23)},
177        {IA64_GR0_REGNUM + 24, ptoff(r24)},
178        {IA64_GR0_REGNUM + 25, ptoff(r25)},
179        {IA64_GR0_REGNUM + 26, ptoff(r26)},
180        {IA64_GR0_REGNUM + 27, ptoff(r27)},
181        {IA64_GR0_REGNUM + 28, ptoff(r28)},
182        {IA64_GR0_REGNUM + 29, ptoff(r29)},
183        {IA64_GR0_REGNUM + 30, ptoff(r30)},
184        {IA64_GR0_REGNUM + 31, ptoff(r31)},
185
186        {IA64_GR0_REGNUM + 4,  ptoff(r4)},
187        {IA64_GR0_REGNUM + 5,  ptoff(r5)},
188        {IA64_GR0_REGNUM + 6,  ptoff(r6)},
189        {IA64_GR0_REGNUM + 7,  ptoff(r7)},
190};
191static const int gr_reg_to_cpu_user_regs_index_max =
192        sizeof(gr_reg_to_cpu_user_regs_index) /
193        sizeof(gr_reg_to_cpu_user_regs_index[0]); 
194
195// br
196static const struct regs_to_cpu_user_resgs_index
197br_reg_to_cpu_user_regs_index[] = {
198        {IA64_BR0_REGNUM + 0, ptoff(b0)},
199        {IA64_BR0_REGNUM + 6, ptoff(b6)},
200        {IA64_BR0_REGNUM + 7, ptoff(b7)},
201};
202static const int br_reg_to_cpu_user_regs_index_max =
203        sizeof(br_reg_to_cpu_user_regs_index) /
204        sizeof(br_reg_to_cpu_user_regs_index[0]); 
205
206// f
207static const struct regs_to_cpu_user_resgs_index
208fr_reg_to_cpu_user_regs_index[] = {
209        {IA64_FR0_REGNUM + 6,  ptoff(f6)},
210        {IA64_FR0_REGNUM + 7,  ptoff(f7)},
211        {IA64_FR0_REGNUM + 8,  ptoff(f8)},
212        {IA64_FR0_REGNUM + 9,  ptoff(f9)},
213        {IA64_FR0_REGNUM + 10, ptoff(f10)},
214        {IA64_FR0_REGNUM + 11, ptoff(f11)},
215};
216static const int fr_reg_to_cpu_user_regs_index_max =
217        sizeof(fr_reg_to_cpu_user_regs_index) /
218        sizeof(fr_reg_to_cpu_user_regs_index[0]); 
219       
220
221void 
222gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs,
223                  struct gdb_context *ctx)
224{
225        unsigned long reg = IA64_IP_REGNUM;
226        char buf[9];
227        int i;
228
229        dbg_printk("Register read regnum = 0x%lx\n", regnum);
230        if (IA64_GR0_REGNUM <= regnum && regnum <= IA64_GR0_REGNUM + 31) {
231                for (i = 0; i < gr_reg_to_cpu_user_regs_index_max; i++) {
232                        if (gr_reg_to_cpu_user_regs_index[i].reg == regnum) {
233                                reg = *(unsigned long*)(((char*)regs) + gr_reg_to_cpu_user_regs_index[i].ptregoff);
234                                break;
235                        }
236                }
237                if (i == gr_reg_to_cpu_user_regs_index_max) {
238                        goto out_err;
239                }
240        } else if (IA64_BR0_REGNUM <= regnum && regnum <= IA64_BR0_REGNUM + 7) {
241                for (i = 0; i < br_reg_to_cpu_user_regs_index_max; i++) {
242                        if (br_reg_to_cpu_user_regs_index[i].reg == regnum) {
243                                reg = *(unsigned long*)(((char*)regs) + br_reg_to_cpu_user_regs_index[i].ptregoff);
244                                break;
245                        }
246                }
247                if (i == br_reg_to_cpu_user_regs_index_max) {
248                        goto out_err;
249                }
250        } else if (IA64_FR0_REGNUM + 6 <= regnum && regnum <= IA64_FR0_REGNUM + 11) {
251                for (i = 0; i < fr_reg_to_cpu_user_regs_index_max; i++) {
252                        if (fr_reg_to_cpu_user_regs_index[i].reg == regnum) {
253                                reg = *(unsigned long*)(((char*)regs) + fr_reg_to_cpu_user_regs_index[i].ptregoff);
254                                break;
255                        }
256                }
257                if (i == fr_reg_to_cpu_user_regs_index_max) {
258                        goto out_err;
259                }
260        } else if (regnum == IA64_CSD_REGNUM) {
261                reg = regs->ar_csd;
262        } else if (regnum == IA64_SSD_REGNUM) {
263                reg = regs->ar_ssd;
264        } else if (regnum == IA64_PSR_REGNUM) {
265                reg = regs->cr_ipsr;
266        } else if (regnum == IA64_IP_REGNUM) {
267                reg = regs->cr_iip;
268        } else if (regnum == IA64_CFM_REGNUM) {
269                reg = regs->cr_ifs;
270        } else if (regnum == IA64_UNAT_REGNUM) {
271                reg = regs->ar_unat;
272        } else if (regnum == IA64_PFS_REGNUM) {
273                reg = regs->ar_pfs;
274        } else if (regnum == IA64_RSC_REGNUM) {
275                reg = regs->ar_rsc;
276        } else if (regnum == IA64_RNAT_REGNUM) {
277                reg = regs->ar_rnat;
278        } else if (regnum == IA64_BSPSTORE_REGNUM) {
279                reg = regs->ar_bspstore;
280        } else if (regnum == IA64_PR_REGNUM) {
281                reg = regs->pr;
282        } else if (regnum == IA64_FPSR_REGNUM) {
283                reg = regs->ar_fpsr;
284        } else if (regnum == IA64_CCV_REGNUM) {
285                reg = regs->ar_ccv;
286        } else {
287                // emul_unat, rfi_pfs
288                goto out_err;
289        }
290
291        dbg_printk("Register read regnum = 0x%lx, val = 0x%lx\n", regnum, reg); 
292        snprintf(buf, sizeof(buf), "%.08lx", swab64(reg));
293out:
294        return gdb_send_reply(buf, ctx);
295
296out_err:
297        dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum);
298        safe_strcpy(buf, "x");
299        goto out;
300}
301#else
302
303#define ptoff(V)        ((unsigned int) &((struct pt_regs *)0x0)->V)
304struct reg_to_ptreg_index {
305        unsigned int reg;
306        unsigned int ptregoff;
307};
308
309static struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = {
310        {IA64_GR0_REGNUM + 1, ptoff(r1)},
311        {IA64_GR0_REGNUM + 2, ptoff(r2)},
312        {IA64_GR0_REGNUM + 3, ptoff(r3)},
313        {IA64_GR0_REGNUM + 8, ptoff(r8)},
314        {IA64_GR0_REGNUM + 9, ptoff(r9)},
315        {IA64_GR0_REGNUM + 10, ptoff(r10)},
316        {IA64_GR0_REGNUM + 11, ptoff(r11)},
317        {IA64_GR0_REGNUM + 12, ptoff(r12)},
318        {IA64_GR0_REGNUM + 13, ptoff(r13)},
319        {IA64_GR0_REGNUM + 14, ptoff(r14)},
320        {IA64_GR0_REGNUM + 15, ptoff(r15)},
321        {IA64_GR0_REGNUM + 16, ptoff(r16)},
322        {IA64_GR0_REGNUM + 17, ptoff(r17)},
323        {IA64_GR0_REGNUM + 18, ptoff(r18)},
324        {IA64_GR0_REGNUM + 19, ptoff(r19)},
325        {IA64_GR0_REGNUM + 20, ptoff(r20)},
326        {IA64_GR0_REGNUM + 21, ptoff(r21)},
327        {IA64_GR0_REGNUM + 22, ptoff(r22)},
328        {IA64_GR0_REGNUM + 23, ptoff(r23)},
329        {IA64_GR0_REGNUM + 24, ptoff(r24)},
330        {IA64_GR0_REGNUM + 25, ptoff(r25)},
331        {IA64_GR0_REGNUM + 26, ptoff(r26)},
332        {IA64_GR0_REGNUM + 27, ptoff(r27)},
333        {IA64_GR0_REGNUM + 28, ptoff(r28)},
334        {IA64_GR0_REGNUM + 29, ptoff(r29)},
335        {IA64_GR0_REGNUM + 30, ptoff(r30)},
336        {IA64_GR0_REGNUM + 31, ptoff(r31)},
337};
338
339static struct reg_to_ptreg_index br_reg_to_ptreg_index[] = {
340        {IA64_BR0_REGNUM, ptoff(b0)},
341        {IA64_BR0_REGNUM + 6, ptoff(b6)},
342        {IA64_BR0_REGNUM + 7, ptoff(b7)},
343};
344
345static struct reg_to_ptreg_index ar_reg_to_ptreg_index[] = {
346        {IA64_PFS_REGNUM, ptoff(ar_pfs)},
347        {IA64_UNAT_REGNUM, ptoff(ar_unat)},
348        {IA64_RNAT_REGNUM, ptoff(ar_rnat)},
349        {IA64_BSPSTORE_REGNUM, ptoff(ar_bspstore)},
350        {IA64_RSC_REGNUM, ptoff(ar_rsc)},
351        {IA64_CSD_REGNUM, ptoff(ar_csd)},
352        {IA64_SSD_REGNUM, ptoff(ar_ssd)},
353        {IA64_FPSR_REGNUM, ptoff(ar_fpsr)},
354        {IA64_CCV_REGNUM, ptoff(ar_ccv)},
355};
356
357#ifndef XEN
358extern atomic_t cpu_doing_single_step;
359#endif
360
361static int kgdb_gr_reg(int regnum, struct unw_frame_info *info,
362        unsigned long *reg, int rw)
363{
364        char nat;
365
366        if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) ||
367                (regnum >= (IA64_GR0_REGNUM + 4) &&
368                regnum <= (IA64_GR0_REGNUM + 7)))
369                return !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
370                reg, &nat, rw);
371        else
372                return 0;
373}
374static int kgdb_gr_ptreg(int regnum, struct pt_regs * ptregs,
375        struct unw_frame_info *info, unsigned long *reg, int rw)
376{
377        int i, result = 1;
378        char nat;
379
380        if (!((regnum >= (IA64_GR0_REGNUM + 2) &&
381                regnum <= (IA64_GR0_REGNUM + 3)) ||
382                (regnum >= (IA64_GR0_REGNUM + 8) &&
383                regnum <= (IA64_GR0_REGNUM + 15)) ||
384                (regnum >= (IA64_GR0_REGNUM + 16) &&
385                regnum <= (IA64_GR0_REGNUM + 31))))
386                return 0;
387        else if (rw && ptregs) {
388                for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++)
389                        if (gr_reg_to_ptreg_index[i].reg == regnum) {
390                                *((unsigned long *)(((void *)ptregs) +
391                                gr_reg_to_ptreg_index[i].ptregoff)) = *reg;
392                                break;
393                        }
394        } else if (!rw && ptregs) {
395                for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++)
396                        if (gr_reg_to_ptreg_index[i].reg == regnum) {
397                                *reg = *((unsigned long *)
398                                (((void *)ptregs) +
399                                 gr_reg_to_ptreg_index[i].ptregoff));
400                                break;
401                        }
402        } else
403                result = !unw_access_gr(info, regnum - IA64_GR0_REGNUM,
404                                        reg, &nat, rw);
405        return result;
406}
407
408static int kgdb_br_reg(int regnum, struct pt_regs * ptregs,
409        struct unw_frame_info *info, unsigned long *reg, int rw)
410{
411        int i, result = 1;
412
413        if (!(regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7)))
414                return 0;
415
416        switch (regnum) {
417        case IA64_BR0_REGNUM:
418        case IA64_BR0_REGNUM + 6:
419        case IA64_BR0_REGNUM + 7:
420                if (rw) {
421                        for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++)
422                                if (br_reg_to_ptreg_index[i].reg == regnum) {
423                                        *((unsigned long *)
424                                        (((void *)ptregs) +
425                                        br_reg_to_ptreg_index[i].ptregoff)) =
426                                        *reg;
427                                        break;
428                                }
429                } else
430                        for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++)
431                                if (br_reg_to_ptreg_index[i].reg == regnum) {
432                                                *reg = *((unsigned long *)
433                                                (((void *)ptregs) +
434                                                br_reg_to_ptreg_index[i].
435                                                ptregoff));
436                                                break;
437                                }
438                break;
439        case IA64_BR0_REGNUM + 1:
440        case IA64_BR0_REGNUM + 2:
441        case IA64_BR0_REGNUM + 3:
442        case IA64_BR0_REGNUM + 4:
443        case IA64_BR0_REGNUM + 5:
444                result = !unw_access_br(info, regnum - IA64_BR0_REGNUM,
445                                reg, rw);
446                break;
447        }
448
449        return result;
450}
451
452static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs,
453        struct unw_frame_info *info, unsigned long *reg,
454        struct ia64_fpreg *freg, int rw)
455{
456        int result = 1;
457
458        if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127)))
459                return 0;
460
461        switch (regnum) {
462        case IA64_FR0_REGNUM + 6:
463        case IA64_FR0_REGNUM + 7:
464        case IA64_FR0_REGNUM + 8:
465        case IA64_FR0_REGNUM + 9:
466        case IA64_FR0_REGNUM + 10:
467        case IA64_FR0_REGNUM + 11:
468        case IA64_FR0_REGNUM + 12:
469                if (rw) {
470#ifndef XEN
471                        char *ptr = inbuffer;
472
473                        freg->u.bits[0] = *reg;
474                        kgdb_hex2long(&ptr, &freg->u.bits[1]);
475                        *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) =
476                                *freg;
477#else
478                        printk("%s: %d: writing to fpreg is not supported.\n",
479                                   __func__, __LINE__);
480#endif
481                        break;
482                } else if (!ptregs)
483                        result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
484                                freg, rw);
485                else
486#ifndef XEN
487                        *freg =
488                        *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6)));
489#else
490                    //XXX struct ia64_fpreg and struct pt_fpreg are same.
491                        *freg = *((struct ia64_fpreg*)(&ptregs->f6 +
492                                                                                   (regnum - (IA64_FR0_REGNUM + 6))));
493#endif
494                break;
495        default:
496                if (!rw)
497                        result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM,
498                                freg, rw);
499                else
500                        result = 0;
501                break;
502        }
503
504        return result;
505}
506
507static int kgdb_ar_reg(int regnum, struct pt_regs * ptregs,
508        struct unw_frame_info *info, unsigned long *reg, int rw)
509{
510        int result = 0, i;
511
512        if (!(regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM))
513                return 0;
514
515        if (rw && ptregs) {
516                for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++)
517                        if (ar_reg_to_ptreg_index[i].reg == regnum) {
518                                *((unsigned long *) (((void *)ptregs) +
519                                ar_reg_to_ptreg_index[i].ptregoff)) =
520                                        *reg;
521                                result = 1;
522                                break;
523                        }
524        } else if (ptregs) {
525                for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++)
526                        if (ar_reg_to_ptreg_index[i].reg == regnum) {
527                                *reg = *((unsigned long *) (((void *)ptregs) +
528                                        ar_reg_to_ptreg_index[i].ptregoff));
529                                        result = 1;
530                                break;
531                        }
532        }
533
534        if (result)
535                return result;
536
537       result = 1;
538
539        switch (regnum) {
540        case IA64_CSD_REGNUM:
541                result = !unw_access_ar(info, UNW_AR_CSD, reg, rw);
542                break;
543        case IA64_SSD_REGNUM:
544                result = !unw_access_ar(info, UNW_AR_SSD, reg, rw);
545                break;
546        case IA64_UNAT_REGNUM:
547                result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
548                break;
549                case IA64_RNAT_REGNUM:
550                result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
551                break;
552        case IA64_BSPSTORE_REGNUM:
553                result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
554                break;
555        case IA64_PFS_REGNUM:
556                result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw);
557                break;
558        case IA64_LC_REGNUM:
559                result = !unw_access_ar(info, UNW_AR_LC, reg, rw);
560                break;
561        case IA64_EC_REGNUM:
562                result = !unw_access_ar(info, UNW_AR_EC, reg, rw);
563                break;
564        case IA64_FPSR_REGNUM:
565                result = !unw_access_ar(info, UNW_AR_FPSR, reg, rw);
566                break;
567        case IA64_RSC_REGNUM:
568                result = !unw_access_ar(info, UNW_AR_RSC, reg, rw);
569                break;
570        case IA64_CCV_REGNUM:
571                result = !unw_access_ar(info, UNW_AR_CCV, reg, rw);
572                break;
573        default:
574                result = 0;
575        }
576
577        return result;
578}
579
580#ifndef XEN
581void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info,
582        struct pt_regs *ptregs)
583#else
584static int
585kgdb_get_reg(int regnum, struct unw_frame_info *info,
586                         struct cpu_user_regs* ptregs,
587                         unsigned long* __reg, struct ia64_fpreg* __freg)
588#endif
589{
590        unsigned long reg, size = 0, *mem = &reg;
591        struct ia64_fpreg freg;
592
593        if (kgdb_gr_reg(regnum, info, &reg, 0) ||
594                kgdb_gr_ptreg(regnum, ptregs, info, &reg, 0) ||
595                kgdb_br_reg(regnum, ptregs, info, &reg, 0) ||
596                kgdb_ar_reg(regnum, ptregs, info, &reg, 0))
597                        size = sizeof(reg);
598        else if (kgdb_fr_reg(regnum, NULL, ptregs, info, &reg, &freg, 0)) {
599                size = sizeof(freg);
600                mem = (unsigned long *)&freg;
601        } else if (regnum == IA64_IP_REGNUM) {
602                if (!ptregs) {
603                        unw_get_ip(info, &reg);
604                        size = sizeof(reg);
605                } else {
606                        reg = ptregs->cr_iip;
607                        size = sizeof(reg);
608                }
609        } else if (regnum == IA64_CFM_REGNUM) {
610                if (!ptregs)
611                        unw_get_cfm(info, &reg);
612                else
613                        reg = ptregs->cr_ifs;
614                size = sizeof(reg);
615        } else if (regnum == IA64_PSR_REGNUM) {
616#ifndef XEN
617                if (!ptregs && kgdb_usethread)
618                        ptregs = (struct pt_regs *)
619                        ((unsigned long)kgdb_usethread +
620                        IA64_STK_OFFSET) - 1;
621#endif
622                if (ptregs)
623                        reg = ptregs->cr_ipsr;
624                size = sizeof(reg);
625        } else if (regnum == IA64_PR_REGNUM) {
626                if (ptregs)
627                        reg = ptregs->pr;
628                else
629                        unw_access_pr(info, &reg, 0);
630                size = sizeof(reg);
631        } else if (regnum == IA64_BSP_REGNUM) {
632                unw_get_bsp(info, &reg);
633                size = sizeof(reg);
634        }
635
636#ifndef XEN
637        if (size) {
638                kgdb_mem2hex((char *) mem, outbuffer, size);
639                outbuffer[size*2] = 0;
640        }
641        else
642                strlcpy(outbuffer, "E0", sizeof("E0"));
643
644        return;
645#else
646        if (size) {
647                if (size == sizeof(reg)) {
648                        *__reg = reg;
649                } else {
650                        BUG_ON(size != sizeof(freg));
651                        *__freg = freg;
652                }
653                return 0;
654        }
655
656        return -1;
657#endif
658}
659
660#ifndef XEN
661static int inline kgdb_get_blocked_state(struct task_struct *p,
662                                         struct unw_frame_info *unw)
663#else
664static int
665kgdb_get_blocked_state(struct vcpu *p,
666                                           struct cpu_user_regs *regs,
667                                           struct unw_frame_info *unw)
668#endif
669{
670        unsigned long ip;
671        int count = 0;
672
673#ifndef XEN
674        unw_init_from_blocked_task(unw, p);
675#endif
676        ip = 0UL;
677        do {
678                if (unw_unwind(unw) < 0)
679                        return -1;
680                unw_get_ip(unw, &ip);
681#ifndef XEN
682                if (!in_sched_functions(ip))
683                        break;
684#else
685                dbg_printk("ip 0x%lx cr_iip 0x%lx\n", ip, regs->cr_iip);
686                if (ip == regs->cr_iip)
687                        break;
688#endif
689        } while (count++ < 16);
690
691        if (!ip)
692                return -1;
693        else
694                return 0;
695}
696
697struct gdb_callback_arg
698{
699        struct cpu_user_regs*           regs;
700        unsigned long                           regnum;
701        unsigned long*                          reg;
702        struct pt_fpreg*                        freg;
703
704        int                                                     error;
705                                    //  1: not supported
706                                                                //  0: success
707                                                                // -1: failure
708};
709
710static void
711gdb_get_reg_callback(struct unw_frame_info* info, void* __arg)
712{
713        struct gdb_callback_arg* arg = (struct gdb_callback_arg*)__arg;
714
715        if (kgdb_get_blocked_state(current, arg->regs, info) < 0) {
716                dbg_printk("%s: kgdb_get_blocked_state failed\n", __func__);
717                arg->error = -1;
718                return;
719        }
720        //XXX struct ia64_fpreg and struct pt_fpreg are same.
721        if (kgdb_get_reg(arg->regnum, info, arg->regs, arg->reg, 
722                                         (struct ia64_fpreg*)arg->freg) < 0) {
723                dbg_printk("%s: kgdb_get_reg failed\n", __func__);
724                arg->error = 1;
725                return;
726        }
727        arg->error = 0;
728        return;
729}
730
731void 
732gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs,
733                  struct gdb_context *ctx)
734{
735        struct gdb_callback_arg arg;
736        unsigned long reg;
737        struct pt_fpreg freg;
738        char buf[16 * 2 + 1];
739
740        if (regnum >= NUM_REGS) {
741                dbg_printk("%s: regnum %ld\n", __func__, regnum);
742                goto out_err;
743        }
744
745        arg.regs = regs;
746        arg.regnum = regnum;
747        arg.reg = &reg;
748        arg.freg = &freg;
749        arg.error = 0;
750        unw_init_running(&gdb_get_reg_callback, (void*)&arg);
751        if (arg.error < 0) {
752                dbg_printk("%s: gdb_get_reg_callback failed\n", __func__);
753                goto out_err;
754        }
755
756        if (arg.error > 0) {
757                // notify gdb that this register is not supported.
758                // see fetch_register_using_p() in gdb/remote.c.
759                safe_strcpy(buf, "x");
760        } else if (IA64_FR0_REGNUM <= regnum && regnum <= IA64_FR0_REGNUM + 127) {
761                snprintf(buf, sizeof(buf), "%.016lx", swab64(freg.u.bits[0]));
762                snprintf(buf + 16, sizeof(buf) - 16, "%.016lx", swab64(freg.u.bits[1]));
763        } else {
764                snprintf(buf, sizeof(buf), "%.016lx", swab64(reg));
765        }
766out:
767        return gdb_send_reply(buf, ctx);
768
769out_err:
770        dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum);
771        safe_strcpy(buf, "E0");
772        goto out;
773}
774#endif
775
776void 
777gdb_arch_resume(struct cpu_user_regs *regs,
778                unsigned long addr, unsigned long type,
779                struct gdb_context *ctx)
780{
781    /* XXX */
782    if (type == GDB_STEP) {
783        gdb_send_reply("S01", ctx);
784    }
785}
786
787void
788gdb_arch_print_state(struct cpu_user_regs *regs)
789{
790    /* XXX */
791}
792
793void
794gdb_arch_enter(struct cpu_user_regs *regs)
795{
796    /* nothing */
797}
798
799void
800gdb_arch_exit(struct cpu_user_regs *regs)
801{
802    /* nothing */
803}
804
805/*
806 * Local variables:
807 * mode: C
808 * c-set-style: "BSD"
809 * c-basic-offset: 4
810 * tab-width: 4
811 * End:
812 */
Note: See TracBrowser for help on using the repository browser.