1139790Simp/*-
2131945Smarcel * Copyright (c) 2003, 2004 Marcel Moolenaar
385685Sdfr * All rights reserved.
485685Sdfr *
585685Sdfr * Redistribution and use in source and binary forms, with or without
685685Sdfr * modification, are permitted provided that the following conditions
785685Sdfr * are met:
8117267Smarcel *
985685Sdfr * 1. Redistributions of source code must retain the above copyright
1085685Sdfr *    notice, this list of conditions and the following disclaimer.
1185685Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1285685Sdfr *    notice, this list of conditions and the following disclaimer in the
1385685Sdfr *    documentation and/or other materials provided with the distribution.
1485685Sdfr *
15117267Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16117267Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17117267Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18117267Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19117267Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20117267Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21117267Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22117267Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23117267Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24117267Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2585685Sdfr */
2685685Sdfr
27117267Smarcel#include <sys/cdefs.h>
28117267Smarcel__FBSDID("$FreeBSD$");
29117267Smarcel
3085685Sdfr#include <sys/param.h>
31131945Smarcel#include <sys/kdb.h>
3285685Sdfr#include <sys/kernel.h>
3385685Sdfr#include <sys/systm.h>
3485685Sdfr#include <sys/malloc.h>
3585685Sdfr#include <sys/queue.h>
3685685Sdfr
3796912Smarcel#include <machine/frame.h>
38131945Smarcel#include <machine/md_var.h>
39131945Smarcel#include <machine/pcb.h>
4085685Sdfr#include <machine/unwind.h>
4185685Sdfr
42115084Smarcel#include <uwx.h>
4385685Sdfr
44249132Smavstatic MALLOC_DEFINE(M_UNWIND, "Unwind", "Unwind information");
4585685Sdfr
46115084Smarcelstruct unw_entry {
47115084Smarcel	uint64_t	ue_start;	/* procedure start */
48115084Smarcel	uint64_t	ue_end;		/* procedure end */
49115084Smarcel	uint64_t	ue_info;	/* offset to procedure descriptors */
5085685Sdfr};
5185685Sdfr
52115084Smarcelstruct unw_table {
53115084Smarcel	LIST_ENTRY(unw_table) ut_link;
54115084Smarcel	uint64_t	ut_base;
55115084Smarcel	uint64_t	ut_limit;
56115084Smarcel	struct unw_entry *ut_start;
57115084Smarcel	struct unw_entry *ut_end;
5885685Sdfr};
5985685Sdfr
60115084SmarcelLIST_HEAD(unw_table_list, unw_table);
6185685Sdfr
62115084Smarcelstatic struct unw_table_list unw_tables;
6385685Sdfr
64131945Smarcel#ifdef KDB
65131945Smarcel#define	KDBHEAPSZ	8192
66117267Smarcel
67117267Smarcelstruct mhdr {
68117267Smarcel	uint32_t	sig;
69117267Smarcel#define	MSIG_FREE	0x65657246	/* "Free". */
70117267Smarcel#define	MSIG_USED	0x64657355	/* "Used". */
71117267Smarcel	uint32_t	size;
72117267Smarcel	int32_t		next;
73117267Smarcel	int32_t		prev;
74117267Smarcel};
75117267Smarcel
76131945Smarcelstatic struct mhdr *kdbheap;
77131945Smarcel#endif /* KDB */
78117267Smarcel
79115084Smarcelstatic void *
80115084Smarcelunw_alloc(size_t sz)
8185685Sdfr{
82131945Smarcel#ifdef KDB
83117267Smarcel	struct mhdr *hdr, *hfree;
8485685Sdfr
85131945Smarcel	if (kdb_active) {
86117267Smarcel		sz = (sz + 15) >> 4;
87131945Smarcel		hdr = kdbheap;
88117267Smarcel		while (hdr->sig != MSIG_FREE || hdr->size < sz) {
89117267Smarcel			if (hdr->next == -1)
90117267Smarcel				return (NULL);
91131945Smarcel			hdr = kdbheap + hdr->next;
92117267Smarcel		}
93117267Smarcel		if (hdr->size > sz + 1) {
94117267Smarcel			hfree = hdr + sz + 1;
95117267Smarcel			hfree->sig = MSIG_FREE;
96117267Smarcel			hfree->size = hdr->size - sz - 1;
97131945Smarcel			hfree->prev = hdr - kdbheap;
98117267Smarcel			hfree->next = hdr->next;
99117267Smarcel			hdr->size = sz;
100131945Smarcel			hdr->next = hfree - kdbheap;
101117267Smarcel			if (hfree->next >= 0) {
102131945Smarcel				hfree = kdbheap + hfree->next;
103117267Smarcel				hfree->prev = hdr->next;
104117267Smarcel			}
105117267Smarcel		}
106117267Smarcel		hdr->sig = MSIG_USED;
107117267Smarcel		return (void*)(hdr + 1);
108117267Smarcel	}
109117267Smarcel#endif
110133711Smarcel	return (malloc(sz, M_UNWIND, M_NOWAIT));
11185685Sdfr}
11285685Sdfr
113115084Smarcelstatic void
114115084Smarcelunw_free(void *p)
11585685Sdfr{
116131945Smarcel#ifdef KDB
117117267Smarcel	struct mhdr *hdr, *hfree;
11885685Sdfr
119131945Smarcel	if (kdb_active) {
120117267Smarcel		hdr = (struct mhdr*)p - 1;
121117267Smarcel		if (hdr->sig != MSIG_USED)
122117267Smarcel			return;
123117267Smarcel		hdr->sig = MSIG_FREE;
124131945Smarcel		if (hdr->prev >= 0 && kdbheap[hdr->prev].sig == MSIG_FREE) {
125131945Smarcel			hfree = kdbheap + hdr->prev;
126117267Smarcel			hfree->size += hdr->size + 1;
127117267Smarcel			hfree->next = hdr->next;
128117267Smarcel			if (hdr->next >= 0) {
129131945Smarcel				hfree = kdbheap + hdr->next;
130117267Smarcel				hfree->prev = hdr->prev;
131117267Smarcel			}
132117267Smarcel		} else if (hdr->next >= 0 &&
133131945Smarcel		    kdbheap[hdr->next].sig == MSIG_FREE) {
134131945Smarcel			hfree = kdbheap + hdr->next;
135117267Smarcel			hdr->size += hfree->size + 1;
136117267Smarcel			hdr->next = hfree->next;
137117267Smarcel			if (hdr->next >= 0) {
138131945Smarcel				hfree = kdbheap + hdr->next;
139131945Smarcel				hfree->prev = hdr - kdbheap;
140117267Smarcel			}
141117267Smarcel		}
142117267Smarcel		return;
143117267Smarcel	}
144117267Smarcel#endif
145115084Smarcel	free(p, M_UNWIND);
14685685Sdfr}
14785685Sdfr
148115084Smarcelstatic struct unw_table *
149115084Smarcelunw_table_lookup(uint64_t ip)
150105470Smarcel{
151115084Smarcel	struct unw_table *ut;
152105470Smarcel
153115084Smarcel	LIST_FOREACH(ut, &unw_tables, ut_link) {
154115084Smarcel		if (ip >= ut->ut_base && ip < ut->ut_limit)
155115084Smarcel			return (ut);
156105470Smarcel	}
157115084Smarcel	return (NULL);
158105470Smarcel}
159105470Smarcel
160131945Smarcelstatic uint64_t
161131945Smarcelunw_copyin_from_frame(struct trapframe *tf, uint64_t from)
162131945Smarcel{
163131945Smarcel	uint64_t val;
164131945Smarcel	int reg;
165131945Smarcel
166131945Smarcel	if (from == UWX_REG_AR_PFS)
167131945Smarcel		val = tf->tf_special.pfs;
168131945Smarcel	else if (from == UWX_REG_PREDS)
169131945Smarcel		val = tf->tf_special.pr;
170131945Smarcel	else if (from == UWX_REG_AR_RNAT)
171131945Smarcel		val = tf->tf_special.rnat;
172131945Smarcel	else if (from == UWX_REG_AR_UNAT)
173131945Smarcel		val = tf->tf_special.unat;
174131945Smarcel	else if (from >= UWX_REG_GR(0) && from <= UWX_REG_GR(127)) {
175131945Smarcel		reg = from - UWX_REG_GR(0);
176131945Smarcel		if (reg == 1)
177131945Smarcel			val = tf->tf_special.gp;
178131945Smarcel		else if (reg == 12)
179131945Smarcel			val = tf->tf_special.sp;
180131945Smarcel		else if (reg == 13)
181131945Smarcel			val = tf->tf_special.tp;
182131945Smarcel		else if (reg >= 2 && reg <= 3)
183131945Smarcel			val = (&tf->tf_scratch.gr2)[reg - 2];
184131945Smarcel		else if (reg >= 8 && reg <= 11)
185131945Smarcel			val = (&tf->tf_scratch.gr8)[reg - 8];
186131945Smarcel		else if (reg >= 14 && reg <= 31)
187131945Smarcel			val = (&tf->tf_scratch.gr14)[reg - 14];
188131945Smarcel		else
189131945Smarcel			goto oops;
190131945Smarcel	} else if (from >= UWX_REG_BR(0) && from <= UWX_REG_BR(7)) {
191131945Smarcel		reg = from - UWX_REG_BR(0);
192131945Smarcel		if (reg == 0)
193131945Smarcel			val = tf->tf_special.rp;
194131945Smarcel		else if (reg >= 6 && reg <= 7)
195131945Smarcel			val = (&tf->tf_scratch.br6)[reg - 6];
196131945Smarcel		else
197131945Smarcel			goto oops;
198131945Smarcel	} else
199131945Smarcel		goto oops;
200131945Smarcel	return (val);
201131945Smarcel
202131945Smarcel oops:
203131945Smarcel	printf("UNW: %s(%p, %lx)\n", __func__, tf, from);
204131945Smarcel	return (0UL);
205131945Smarcel}
206131945Smarcel
207131945Smarcelstatic uint64_t
208131945Smarcelunw_copyin_from_pcb(struct pcb *pcb, uint64_t from)
209131945Smarcel{
210131945Smarcel	uint64_t val;
211131945Smarcel	int reg;
212131945Smarcel
213131945Smarcel	if (from == UWX_REG_AR_PFS)
214131945Smarcel		val = pcb->pcb_special.pfs;
215131945Smarcel	else if (from == UWX_REG_PREDS)
216131945Smarcel		val = pcb->pcb_special.pr;
217131945Smarcel	else if (from == UWX_REG_AR_RNAT)
218131945Smarcel		val = pcb->pcb_special.rnat;
219131945Smarcel	else if (from == UWX_REG_AR_UNAT)
220131945Smarcel		val = pcb->pcb_special.unat;
221131945Smarcel	else if (from >= UWX_REG_GR(0) && from <= UWX_REG_GR(127)) {
222131945Smarcel		reg = from - UWX_REG_GR(0);
223131945Smarcel		if (reg == 1)
224131945Smarcel			val = pcb->pcb_special.gp;
225131945Smarcel		else if (reg == 12)
226131945Smarcel			val = pcb->pcb_special.sp;
227131945Smarcel		else if (reg == 13)
228131945Smarcel			val = pcb->pcb_special.tp;
229131945Smarcel		else if (reg >= 4 && reg <= 7)
230131945Smarcel			val = (&pcb->pcb_preserved.gr4)[reg - 4];
231131945Smarcel		else
232131945Smarcel			goto oops;
233131945Smarcel	} else if (from >= UWX_REG_BR(0) && from <= UWX_REG_BR(7)) {
234131945Smarcel		reg = from - UWX_REG_BR(0);
235131945Smarcel		if (reg == 0)
236131945Smarcel			val = pcb->pcb_special.rp;
237131945Smarcel		else if (reg >= 1 && reg <= 5)
238131945Smarcel			val = (&pcb->pcb_preserved.br1)[reg - 1];
239131945Smarcel		else
240131945Smarcel			goto oops;
241131945Smarcel	} else
242131945Smarcel		goto oops;
243131945Smarcel	return (val);
244131945Smarcel
245131945Smarcel oops:
246131945Smarcel	printf("UNW: %s(%p, %lx)\n", __func__, pcb, from);
247131945Smarcel	return (0UL);
248131945Smarcel}
249131945Smarcel
250115084Smarcelstatic int
251115084Smarcelunw_cb_copyin(int req, char *to, uint64_t from, int len, intptr_t tok)
25285685Sdfr{
253115084Smarcel	struct unw_regstate *rs = (void*)tok;
254131945Smarcel	uint64_t val;
25585685Sdfr
256115084Smarcel	switch (req) {
257115084Smarcel	case UWX_COPYIN_UINFO:
258115084Smarcel		break;
259115084Smarcel	case UWX_COPYIN_MSTACK:
260115084Smarcel		*((uint64_t*)to) = *((uint64_t*)from);
261115084Smarcel		return (8);
262115084Smarcel	case UWX_COPYIN_RSTACK:
263115084Smarcel		*((uint64_t*)to) = *((uint64_t*)from);
264115084Smarcel		return (8);
265115084Smarcel	case UWX_COPYIN_REG:
266131945Smarcel		if (rs->frame != NULL)
267131945Smarcel			val = unw_copyin_from_frame(rs->frame, from);
268131945Smarcel		else if (rs->pcb != NULL)
269131945Smarcel			val = unw_copyin_from_pcb(rs->pcb, from);
270131945Smarcel		else
271115084Smarcel			goto oops;
272131945Smarcel		*((uint64_t*)to) = val;
273115084Smarcel		return (len);
27485865Sdfr	}
27585685Sdfr
276115084Smarcel oops:
277115084Smarcel	printf("UNW: %s(%d, %p, %lx, %d, %lx)\n", __func__, req, to, from,
278115084Smarcel	    len, tok);
279115084Smarcel	return (0);
28085685Sdfr}
28185685Sdfr
282115084Smarcelstatic int
283115084Smarcelunw_cb_lookup(int req, uint64_t ip, intptr_t tok, uint64_t **vec)
28485685Sdfr{
285115084Smarcel	struct unw_regstate *rs = (void*)tok;
286115084Smarcel	struct unw_table *ut;
28785685Sdfr
288115084Smarcel	switch (req) {
289115084Smarcel	case UWX_LKUP_LOOKUP:
290115084Smarcel		ut = unw_table_lookup(ip);
291115084Smarcel		if (ut == NULL)
292115084Smarcel			return (UWX_LKUP_NOTFOUND);
293115084Smarcel		rs->keyval[0] = UWX_KEY_TBASE;
294115084Smarcel		rs->keyval[1] = ut->ut_base;
295115084Smarcel		rs->keyval[2] = UWX_KEY_USTART;
296115084Smarcel		rs->keyval[3] = (intptr_t)ut->ut_start;
297115084Smarcel		rs->keyval[4] = UWX_KEY_UEND;
298115084Smarcel		rs->keyval[5] = (intptr_t)ut->ut_end;
299115084Smarcel		rs->keyval[6] = 0;
300115084Smarcel		rs->keyval[7] = 0;
301115084Smarcel		*vec = rs->keyval;
302115084Smarcel		return (UWX_LKUP_UTABLE);
303115084Smarcel	case UWX_LKUP_FREE:
304115084Smarcel		return (0);
30585685Sdfr	}
30685685Sdfr
307115084Smarcel	return (UWX_LKUP_ERR);
30885685Sdfr}
30985685Sdfr
310115084Smarcelint
311131945Smarcelunw_create_from_frame(struct unw_regstate *rs, struct trapframe *tf)
31285685Sdfr{
313131945Smarcel	uint64_t bsp, ip;
314131945Smarcel	int uwxerr;
31585685Sdfr
316115084Smarcel	rs->frame = tf;
317131945Smarcel	rs->pcb = NULL;
318115084Smarcel	rs->env = uwx_init();
319115084Smarcel	if (rs->env == NULL)
320115084Smarcel		return (ENOMEM);
32185685Sdfr
322115084Smarcel	uwxerr = uwx_register_callbacks(rs->env, (intptr_t)rs,
323115084Smarcel	    unw_cb_copyin, unw_cb_lookup);
324115084Smarcel	if (uwxerr)
325115084Smarcel		return (EINVAL);		/* XXX */
32685685Sdfr
327115084Smarcel	bsp = tf->tf_special.bspstore + tf->tf_special.ndirty;
328131945Smarcel	bsp = ia64_bsp_adjust(bsp, -IA64_CFM_SOF(tf->tf_special.cfm));
329131945Smarcel	ip = tf->tf_special.iip + ((tf->tf_special.psr >> 41) & 3);
33085685Sdfr
331131945Smarcel	uwxerr = uwx_init_context(rs->env, ip, tf->tf_special.sp, bsp,
332131945Smarcel	    tf->tf_special.cfm);
333131945Smarcel
334115084Smarcel	return ((uwxerr) ? EINVAL : 0);		/* XXX */
33585685Sdfr}
33685685Sdfr
337131945Smarcelint
338131945Smarcelunw_create_from_pcb(struct unw_regstate *rs, struct pcb *pcb)
339131945Smarcel{
340131945Smarcel	uint64_t bsp, cfm, ip;
341131945Smarcel	int uwxerr;
342131945Smarcel
343131945Smarcel	rs->frame = NULL;
344131945Smarcel	rs->pcb = pcb;
345131945Smarcel	rs->env = uwx_init();
346131945Smarcel	if (rs->env == NULL)
347131945Smarcel		return (ENOMEM);
348131945Smarcel
349131945Smarcel	uwxerr = uwx_register_callbacks(rs->env, (intptr_t)rs,
350131945Smarcel	    unw_cb_copyin, unw_cb_lookup);
351131945Smarcel	if (uwxerr)
352131945Smarcel		return (EINVAL);		/* XXX */
353131945Smarcel
354131945Smarcel	bsp = pcb->pcb_special.bspstore;
355131945Smarcel	if (pcb->pcb_special.__spare == ~0UL) {
356131945Smarcel		ip = pcb->pcb_special.iip + ((pcb->pcb_special.psr >> 41) & 3);
357131945Smarcel		cfm = pcb->pcb_special.cfm;
358131945Smarcel		bsp += pcb->pcb_special.ndirty;
359131945Smarcel		bsp = ia64_bsp_adjust(bsp, -IA64_CFM_SOF(cfm));
360131945Smarcel	} else {
361131945Smarcel		ip = pcb->pcb_special.rp;
362131945Smarcel		cfm = pcb->pcb_special.pfs;
363131945Smarcel		bsp = ia64_bsp_adjust(bsp, -IA64_CFM_SOL(cfm));
364131945Smarcel	}
365131945Smarcel	uwxerr = uwx_init_context(rs->env, ip, pcb->pcb_special.sp, bsp, cfm);
366131945Smarcel
367131945Smarcel	return ((uwxerr) ? EINVAL : 0);		/* XXX */
368131945Smarcel}
369131945Smarcel
370117267Smarcelvoid
371117267Smarcelunw_delete(struct unw_regstate *rs)
372117267Smarcel{
373117267Smarcel
374117467Smarcel	if (rs->env != NULL)
375117467Smarcel		uwx_free(rs->env);
376117267Smarcel}
377117267Smarcel
378115084Smarcelint
379115084Smarcelunw_step(struct unw_regstate *rs)
38085685Sdfr{
381117467Smarcel	int err;
38285685Sdfr
383145137Smarcel	switch (uwx_step(rs->env)) {
384145137Smarcel	case UWX_ABI_FRAME:
385145137Smarcel		err = ERESTART;
386145137Smarcel		break;
387145137Smarcel	case UWX_BOTTOM:
388145137Smarcel		err = EJUSTRETURN;
389145137Smarcel		break;
390145137Smarcel	case UWX_OK:
391145137Smarcel		err = 0;
392145137Smarcel		break;
393145137Smarcel	default:
394145137Smarcel		err = EINVAL;		/* XXX */
395145137Smarcel		break;
396145137Smarcel	}
397145137Smarcel	return (err);
39885685Sdfr}
39985685Sdfr
400115084Smarcelint
401115084Smarcelunw_get_bsp(struct unw_regstate *s, uint64_t *r)
40285685Sdfr{
403115084Smarcel	int uwxerr;
40485685Sdfr
405115084Smarcel	uwxerr = uwx_get_reg(s->env, UWX_REG_BSP, r);
406115084Smarcel	return ((uwxerr) ? EINVAL : 0); 	/* XXX */
40785685Sdfr}
40885685Sdfr
409115084Smarcelint
410115084Smarcelunw_get_cfm(struct unw_regstate *s, uint64_t *r)
41185685Sdfr{
412115084Smarcel	int uwxerr;
41385685Sdfr
414115084Smarcel	uwxerr = uwx_get_reg(s->env, UWX_REG_CFM, r);
415115084Smarcel	return ((uwxerr) ? EINVAL : 0); 	/* XXX */
41685685Sdfr}
41785685Sdfr
418115084Smarcelint
419115084Smarcelunw_get_ip(struct unw_regstate *s, uint64_t *r)
42085685Sdfr{
421115084Smarcel	int uwxerr;
42285685Sdfr
423115084Smarcel	uwxerr = uwx_get_reg(s->env, UWX_REG_IP, r);
424115084Smarcel	return ((uwxerr) ? EINVAL : 0); 	/* XXX */
42585685Sdfr}
42685685Sdfr
427115084Smarcelint
428117467Smarcelunw_get_sp(struct unw_regstate *s, uint64_t *r)
429117467Smarcel{
430117467Smarcel	int uwxerr;
431117467Smarcel
432117467Smarcel	uwxerr = uwx_get_reg(s->env, UWX_REG_SP, r);
433117467Smarcel	return ((uwxerr) ? EINVAL : 0); 	/* XXX */
434117467Smarcel}
435117467Smarcel
436117467Smarcelint
437115084Smarcelunw_table_add(uint64_t base, uint64_t start, uint64_t end)
43885685Sdfr{
439115084Smarcel	struct unw_table *ut;
44085685Sdfr
441117267Smarcel	ut = malloc(sizeof(struct unw_table), M_UNWIND, M_WAITOK);
442115084Smarcel	ut->ut_base = base;
443115084Smarcel	ut->ut_start = (struct unw_entry*)start;
444115084Smarcel	ut->ut_end = (struct unw_entry*)end;
445115084Smarcel	ut->ut_limit = base + ut->ut_end[-1].ue_end;
446115084Smarcel	LIST_INSERT_HEAD(&unw_tables, ut, ut_link);
44785685Sdfr
448115084Smarcel	if (bootverbose)
449115084Smarcel		printf("UNWIND: table added: base=%lx, start=%lx, end=%lx\n",
450115084Smarcel		    base, start, end);
45185685Sdfr
452115084Smarcel	return (0);
45385685Sdfr}
45485685Sdfr
455115084Smarcelvoid
456115084Smarcelunw_table_remove(uint64_t base)
45785685Sdfr{
458115084Smarcel	struct unw_table *ut;
45985685Sdfr
460115084Smarcel	ut = unw_table_lookup(base);
461115084Smarcel	if (ut != NULL) {
462115084Smarcel		LIST_REMOVE(ut, ut_link);
463115084Smarcel		free(ut, M_UNWIND);
464115084Smarcel		if (bootverbose)
465115084Smarcel			printf("UNWIND: table removed: base=%lx\n", base);
46685685Sdfr	}
46785685Sdfr}
46885685Sdfr
46985685Sdfrstatic void
470115084Smarcelunw_initialize(void *dummy __unused)
47185685Sdfr{
47285685Sdfr
473115084Smarcel	LIST_INIT(&unw_tables);
474115084Smarcel	uwx_register_alloc_cb(unw_alloc, unw_free);
475131945Smarcel#ifdef KDB
476131945Smarcel	kdbheap = malloc(KDBHEAPSZ, M_UNWIND, M_WAITOK);
477131945Smarcel	kdbheap->sig = MSIG_FREE;
478131945Smarcel	kdbheap->size = (KDBHEAPSZ - sizeof(struct mhdr)) >> 4;
479131945Smarcel	kdbheap->next = -1;
480131945Smarcel	kdbheap->prev = -1;
481117267Smarcel#endif
48285685Sdfr}
483115084SmarcelSYSINIT(unwind, SI_SUB_KMEM, SI_ORDER_ANY, unw_initialize, 0);
484