1178172Simp/*- 2178172Simp * Copyright (c) 2005 Antoine Brodin 3178172Simp * All rights reserved. 4178172Simp * 5178172Simp * Redistribution and use in source and binary forms, with or without 6178172Simp * modification, are permitted provided that the following conditions 7178172Simp * are met: 8178172Simp * 1. Redistributions of source code must retain the above copyright 9178172Simp * notice, this list of conditions and the following disclaimer. 10178172Simp * 2. Redistributions in binary form must reproduce the above copyright 11178172Simp * notice, this list of conditions and the following disclaimer in the 12178172Simp * documentation and/or other materials provided with the distribution. 13178172Simp * 14178172Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17178172Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24178172Simp * SUCH DAMAGE. 25178172Simp */ 26178172Simp 27178172Simp#include <sys/cdefs.h> 28178172Simp__FBSDID("$FreeBSD: releng/10.3/sys/mips/mips/stack_machdep.c 250576 2013-05-12 16:43:26Z eadler $"); 29178172Simp 30178172Simp#include <sys/types.h> 31178172Simp#include <sys/systm.h> 32178172Simp#include <sys/param.h> 33178172Simp#include <sys/proc.h> 34178172Simp#include <sys/stack.h> 35178172Simp 36178172Simp#include <machine/mips_opcode.h> 37178172Simp 38178172Simp#include <machine/param.h> 39178172Simp#include <machine/pcb.h> 40178172Simp#include <machine/regnum.h> 41178172Simp 42178172Simpstatic u_register_t 43178172Simpstack_register_fetch(u_register_t sp, u_register_t stack_pos) 44178172Simp{ 45178172Simp u_register_t * stack = 46209500Sjchandra ((u_register_t *)(intptr_t)sp + (size_t)stack_pos/sizeof(u_register_t)); 47178172Simp 48178172Simp return *stack; 49178172Simp} 50178172Simp 51178172Simpstatic void 52178172Simpstack_capture(struct stack *st, u_register_t pc, u_register_t sp) 53178172Simp{ 54178172Simp u_register_t ra = 0, i, stacksize; 55178172Simp short ra_stack_pos = 0; 56178172Simp InstFmt insn; 57178172Simp 58178172Simp stack_zero(st); 59178172Simp 60178172Simp for (;;) { 61178172Simp stacksize = 0; 62209500Sjchandra if (pc <= (u_register_t)(intptr_t)btext) 63178172Simp break; 64209500Sjchandra for (i = pc; i >= (u_register_t)(intptr_t)btext; i -= sizeof (insn)) { 65209500Sjchandra bcopy((void *)(intptr_t)i, &insn, sizeof insn); 66178172Simp switch (insn.IType.op) { 67178172Simp case OP_ADDI: 68178172Simp case OP_ADDIU: 69209500Sjchandra case OP_DADDI: 70209500Sjchandra case OP_DADDIU: 71178172Simp if (insn.IType.rs != SP || insn.IType.rt != SP) 72178172Simp break; 73178172Simp stacksize = -(short)insn.IType.imm; 74178172Simp break; 75178172Simp 76178172Simp case OP_SW: 77209500Sjchandra case OP_SD: 78178172Simp if (insn.IType.rs != SP || insn.IType.rt != RA) 79178172Simp break; 80178172Simp ra_stack_pos = (short)insn.IType.imm; 81178172Simp break; 82178172Simp default: 83178172Simp break; 84178172Simp } 85178172Simp 86178172Simp if (stacksize) 87178172Simp break; 88178172Simp } 89178172Simp 90178172Simp if (stack_put(st, pc) == -1) 91178172Simp break; 92178172Simp 93178172Simp for (i = pc; !ra; i += sizeof (insn)) { 94209500Sjchandra bcopy((void *)(intptr_t)i, &insn, sizeof insn); 95178172Simp 96178172Simp switch (insn.IType.op) { 97178172Simp case OP_SPECIAL: 98178172Simp if((insn.RType.func == OP_JR)) 99178172Simp { 100209500Sjchandra if (ra >= (u_register_t)(intptr_t)btext) 101178172Simp break; 102178172Simp if (insn.RType.rs != RA) 103178172Simp break; 104178172Simp ra = stack_register_fetch(sp, 105178172Simp ra_stack_pos); 106178172Simp if (!ra) 107178172Simp goto done; 108178172Simp ra -= 8; 109178172Simp } 110178172Simp break; 111178172Simp default: 112178172Simp break; 113178172Simp } 114178172Simp /* eret */ 115178172Simp if (insn.word == 0x42000018) 116178172Simp goto done; 117178172Simp } 118178172Simp 119178172Simp if (pc == ra && stacksize == 0) 120178172Simp break; 121178172Simp 122178172Simp sp += stacksize; 123178172Simp pc = ra; 124178172Simp ra = 0; 125178172Simp } 126178172Simpdone: 127178172Simp return; 128178172Simp} 129178172Simp 130178172Simpvoid 131178172Simpstack_save_td(struct stack *st, struct thread *td) 132178172Simp{ 133178172Simp u_register_t pc, sp; 134178172Simp 135178172Simp if (TD_IS_SWAPPED(td)) 136178172Simp panic("stack_save_td: swapped"); 137178172Simp if (TD_IS_RUNNING(td)) 138178172Simp panic("stack_save_td: running"); 139178172Simp 140178172Simp pc = td->td_pcb->pcb_regs.pc; 141178172Simp sp = td->td_pcb->pcb_regs.sp; 142178172Simp stack_capture(st, pc, sp); 143178172Simp} 144178172Simp 145178172Simpvoid 146178172Simpstack_save(struct stack *st) 147178172Simp{ 148178172Simp u_register_t pc, sp; 149178172Simp 150178172Simp if (curthread == NULL) 151250576Seadler panic("stack_save: curthread == NULL"); 152178172Simp 153178172Simp pc = curthread->td_pcb->pcb_regs.pc; 154178172Simp sp = curthread->td_pcb->pcb_regs.sp; 155178172Simp stack_capture(st, pc, sp); 156178172Simp} 157