1174195Srwatson/*-
2174195Srwatson * Copyright (c) 2005 Antoine Brodin
3174195Srwatson * All rights reserved.
4174195Srwatson *
5174195Srwatson * Redistribution and use in source and binary forms, with or without
6174195Srwatson * modification, are permitted provided that the following conditions
7174195Srwatson * are met:
8174195Srwatson * 1. Redistributions of source code must retain the above copyright
9174195Srwatson *    notice, this list of conditions and the following disclaimer.
10174195Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11174195Srwatson *    notice, this list of conditions and the following disclaimer in the
12174195Srwatson *    documentation and/or other materials provided with the distribution.
13174195Srwatson *
14174195Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15174195Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16174195Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17174195Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18174195Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19174195Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20174195Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21174195Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22174195Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23174195Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24174195Srwatson * SUCH DAMAGE.
25174195Srwatson */
26174195Srwatson
27174195Srwatson#include <sys/cdefs.h>
28174195Srwatson__FBSDID("$FreeBSD$");
29174195Srwatson
30174195Srwatson#include <sys/systm.h>
31174195Srwatson#include <sys/param.h>
32174195Srwatson#include <sys/proc.h>
33174195Srwatson#include <sys/stack.h>
34174195Srwatson
35174195Srwatson#include <machine/vmparam.h>
36174195Srwatson#include <machine/pcb.h>
37174195Srwatson#include <machine/stack.h>
38174195Srwatson
39250810Sandrew/*
40250810Sandrew * This code makes assumptions about the stack layout. These are correct
41250810Sandrew * when using APCS (the old ABI), but are no longer true with AAPCS and the
42250810Sandrew * ARM EABI. There is also an issue with clang and llvm when building for
43250810Sandrew * APCS where it lays out the stack incorrectly. Because of this we disable
44250810Sandrew * this when building for ARM EABI or when building with clang.
45250810Sandrew */
46266404Sian
47266404Sianextern vm_offset_t kernel_vm_end;
48266404Sian
49174195Srwatsonstatic void
50174195Srwatsonstack_capture(struct stack *st, u_int32_t *frame)
51174195Srwatson{
52250531Skientzle#if !defined(__ARM_EABI__) && !defined(__clang__)
53174195Srwatson	vm_offset_t callpc;
54174195Srwatson
55266404Sian	while (INKERNEL(frame) && (vm_offset_t)frame < kernel_vm_end) {
56174195Srwatson		callpc = frame[FR_SCP];
57174195Srwatson		if (stack_put(st, callpc) == -1)
58174195Srwatson			break;
59174195Srwatson		frame = (u_int32_t *)(frame[FR_RFP]);
60174195Srwatson	}
61250531Skientzle#endif
62174195Srwatson}
63174195Srwatson
64174195Srwatsonvoid
65174195Srwatsonstack_save_td(struct stack *st, struct thread *td)
66174195Srwatson{
67174195Srwatson	u_int32_t *frame;
68174195Srwatson
69174195Srwatson	if (TD_IS_SWAPPED(td))
70174195Srwatson		panic("stack_save_td: swapped");
71174195Srwatson	if (TD_IS_RUNNING(td))
72174195Srwatson		panic("stack_save_td: running");
73174195Srwatson
74250810Sandrew	/*
75250810Sandrew	 * This register, the frame pointer, is incorrect for the ARM EABI
76250810Sandrew	 * as it doesn't have a frame pointer, however it's value is not used
77250810Sandrew	 * when building for EABI.
78250810Sandrew	 */
79278614Sian	frame = (u_int32_t *)td->td_pcb->pcb_regs.sf_r11;
80250531Skientzle	stack_zero(st);
81174195Srwatson	stack_capture(st, frame);
82174195Srwatson}
83174195Srwatson
84174195Srwatsonvoid
85174195Srwatsonstack_save(struct stack *st)
86174195Srwatson{
87174195Srwatson	u_int32_t *frame;
88174195Srwatson
89174195Srwatson	frame = (u_int32_t *)__builtin_frame_address(0);
90250531Skientzle	stack_zero(st);
91174195Srwatson	stack_capture(st, frame);
92174195Srwatson}
93