1/*
2 * Copyright (c) 2004 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include <sys/types.h>
31#include <machine/asm.h>
32#include <machine/pcb.h>
33#include <machine/frame.h>
34#include <err.h>
35#include <kvm.h>
36#include <string.h>
37
38#include <defs.h>
39#include <target.h>
40#include <gdbthread.h>
41#include <inferior.h>
42#include <regcache.h>
43#include <frame-unwind.h>
44#include <sparc-tdep.h>
45#include <sparc64-tdep.h>
46
47#include "kgdb.h"
48
49CORE_ADDR
50kgdb_trgt_core_pcb(u_int cpuid)
51{
52	return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb)));
53}
54
55void
56kgdb_trgt_fetch_registers(int regno __unused)
57{
58	struct kthr *kt;
59	struct pcb pcb;
60
61	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
62	if (kt == NULL)
63		return;
64	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
65		warnx("kvm_read: %s", kvm_geterr(kvm));
66		memset(&pcb, 0, sizeof(pcb));
67	}
68
69	supply_register(SPARC_SP_REGNUM, (char *)&pcb.pcb_sp);
70	sparc_supply_rwindow(current_regcache, pcb.pcb_sp, -1);
71	supply_register(SPARC64_PC_REGNUM, (char *)&pcb.pcb_pc);
72	pcb.pcb_pc += 4;
73	supply_register(SPARC64_NPC_REGNUM, (char *)&pcb.pcb_pc);
74}
75
76void
77kgdb_trgt_store_registers(int regno __unused)
78{
79	fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
80}
81
82void
83kgdb_trgt_new_objfile(struct objfile *objfile)
84{
85}
86
87struct kgdb_frame_cache {
88	CORE_ADDR	pc;
89	CORE_ADDR	sp;
90	CORE_ADDR	fp;
91};
92
93static struct kgdb_frame_cache *
94kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
95{
96	char buf[MAX_REGISTER_SIZE];
97	struct kgdb_frame_cache *cache;
98
99	cache = *this_cache;
100	if (cache == NULL) {
101		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
102		*this_cache = cache;
103		cache->pc = frame_func_unwind(next_frame);
104		frame_unwind_register(next_frame, SPARC_SP_REGNUM, buf);
105		cache->sp = extract_unsigned_integer(buf,
106		    register_size(current_gdbarch, SPARC_SP_REGNUM));
107		frame_unwind_register(next_frame, SPARC_FP_REGNUM, buf);
108		cache->fp = extract_unsigned_integer(buf,
109		    register_size(current_gdbarch, SPARC_FP_REGNUM));
110		cache->fp += BIAS - sizeof(struct trapframe);
111	}
112	return (cache);
113}
114
115static void
116kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
117    struct frame_id *this_id)
118{
119	struct kgdb_frame_cache *cache;
120
121	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
122	*this_id = frame_id_build(cache->sp, cache->pc);
123}
124
125static void
126kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
127    void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp,
128    CORE_ADDR *addrp, int *realnump, void *valuep)
129{
130	char dummy_valuep[MAX_REGISTER_SIZE];
131	struct kgdb_frame_cache *cache;
132	int ofs, regsz;
133
134	regsz = register_size(current_gdbarch, regnum);
135
136	if (valuep == NULL)
137		valuep = dummy_valuep;
138	memset(valuep, 0, regsz);
139	*optimizedp = 0;
140	*addrp = 0;
141	*lvalp = not_lval;
142	*realnump = -1;
143
144	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
145
146	switch (regnum) {
147	case SPARC_SP_REGNUM:
148		ofs = offsetof(struct trapframe, tf_sp);
149		break;
150	case SPARC64_PC_REGNUM:
151		ofs = offsetof(struct trapframe, tf_tpc);
152		break;
153	case SPARC64_NPC_REGNUM:
154		ofs = offsetof(struct trapframe, tf_tnpc);
155		break;
156	case SPARC_O0_REGNUM:
157	case SPARC_O1_REGNUM:
158	case SPARC_O2_REGNUM:
159	case SPARC_O3_REGNUM:
160	case SPARC_O4_REGNUM:
161	case SPARC_O5_REGNUM:
162	case SPARC_O7_REGNUM:
163		ofs = offsetof(struct trapframe, tf_out) +
164		    (regnum - SPARC_O0_REGNUM) * 8;
165		break;
166	default:
167		if (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) {
168			ofs = (regnum - SPARC_L0_REGNUM) * 8;
169			*addrp = cache->sp + BIAS + ofs;
170			*lvalp = lval_memory;
171			target_read_memory(*addrp, valuep, regsz);
172		}
173		return;
174	}
175
176	*addrp = cache->fp + ofs;
177	*lvalp = lval_memory;
178	target_read_memory(*addrp, valuep, regsz);
179}
180
181static const struct frame_unwind kgdb_trgt_trapframe_unwind = {
182        UNKNOWN_FRAME,
183        &kgdb_trgt_trapframe_this_id,
184        &kgdb_trgt_trapframe_prev_register
185};
186
187const struct frame_unwind *
188kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
189{
190	char *pname;
191	CORE_ADDR pc;
192
193	pc = frame_func_unwind(next_frame);
194	pname = NULL;
195	find_pc_partial_function(pc, &pname, NULL, NULL);
196	if (pname == NULL)
197		return (NULL);
198	if (strcmp(pname, "tl0_intr") == 0 ||
199	    strcmp(pname, "tl0_trap") == 0 ||
200	    strcmp(pname, "tl1_intr") == 0 ||
201	    strcmp(pname, "tl1_trap") == 0)
202		return (&kgdb_trgt_trapframe_unwind);
203	/* printf("%s: %lx =%s\n", __func__, pc, pname); */
204	return (NULL);
205}
206