Blame alpha.c

Packit bf408e
/* alpha.c - core analysis suite
Packit bf408e
 *
Packit bf408e
 * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
Packit bf408e
 * Copyright (C) 2002-2006, 2010-2013 David Anderson
Packit bf408e
 * Copyright (C) 2002-2006, 2010-2013 Red Hat, Inc. All rights reserved.
Packit bf408e
 *
Packit bf408e
 * This program is free software; you can redistribute it and/or modify
Packit bf408e
 * it under the terms of the GNU General Public License as published by
Packit bf408e
 * the Free Software Foundation; either version 2 of the License, or
Packit bf408e
 * (at your option) any later version.
Packit bf408e
 *
Packit bf408e
 * This program is distributed in the hope that it will be useful,
Packit bf408e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bf408e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit bf408e
 * GNU General Public License for more details.
Packit bf408e
 *
Packit bf408e
 */ 
Packit bf408e
#ifdef ALPHA
Packit bf408e
#include "defs.h"
Packit bf408e
Packit bf408e
static void alpha_back_trace(struct gnu_request *, struct bt_info *);
Packit bf408e
static int alpha_trace_status(struct gnu_request *, struct bt_info *);
Packit bf408e
static void alpha_exception_frame(ulong, ulong, 
Packit bf408e
	struct gnu_request *, struct bt_info *);
Packit bf408e
static void alpha_frame_offset(struct gnu_request *, ulong);
Packit bf408e
static int alpha_backtrace_resync(struct gnu_request *, ulong,
Packit bf408e
	struct bt_info *);
Packit bf408e
static void alpha_print_stack_entry(struct gnu_request *, ulong, 
Packit bf408e
	char *, ulong, struct bt_info *);
Packit bf408e
static int alpha_resync_speculate(struct gnu_request *, ulong,struct bt_info *);
Packit bf408e
static int alpha_dis_filter(ulong, char *, unsigned int);
Packit bf408e
static void dis_address_translation(ulong, char *, unsigned int);
Packit bf408e
static void alpha_cmd_mach(void);
Packit bf408e
static int alpha_get_smp_cpus(void);
Packit bf408e
static void alpha_display_machine_stats(void);
Packit bf408e
static void alpha_dump_line_number(char *, ulong);
Packit bf408e
static void display_hwrpb(unsigned int);
Packit bf408e
static void alpha_post_init(void);
Packit bf408e
static struct line_number_hook alpha_line_number_hooks[];
Packit bf408e
Packit bf408e
Packit bf408e
#define ALPHA_CONTINUE_TRACE     (1)
Packit bf408e
#define ALPHA_END_OF_TRACE       (2)
Packit bf408e
#define ALPHA_EXCEPTION_FRAME    (3)
Packit bf408e
#define ALPHA_SYSCALL_FRAME      (4)
Packit bf408e
#define ALPHA_MM_FAULT           (5)
Packit bf408e
#define ALPHA_INTERRUPT_PENDING  (6)
Packit bf408e
#define ALPHA_RESCHEDULE         (7)
Packit bf408e
#define ALPHA_DOWN_FAILED        (8)
Packit bf408e
#define ALPHA_RET_FROM_SMP_FORK  (9)
Packit bf408e
#define ALPHA_SIGNAL_RETURN     (10)
Packit bf408e
#define ALPHA_STRACE            (11)
Packit bf408e
Packit bf408e
static int alpha_eframe_search(struct bt_info *);
Packit bf408e
static int alpha_uvtop(struct task_context *, ulong, physaddr_t *, int);
Packit bf408e
static int alpha_kvtop(struct task_context *, ulong, physaddr_t *, int);
Packit bf408e
static void alpha_back_trace_cmd(struct bt_info *);
Packit bf408e
static ulong alpha_get_task_pgd(ulong task);
Packit bf408e
static ulong alpha_processor_speed(void);
Packit bf408e
static void alpha_dump_irq(int);
Packit bf408e
static void alpha_get_stack_frame(struct bt_info *, ulong *, ulong *);
Packit bf408e
static void get_alpha_frame(struct bt_info *, ulong *, ulong *);
Packit bf408e
static int verify_user_eframe(struct bt_info *, ulong, ulong);
Packit bf408e
static int alpha_translate_pte(ulong, void *, ulonglong);
Packit bf408e
static uint64_t alpha_memory_size(void);
Packit bf408e
static ulong alpha_vmalloc_start(void);
Packit bf408e
static int alpha_is_task_addr(ulong);
Packit bf408e
static int alpha_verify_symbol(const char *, ulong, char);
Packit bf408e
Packit bf408e
struct percpu_data {
Packit bf408e
	ulong halt_PC;
Packit bf408e
	ulong halt_ra;
Packit bf408e
	ulong halt_pv;
Packit bf408e
};
Packit bf408e
#define GET_HALT_PC  0x1
Packit bf408e
#define GET_HALT_RA  0x2
Packit bf408e
#define GET_HALT_PV  0x3
Packit bf408e
static ulong get_percpu_data(int, ulong, struct percpu_data *);
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Do all necessary machine-specific setup here.  This is called three times,
Packit bf408e
 *  before symbol table initialization, and before and after GDB has been 
Packit bf408e
 *  initialized.
Packit bf408e
 */
Packit bf408e
void
Packit bf408e
alpha_init(int when)
Packit bf408e
{
Packit bf408e
	int tmp;
Packit bf408e
Packit bf408e
	switch (when)
Packit bf408e
	{
Packit bf408e
	case PRE_SYMTAB:
Packit bf408e
		machdep->verify_symbol = alpha_verify_symbol;
Packit bf408e
                if (pc->flags & KERNEL_DEBUG_QUERY)
Packit bf408e
                        return;
Packit bf408e
                machdep->pagesize = memory_page_size();
Packit bf408e
                machdep->pageshift = ffs(machdep->pagesize) - 1;
Packit bf408e
                machdep->pageoffset = machdep->pagesize - 1;
Packit bf408e
                machdep->pagemask = ~(machdep->pageoffset);
Packit bf408e
		machdep->stacksize = machdep->pagesize * 2;
Packit bf408e
                if ((machdep->pgd = (char *)malloc(PAGESIZE())) == NULL)
Packit bf408e
                        error(FATAL, "cannot malloc pgd space.");
Packit bf408e
                if ((machdep->pmd = (char *)malloc(PAGESIZE())) == NULL)
Packit bf408e
                        error(FATAL, "cannot malloc pmd space.");
Packit bf408e
                if ((machdep->ptbl = (char *)malloc(PAGESIZE())) == NULL)
Packit bf408e
                        error(FATAL, "cannot malloc ptbl space.");
Packit bf408e
                machdep->last_pgd_read = 0;
Packit bf408e
                machdep->last_pmd_read = 0;
Packit bf408e
                machdep->last_ptbl_read = 0;
Packit bf408e
		machdep->verify_paddr = generic_verify_paddr;
Packit bf408e
		machdep->ptrs_per_pgd = PTRS_PER_PGD;
Packit bf408e
		break;
Packit bf408e
		
Packit bf408e
	case PRE_GDB:
Packit bf408e
	        switch (symbol_value("_stext") & KSEG_BASE)
Packit bf408e
	        {
Packit bf408e
	        case KSEG_BASE:
Packit bf408e
	                machdep->kvbase = KSEG_BASE;
Packit bf408e
	                break;
Packit bf408e
	
Packit bf408e
	        case KSEG_BASE_48_BIT:
Packit bf408e
	                machdep->kvbase = KSEG_BASE_48_BIT;
Packit bf408e
	                break;
Packit bf408e
	
Packit bf408e
	        default:
Packit bf408e
	                error(FATAL, 
Packit bf408e
			    "cannot determine KSEG base from _stext: %lx\n",
Packit bf408e
	                        symbol_value("_stext"));
Packit bf408e
	        }
Packit bf408e
Packit bf408e
		machdep->identity_map_base = machdep->kvbase;
Packit bf408e
		machdep->is_kvaddr = generic_is_kvaddr;
Packit bf408e
                machdep->is_uvaddr = generic_is_uvaddr;
Packit bf408e
	        machdep->eframe_search = alpha_eframe_search;
Packit bf408e
	        machdep->back_trace = alpha_back_trace_cmd;
Packit bf408e
	        machdep->processor_speed = alpha_processor_speed;
Packit bf408e
	        machdep->uvtop = alpha_uvtop;
Packit bf408e
	        machdep->kvtop = alpha_kvtop;
Packit bf408e
	        machdep->get_task_pgd = alpha_get_task_pgd;
Packit bf408e
		if (symbol_exists("irq_desc"))
Packit bf408e
			machdep->dump_irq = generic_dump_irq;
Packit bf408e
		else
Packit bf408e
			machdep->dump_irq = alpha_dump_irq;
Packit bf408e
		machdep->get_stack_frame = alpha_get_stack_frame;
Packit bf408e
		machdep->get_stackbase = generic_get_stackbase;
Packit bf408e
		machdep->get_stacktop = generic_get_stacktop;
Packit bf408e
		machdep->translate_pte = alpha_translate_pte;
Packit bf408e
		machdep->memory_size = alpha_memory_size;
Packit bf408e
		machdep->vmalloc_start = alpha_vmalloc_start;
Packit bf408e
		machdep->is_task_addr = alpha_is_task_addr;
Packit bf408e
		if (symbol_exists("console_crash")) {
Packit bf408e
			get_symbol_data("console_crash", sizeof(int), &tmp);
Packit bf408e
			if (tmp)
Packit bf408e
				machdep->flags |= HWRESET;
Packit bf408e
		}
Packit bf408e
		machdep->dis_filter = alpha_dis_filter;
Packit bf408e
		machdep->cmd_mach = alpha_cmd_mach;
Packit bf408e
		machdep->get_smp_cpus = alpha_get_smp_cpus;
Packit bf408e
		machdep->line_number_hooks = alpha_line_number_hooks;
Packit bf408e
		machdep->value_to_symbol = generic_machdep_value_to_symbol;
Packit bf408e
                machdep->init_kernel_pgd = NULL;
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	case POST_GDB:
Packit bf408e
		MEMBER_OFFSET_INIT(thread_struct_ptbr, 
Packit bf408e
			"thread_struct", "ptbr");
Packit bf408e
		MEMBER_OFFSET_INIT(hwrpb_struct_cycle_freq, 
Packit bf408e
			"hwrpb_struct", "cycle_freq");
Packit bf408e
		MEMBER_OFFSET_INIT(hwrpb_struct_processor_offset,
Packit bf408e
			"hwrpb_struct", "processor_offset");
Packit bf408e
		MEMBER_OFFSET_INIT(hwrpb_struct_processor_size,
Packit bf408e
			"hwrpb_struct", "processor_size");
Packit bf408e
		MEMBER_OFFSET_INIT(percpu_struct_halt_PC,
Packit bf408e
			"percpu_struct", "halt_PC");
Packit bf408e
		MEMBER_OFFSET_INIT(percpu_struct_halt_ra, 
Packit bf408e
			"percpu_struct", "halt_ra");
Packit bf408e
                MEMBER_OFFSET_INIT(percpu_struct_halt_pv,
Packit bf408e
                        "percpu_struct", "halt_pv");
Packit bf408e
		MEMBER_OFFSET_INIT(switch_stack_r26,
Packit bf408e
			"switch_stack", "r26");
Packit bf408e
        	if (symbol_exists("irq_action"))
Packit bf408e
			ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_action, 
Packit bf408e
				"irq_action", NULL, 0);
Packit bf408e
        	else if (symbol_exists("irq_desc"))
Packit bf408e
                	ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc, 
Packit bf408e
				"irq_desc", NULL, 0);
Packit bf408e
        	else
Packit bf408e
                	machdep->nr_irqs = 0;
Packit bf408e
		if (!machdep->hz)
Packit bf408e
			machdep->hz = HZ;
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	case POST_INIT:
Packit bf408e
		alpha_post_init();
Packit bf408e
		break;
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Unroll a kernel stack.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
alpha_back_trace_cmd(struct bt_info *bt)
Packit bf408e
{
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	struct gnu_request *req;
Packit bf408e
Packit bf408e
        bt->flags |= BT_EXCEPTION_FRAME;
Packit bf408e
Packit bf408e
        if (CRASHDEBUG(1) || bt->debug)
Packit bf408e
                fprintf(fp, " => PC: %lx (%s) FP: %lx \n",
Packit bf408e
                        bt->instptr, value_to_symstr(bt->instptr, buf, 0),
Packit bf408e
			bt->stkptr );
Packit bf408e
Packit bf408e
        req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
Packit bf408e
        req->command = GNU_STACK_TRACE;
Packit bf408e
        req->flags = GNU_RETURN_ON_ERROR;
Packit bf408e
        req->buf = GETBUF(BUFSIZE);
Packit bf408e
        req->debug = bt->debug;
Packit bf408e
        req->task = bt->task;
Packit bf408e
Packit bf408e
        req->pc = bt->instptr;
Packit bf408e
        req->sp = bt->stkptr;
Packit bf408e
Packit bf408e
        if (bt->flags & BT_USE_GDB) {
Packit bf408e
                strcpy(req->buf, "backtrace");
Packit bf408e
                gdb_interface(req);
Packit bf408e
        }
Packit bf408e
        else
Packit bf408e
                alpha_back_trace(req, bt);
Packit bf408e
Packit bf408e
        FREEBUF(req->buf);
Packit bf408e
        FREEBUF(req);
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Unroll the kernel stack.
Packit bf408e
 */
Packit bf408e
Packit bf408e
#define ALPHA_BACKTRACE_SPECULATE(X) 				        \
Packit bf408e
{									\
Packit bf408e
        speculate_location = X;				                \
Packit bf408e
							                \
Packit bf408e
        if (bt->flags & BT_SPECULATE)					\
Packit bf408e
                return;							\
Packit bf408e
									\
Packit bf408e
        BZERO(btloc, sizeof(struct bt_info));                           \
Packit bf408e
	btloc->task = req->task;                                        \
Packit bf408e
	btloc->tc = bt->tc;                                             \
Packit bf408e
	btloc->stackbase = bt->stackbase;                               \
Packit bf408e
	btloc->stacktop = bt->stacktop;                                 \
Packit bf408e
	btloc->flags = BT_TEXT_SYMBOLS_NOPRINT;                         \
Packit bf408e
        hook.eip = 0; 					                \
Packit bf408e
	hook.esp = req->lastsp ? req->lastsp + sizeof(long) : 0;        \
Packit bf408e
	btloc->hp = &hook;                                              \
Packit bf408e
									\
Packit bf408e
        back_trace(btloc);	                                        \
Packit bf408e
									\
Packit bf408e
        if (hook.esp && hook.eip) {					\
Packit bf408e
                req->hookp = &hook;					\
Packit bf408e
                if (alpha_resync_speculate(req, bt->flags, bt)) {	\
Packit bf408e
                        req->pc = hook.eip;				\
Packit bf408e
                        req->sp = hook.esp;				\
Packit bf408e
                        continue; 					\
Packit bf408e
                }							\
Packit bf408e
		goto show_remaining_text;			        \
Packit bf408e
        }								\
Packit bf408e
	goto show_remaining_text;					\
Packit bf408e
}								
Packit bf408e
Packit bf408e
Packit bf408e
static void
Packit bf408e
alpha_back_trace(struct gnu_request *req, struct bt_info *bt)
Packit bf408e
{
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
        int frame;
Packit bf408e
	int done;
Packit bf408e
	int status;
Packit bf408e
        struct stack_hook hook;
Packit bf408e
	int eframe_same_pc_ra_function;
Packit bf408e
	int speculate_location;
Packit bf408e
	struct bt_info bt_info, *btloc;
Packit bf408e
Packit bf408e
	frame = 0;
Packit bf408e
	req->curframe = 0;
Packit bf408e
	btloc = &bt_info;
Packit bf408e
Packit bf408e
	if (!IS_KVADDR(req->pc)) {
Packit bf408e
		if (BT_REFERENCE_CHECK(bt))
Packit bf408e
			return;
Packit bf408e
Packit bf408e
		if ((machdep->flags & HWRESET) && is_task_active(req->task)) {
Packit bf408e
			fprintf(fp, "(hardware reset while in user space)\n");
Packit bf408e
			return;
Packit bf408e
		}
Packit bf408e
		
Packit bf408e
		fprintf(fp, "invalid pc: %lx\n", req->pc); 
Packit bf408e
Packit bf408e
        	alpha_exception_frame(USER_EFRAME_ADDR(req->task),  
Packit bf408e
			BT_USER_EFRAME, req, bt);
Packit bf408e
Packit bf408e
		return;
Packit bf408e
	}
Packit bf408e
Packit bf408e
Packit bf408e
        for (done = FALSE; !done && (frame < 100); frame++) {
Packit bf408e
Packit bf408e
		speculate_location = 0;
Packit bf408e
Packit bf408e
		if ((req->name = closest_symbol(req->pc)) == NULL) {
Packit bf408e
			req->ra = req->pc = 0;
Packit bf408e
                        if (alpha_backtrace_resync(req, 
Packit bf408e
			    bt->flags | BT_FROM_CALLFRAME, bt)) 
Packit bf408e
                       		continue; 
Packit bf408e
Packit bf408e
			if (BT_REFERENCE_FOUND(bt))
Packit bf408e
				return;
Packit bf408e
Packit bf408e
			ALPHA_BACKTRACE_SPECULATE(1);
Packit bf408e
		}
Packit bf408e
Packit bf408e
                if (!INSTACK(req->sp, bt))
Packit bf408e
                        break;
Packit bf408e
Packit bf408e
		if (!is_kernel_text(req->pc)) 
Packit bf408e
			ALPHA_BACKTRACE_SPECULATE(2);
Packit bf408e
Packit bf408e
		alpha_print_stack_entry(req, req->pc, req->name,
Packit bf408e
			bt->flags | BT_SAVE_LASTSP, bt);
Packit bf408e
Packit bf408e
		if (BT_REFERENCE_FOUND(bt))
Packit bf408e
			return;
Packit bf408e
Packit bf408e
		switch (status = alpha_trace_status(req, bt))
Packit bf408e
		{
Packit bf408e
		case ALPHA_CONTINUE_TRACE:
Packit bf408e
			alpha_frame_offset(req, 0);
Packit bf408e
			if (!req->value) {
Packit bf408e
				done = TRUE;
Packit bf408e
				break;
Packit bf408e
			}
Packit bf408e
			req->prevpc = req->pc;
Packit bf408e
			req->pc = GET_STACK_ULONG(req->sp);
Packit bf408e
			req->prevsp = req->sp;
Packit bf408e
                        req->sp += req->value;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case ALPHA_END_OF_TRACE:
Packit bf408e
			done = TRUE;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case ALPHA_STRACE:
Packit bf408e
                        alpha_exception_frame(req->sp, 
Packit bf408e
				BT_USER_EFRAME|BT_STRACE, req, bt);
Packit bf408e
                        done = TRUE;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case ALPHA_RET_FROM_SMP_FORK:
Packit bf408e
                        alpha_exception_frame(USER_EFRAME_ADDR(req->task), 
Packit bf408e
				BT_USER_EFRAME|BT_RET_FROM_SMP_FORK, req, bt);
Packit bf408e
			done = TRUE;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
                case ALPHA_DOWN_FAILED:
Packit bf408e
                        frame++;
Packit bf408e
                        alpha_print_stack_entry(req,
Packit bf408e
                                req->pc, closest_symbol(req->pc),
Packit bf408e
                                bt->flags | BT_SAVE_LASTSP, bt);
Packit bf408e
Packit bf408e
			if (BT_REFERENCE_FOUND(bt))
Packit bf408e
				return;
Packit bf408e
Packit bf408e
                        alpha_frame_offset(req, 0);
Packit bf408e
                        if (!req->value) {
Packit bf408e
                                done = TRUE;
Packit bf408e
                                break;
Packit bf408e
                        }
Packit bf408e
                        req->prevpc = req->pc;
Packit bf408e
			req->pc = GET_STACK_ULONG(req->sp);
Packit bf408e
                        req->prevsp = req->sp;
Packit bf408e
                        req->sp += req->value;
Packit bf408e
                        break;
Packit bf408e
Packit bf408e
                case ALPHA_RESCHEDULE:
Packit bf408e
                        alpha_exception_frame(USER_EFRAME_ADDR(req->task),
Packit bf408e
                                BT_USER_EFRAME|BT_RESCHEDULE, req, bt);
Packit bf408e
                        done = TRUE;
Packit bf408e
                        break;
Packit bf408e
Packit bf408e
		case ALPHA_MM_FAULT:
Packit bf408e
                        alpha_exception_frame(req->sp, bt->flags, req, bt);
Packit bf408e
Packit bf408e
                        if (!IS_KVADDR(req->pc)) {
Packit bf408e
				done = TRUE;
Packit bf408e
                                break;
Packit bf408e
			}
Packit bf408e
Packit bf408e
                        alpha_frame_offset(req, 0);
Packit bf408e
                        if (!req->value) {
Packit bf408e
                                done = TRUE;
Packit bf408e
                                break;
Packit bf408e
                        }
Packit bf408e
Packit bf408e
                        frame++;
Packit bf408e
			alpha_print_stack_entry(req,
Packit bf408e
				req->pc, closest_symbol(req->pc), 
Packit bf408e
				bt->flags | BT_SAVE_LASTSP, bt);
Packit bf408e
Packit bf408e
			if (BT_REFERENCE_FOUND(bt))
Packit bf408e
				return;
Packit bf408e
Packit bf408e
                        if (!IS_KVADDR(req->pc)) {
Packit bf408e
                                done = TRUE;
Packit bf408e
				break;
Packit bf408e
			}
Packit bf408e
Packit bf408e
			req->prevpc = req->pc;
Packit bf408e
			req->pc = GET_STACK_ULONG(req->sp);
Packit bf408e
			req->prevsp = req->sp;
Packit bf408e
                        req->sp += req->value;
Packit bf408e
                        break;
Packit bf408e
Packit bf408e
		case ALPHA_SYSCALL_FRAME:
Packit bf408e
			req->sp = verify_user_eframe(bt, req->task, req->sp) ?
Packit bf408e
				req->sp : USER_EFRAME_ADDR(req->task);
Packit bf408e
Packit bf408e
                        alpha_exception_frame(req->sp, bt->flags, req, bt);
Packit bf408e
Packit bf408e
			if (!IS_KVADDR(req->pc)) {
Packit bf408e
				done = TRUE;
Packit bf408e
				break;
Packit bf408e
			}
Packit bf408e
Packit bf408e
			alpha_frame_offset(req, 0);
Packit bf408e
                        if (!req->value) {
Packit bf408e
                                done = TRUE;
Packit bf408e
                                break;
Packit bf408e
                        }
Packit bf408e
			req->prevpc = req->pc;
Packit bf408e
			req->pc = GET_STACK_ULONG(req->sp);
Packit bf408e
			req->prevsp = req->sp;
Packit bf408e
                        req->sp += req->value;
Packit bf408e
                        break;
Packit bf408e
Packit bf408e
		case ALPHA_SIGNAL_RETURN:
Packit bf408e
                        alpha_exception_frame(USER_EFRAME_ADDR(req->task),
Packit bf408e
                                bt->flags, req, bt);
Packit bf408e
			done = TRUE;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case ALPHA_EXCEPTION_FRAME:
Packit bf408e
			alpha_frame_offset(req, 0);
Packit bf408e
                        if (!req->value) {
Packit bf408e
				fprintf(fp, 
Packit bf408e
                       "ALPHA EXCEPTION FRAME w/no frame offset for %lx (%s)\n",
Packit bf408e
					req->pc, 
Packit bf408e
					value_to_symstr(req->pc, buf, 0));
Packit bf408e
                                done = TRUE;
Packit bf408e
                                break;
Packit bf408e
                        }
Packit bf408e
Packit bf408e
			alpha_exception_frame(req->sp + req->value, 
Packit bf408e
				bt->flags, req, bt);
Packit bf408e
Packit bf408e
			if (!IS_KVADDR(req->pc)) {
Packit bf408e
                                done = TRUE;
Packit bf408e
                                break;
Packit bf408e
			}
Packit bf408e
Packit bf408e
			alpha_frame_offset(req, 0);
Packit bf408e
Packit bf408e
                        if (!req->value) {
Packit bf408e
                                fprintf(fp,
Packit bf408e
                       "ALPHA EXCEPTION FRAME w/no frame offset for %lx (%s)\n",
Packit bf408e
                                        req->pc, 
Packit bf408e
					value_to_symstr(req->pc, buf, 0));
Packit bf408e
                                done = TRUE;
Packit bf408e
                                break;
Packit bf408e
                        }
Packit bf408e
			
Packit bf408e
			eframe_same_pc_ra_function = 
Packit bf408e
				SAME_FUNCTION(req->pc, req->ra);
Packit bf408e
	
Packit bf408e
			frame++;
Packit bf408e
			alpha_print_stack_entry(req, req->pc,
Packit bf408e
				closest_symbol(req->pc), 
Packit bf408e
				bt->flags | BT_SAVE_LASTSP, bt);
Packit bf408e
Packit bf408e
			if (BT_REFERENCE_FOUND(bt))
Packit bf408e
				return;
Packit bf408e
Packit bf408e
			if (!IS_KVADDR(req->pc)) {
Packit bf408e
				done = TRUE;
Packit bf408e
				break;
Packit bf408e
			}
Packit bf408e
Packit bf408e
			if (STREQ(closest_symbol(req->pc), 
Packit bf408e
			    "ret_from_reschedule")) {
Packit bf408e
                        	alpha_exception_frame(
Packit bf408e
				    USER_EFRAME_ADDR(req->task), 
Packit bf408e
				    BT_USER_EFRAME|BT_RESCHEDULE, req, bt);
Packit bf408e
                        	done = TRUE;
Packit bf408e
				break;
Packit bf408e
			}
Packit bf408e
Packit bf408e
			req->prevpc = req->pc;
Packit bf408e
			req->pc = GET_STACK_ULONG(req->sp);
Packit bf408e
Packit bf408e
			if (!is_kernel_text(req->pc)) {
Packit bf408e
				if (alpha_backtrace_resync(req, 
Packit bf408e
				    bt->flags | BT_FROM_EXCEPTION, bt))
Packit bf408e
					break;
Packit bf408e
Packit bf408e
				if (BT_REFERENCE_FOUND(bt))
Packit bf408e
					return;
Packit bf408e
Packit bf408e
				ALPHA_BACKTRACE_SPECULATE(3);
Packit bf408e
			}
Packit bf408e
Packit bf408e
			if (!eframe_same_pc_ra_function && 
Packit bf408e
			    (req->pc != req->ra)) {
Packit bf408e
				req->pc = req->ra;
Packit bf408e
				break;
Packit bf408e
			}
Packit bf408e
Packit bf408e
			req->prevsp = req->sp;
Packit bf408e
                        req->sp += req->value;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case ALPHA_INTERRUPT_PENDING:
Packit bf408e
			alpha_frame_offset(req, 0);
Packit bf408e
                        if (!req->value) {
Packit bf408e
				req->prevpc = req->pc;
Packit bf408e
                                req->pc = req->addr;
Packit bf408e
				req->prevsp = req->sp;
Packit bf408e
				req->sp = req->frame;
Packit bf408e
                        } else {
Packit bf408e
				req->prevpc = req->pc;
Packit bf408e
				req->pc = GET_STACK_ULONG(req->sp);
Packit bf408e
				req->prevsp = req->sp;
Packit bf408e
                        	req->sp += req->value;
Packit bf408e
			}
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e
        }
Packit bf408e
Packit bf408e
	return;
Packit bf408e
Packit bf408e
show_remaining_text:
Packit bf408e
Packit bf408e
	if (BT_REFERENCE_CHECK(bt))
Packit bf408e
		return;
Packit bf408e
Packit bf408e
        BZERO(btloc, sizeof(struct bt_info));                         
Packit bf408e
        btloc->task = req->task;                                       
Packit bf408e
	btloc->tc = bt->tc;
Packit bf408e
	btloc->stackbase = bt->stackbase;
Packit bf408e
	btloc->stacktop = bt->stacktop;
Packit bf408e
        btloc->flags = BT_TEXT_SYMBOLS_NOPRINT;                        
Packit bf408e
        hook.esp = req->lastsp + sizeof(long);
Packit bf408e
        btloc->hp = &hook; 
Packit bf408e
        back_trace(btloc);
Packit bf408e
Packit bf408e
        if (hook.eip) {
Packit bf408e
       		fprintf(fp,
Packit bf408e
"NOTE: cannot resolve trace from this point -- remaining text symbols on stack:\n");
Packit bf408e
		btloc->flags = BT_TEXT_SYMBOLS_PRINT|BT_ERROR_MASK;
Packit bf408e
        	hook.esp = req->lastsp + sizeof(long);
Packit bf408e
        	back_trace(btloc);
Packit bf408e
	} else 
Packit bf408e
       		fprintf(fp, 
Packit bf408e
"NOTE: cannot resolve trace from this point -- no remaining text symbols\n");
Packit bf408e
Packit bf408e
	if (CRASHDEBUG(1))
Packit bf408e
		fprintf(fp, "speculate_location: %d\n", speculate_location);
Packit bf408e
Packit bf408e
	alpha_exception_frame(USER_EFRAME_ADDR(req->task), 
Packit bf408e
		BT_USER_EFRAME, req, bt);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  print one entry of a stack trace
Packit bf408e
 */
Packit bf408e
static void 
Packit bf408e
alpha_print_stack_entry(struct gnu_request *req, 
Packit bf408e
			ulong callpc, 	
Packit bf408e
			char *name, 
Packit bf408e
			ulong flags,
Packit bf408e
			struct bt_info *bt)
Packit bf408e
{
Packit bf408e
	struct load_module *lm;
Packit bf408e
Packit bf408e
	if (BT_REFERENCE_CHECK(bt)) {
Packit bf408e
                switch (bt->ref->cmdflags & (BT_REF_SYMBOL|BT_REF_HEXVAL))
Packit bf408e
                {
Packit bf408e
                case BT_REF_SYMBOL:
Packit bf408e
			if (STREQ(name, bt->ref->str) ||
Packit bf408e
			    (STREQ(name, "strace") && 
Packit bf408e
			    STREQ(bt->ref->str, "entSys"))) {
Packit bf408e
				bt->ref->cmdflags |= BT_REF_FOUND;
Packit bf408e
			} 
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case BT_REF_HEXVAL:
Packit bf408e
			if (bt->ref->hexval == callpc)
Packit bf408e
				bt->ref->cmdflags |= BT_REF_FOUND;
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e
	} else {
Packit bf408e
		fprintf(fp, "%s#%d [%lx] %s at %lx",
Packit bf408e
        		req->curframe < 10 ? " " : "", req->curframe, req->sp,
Packit bf408e
			STREQ(name, "strace") ?  "strace (via entSys)" : name, 
Packit bf408e
			callpc);
Packit bf408e
		if (module_symbol(callpc, NULL, &lm, NULL, 0))
Packit bf408e
			fprintf(fp, " [%s]", lm->mod_name);
Packit bf408e
		fprintf(fp, "\n");
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (!(flags & BT_SPECULATE))
Packit bf408e
		req->curframe++;
Packit bf408e
Packit bf408e
	if (flags & BT_SAVE_LASTSP)
Packit bf408e
		req->lastsp = req->sp;
Packit bf408e
Packit bf408e
	if (BT_REFERENCE_CHECK(bt))
Packit bf408e
		return;
Packit bf408e
Packit bf408e
	if (flags & BT_LINE_NUMBERS) 
Packit bf408e
		alpha_dump_line_number(name, callpc);
Packit bf408e
}
Packit bf408e
Packit bf408e
static const char *hook_files[] = {
Packit bf408e
        "arch/alpha/kernel/entry.S",
Packit bf408e
        "arch/alpha/kernel/head.S",
Packit bf408e
	"init/main.c",
Packit bf408e
        "arch/alpha/kernel/smp.c",
Packit bf408e
};
Packit bf408e
Packit bf408e
#define ENTRY_S      ((char **)&hook_files[0])
Packit bf408e
#define HEAD_S       ((char **)&hook_files[1])
Packit bf408e
#define MAIN_C       ((char **)&hook_files[2])
Packit bf408e
#define SMP_C        ((char **)&hook_files[3])
Packit bf408e
Packit bf408e
static struct line_number_hook alpha_line_number_hooks[] = {
Packit bf408e
	{"entInt", ENTRY_S},
Packit bf408e
	{"entMM", ENTRY_S},
Packit bf408e
	{"entArith", ENTRY_S},
Packit bf408e
	{"entIF", ENTRY_S},
Packit bf408e
	{"entDbg", ENTRY_S},
Packit bf408e
	{"kernel_clone", ENTRY_S},
Packit bf408e
	{"kernel_thread", ENTRY_S},
Packit bf408e
	{"__kernel_execve", ENTRY_S},
Packit bf408e
	{"do_switch_stack", ENTRY_S},
Packit bf408e
	{"undo_switch_stack", ENTRY_S},
Packit bf408e
	{"entUna", ENTRY_S},
Packit bf408e
	{"entUnaUser", ENTRY_S},
Packit bf408e
	{"sys_fork", ENTRY_S},
Packit bf408e
	{"sys_clone", ENTRY_S},
Packit bf408e
	{"sys_vfork", ENTRY_S},
Packit bf408e
	{"alpha_switch_to", ENTRY_S},
Packit bf408e
	{"entSys", ENTRY_S},
Packit bf408e
	{"ret_from_sys_call", ENTRY_S},
Packit bf408e
	{"ret_from_reschedule", ENTRY_S},
Packit bf408e
	{"restore_all", ENTRY_S},
Packit bf408e
	{"strace", ENTRY_S},
Packit bf408e
	{"strace_success", ENTRY_S},
Packit bf408e
	{"strace_error", ENTRY_S},
Packit bf408e
	{"syscall_error", ENTRY_S},
Packit bf408e
	{"ret_success", ENTRY_S},
Packit bf408e
	{"signal_return", ENTRY_S},
Packit bf408e
	{"ret_from_fork", ENTRY_S},
Packit bf408e
	{"reschedule", ENTRY_S},
Packit bf408e
	{"sys_sigreturn", ENTRY_S},
Packit bf408e
	{"sys_rt_sigreturn", ENTRY_S},
Packit bf408e
	{"sys_sigsuspend", ENTRY_S},
Packit bf408e
	{"sys_rt_sigsuspend", ENTRY_S},
Packit bf408e
	{"ret_from_smpfork", ENTRY_S},
Packit bf408e
Packit bf408e
	{"_stext", HEAD_S},
Packit bf408e
	{"__start", HEAD_S},
Packit bf408e
	{"__smp_callin", HEAD_S},
Packit bf408e
	{"cserve_ena", HEAD_S},
Packit bf408e
	{"cserve_dis", HEAD_S},
Packit bf408e
	{"halt", HEAD_S},
Packit bf408e
Packit bf408e
	{"start_kernel", MAIN_C},
Packit bf408e
Packit bf408e
	{"smp_callin", SMP_C},
Packit bf408e
Packit bf408e
       {NULL, NULL}    /* list must be NULL-terminated */
Packit bf408e
};
Packit bf408e
Packit bf408e
static void
Packit bf408e
alpha_dump_line_number(char *name, ulong callpc)
Packit bf408e
{
Packit bf408e
        char buf[BUFSIZE], *p;
Packit bf408e
        int retries;
Packit bf408e
Packit bf408e
	retries = 0;
Packit bf408e
try_closest:
Packit bf408e
	get_line_number(callpc, buf, FALSE);
Packit bf408e
	if (strlen(buf)) {
Packit bf408e
		if (retries) {
Packit bf408e
			p = strstr(buf, ": ");
Packit bf408e
			if (p)
Packit bf408e
				*p = NULLCHAR;
Packit bf408e
		} 
Packit bf408e
		fprintf(fp, "    %s\n", buf);
Packit bf408e
	} else {
Packit bf408e
		if (retries)
Packit bf408e
			fprintf(fp, GDB_PATCHED() ? 
Packit bf408e
			  "" : "    (cannot determine file and line number)\n");
Packit bf408e
		else {
Packit bf408e
			retries++;
Packit bf408e
			callpc = closest_symbol_value(callpc);
Packit bf408e
			goto try_closest;
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Look for the frame size storage at the beginning of a function.
Packit bf408e
 *  If it's not obvious, try gdb.
Packit bf408e
 *
Packit bf408e
 *  For future reference, here's where the numbers come from:
Packit bf408e
 *
Packit bf408e
 *    0xfffffc00003217e8 <schedule+8>:        subq    sp,0x50,sp
Packit bf408e
 *    fffffc00003217e8:  43ca153e
Packit bf408e
 *    010000 11110 01010000 1 0101001 11110
Packit bf408e
 *    
Packit bf408e
 *    0xfffffc0000321668 <schedule_timeout+8>:        subq    sp,0x60,sp
Packit bf408e
 *    fffffc0000321668:  43cc153e
Packit bf408e
 *    010000 11110 01100000 1 0101001 11110
Packit bf408e
 *    
Packit bf408e
 *    0xfffffc000035d028 <do_select+8>:       subq    sp,0x70,sp
Packit bf408e
 *    fffffc000035d028:  43ce153e
Packit bf408e
 *    010000 11110 01110000 1 0101001 11110
Packit bf408e
 *    
Packit bf408e
 *    0100 0011 110x xxxx xxx1 0101 0011 1110
Packit bf408e
 *    1111 1111 111x xxxx xxx1 1111 1111 1111
Packit bf408e
 *    0000 0000 0001 1111 1110 0000 0000 0000
Packit bf408e
 *       f    f    e    0    1    f    f    f  instruction mask
Packit bf408e
 *       0    0    1    f    e    0    0    0  offset
Packit bf408e
 *    
Packit bf408e
 *    stq     ra,0(sp)
Packit bf408e
 *    fffffc000035d034:  b75e0000
Packit bf408e
 */
Packit bf408e
Packit bf408e
static void
Packit bf408e
alpha_frame_offset(struct gnu_request *req, ulong alt_pc)
Packit bf408e
{
Packit bf408e
	uint *ip, ival;
Packit bf408e
	ulong value;
Packit bf408e
Packit bf408e
	req->value = value = 0;
Packit bf408e
Packit bf408e
	if (alt_pc && !is_kernel_text(alt_pc))
Packit bf408e
		error(FATAL, 
Packit bf408e
		    "trying to get frame offset of non-text address: %lx\n",
Packit bf408e
			alt_pc);
Packit bf408e
	else if (!alt_pc && !is_kernel_text(req->pc))
Packit bf408e
                error(FATAL, 
Packit bf408e
                    "trying to get frame offset of non-text address: %lx\n",
Packit bf408e
                        req->pc);
Packit bf408e
Packit bf408e
	ip = alt_pc ? (int *)closest_symbol_value(alt_pc) :
Packit bf408e
		      (int *)closest_symbol_value(req->pc);
Packit bf408e
	if (!ip)
Packit bf408e
		goto use_gdb;
Packit bf408e
Packit bf408e
	ival = 0;
Packit bf408e
Packit bf408e
 	/*  
Packit bf408e
	 *  Don't go any farther than "stq ra,0(sp)" (0xb75e0000)
Packit bf408e
	 */
Packit bf408e
	while (ival != 0xb75e0000) {
Packit bf408e
		if (!text_value_cache((ulong)ip, 0, &ival)) {
Packit bf408e
	        	readmem((ulong)ip, KVADDR, &ival,
Packit bf408e
                		sizeof(uint), "uncached text value", 
Packit bf408e
				FAULT_ON_ERROR); 
Packit bf408e
			text_value_cache((ulong)ip, ival, NULL);
Packit bf408e
		}
Packit bf408e
Packit bf408e
		if ((ival & 0xffe01fff) == 0x43c0153e) {
Packit bf408e
			value = (ival & 0x1fe000) >> 13;
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e
		ip++;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (value) {
Packit bf408e
		req->value = value;
Packit bf408e
		return;
Packit bf408e
	}
Packit bf408e
Packit bf408e
use_gdb:
Packit bf408e
#ifndef GDB_5_3
Packit bf408e
{
Packit bf408e
	static int gdb_frame_offset_warnings = 10;
Packit bf408e
Packit bf408e
	if (gdb_frame_offset_warnings-- > 0)
Packit bf408e
		error(WARNING, 
Packit bf408e
	        "GNU_ALPHA_FRAME_OFFSET functionality not ported to gdb\n");
Packit bf408e
}
Packit bf408e
#endif
Packit bf408e
	req->command = GNU_ALPHA_FRAME_OFFSET;
Packit bf408e
	if (alt_pc) {
Packit bf408e
		ulong pc_save;
Packit bf408e
        	pc_save = req->pc; 
Packit bf408e
        	req->pc = alt_pc;
Packit bf408e
        	gdb_interface(req);
Packit bf408e
        	req->pc = pc_save;
Packit bf408e
	} else
Packit bf408e
        	gdb_interface(req);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Look for key routines that either mean the trace has ended or has
Packit bf408e
 *  bumped into an exception frame.
Packit bf408e
 */
Packit bf408e
int
Packit bf408e
alpha_trace_status(struct gnu_request *req, struct bt_info *bt)
Packit bf408e
{
Packit bf408e
	ulong value;
Packit bf408e
	char *func;
Packit bf408e
	ulong frame;
Packit bf408e
Packit bf408e
	req->addr = 0;
Packit bf408e
	func = req->name;
Packit bf408e
	frame = req->sp;
Packit bf408e
Packit bf408e
	if (STREQ(func, "start_kernel") || 
Packit bf408e
	    STREQ(func, "smp_callin") ||
Packit bf408e
	    STREQ(func, "kernel_thread") ||
Packit bf408e
	    STREQ(func, "__kernel_thread"))
Packit bf408e
		return ALPHA_END_OF_TRACE;
Packit bf408e
Packit bf408e
	if (STREQ(func, "ret_from_smp_fork") ||
Packit bf408e
	    STREQ(func, "ret_from_smpfork"))
Packit bf408e
		return ALPHA_RET_FROM_SMP_FORK;
Packit bf408e
Packit bf408e
	if (STREQ(func, "entSys")) 
Packit bf408e
		return ALPHA_SYSCALL_FRAME;
Packit bf408e
Packit bf408e
	if (STREQ(func, "entMM")) {
Packit bf408e
		req->sp += 56;       /* see entMM in entry.S */
Packit bf408e
		return ALPHA_MM_FAULT;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (STREQ(func, "do_entInt")) 
Packit bf408e
		return ALPHA_EXCEPTION_FRAME;
Packit bf408e
Packit bf408e
	if (STREQ(func, "do_entArith")) 
Packit bf408e
                return ALPHA_EXCEPTION_FRAME;
Packit bf408e
Packit bf408e
        if (STREQ(func, "do_entIF")) 
Packit bf408e
                return ALPHA_EXCEPTION_FRAME;
Packit bf408e
Packit bf408e
        if (STREQ(func, "do_entDbg")) 
Packit bf408e
                return ALPHA_EXCEPTION_FRAME;
Packit bf408e
Packit bf408e
	if (STREQ(func, "handle_bottom_half"))
Packit bf408e
                return ALPHA_EXCEPTION_FRAME;
Packit bf408e
Packit bf408e
	if (STREQ(func, "handle_softirq"))
Packit bf408e
                return ALPHA_EXCEPTION_FRAME;
Packit bf408e
Packit bf408e
	if (STREQ(func, "reschedule"))
Packit bf408e
		return ALPHA_RESCHEDULE;
Packit bf408e
Packit bf408e
	if (STREQ(func, "ret_from_reschedule")) 
Packit bf408e
		return ALPHA_RESCHEDULE;
Packit bf408e
Packit bf408e
	if (STREQ(func, "signal_return"))
Packit bf408e
		return ALPHA_SIGNAL_RETURN;
Packit bf408e
Packit bf408e
	if (STREQ(func, "strace"))
Packit bf408e
		return ALPHA_STRACE;
Packit bf408e
Packit bf408e
        if (STREQ(func, "__down_failed") ||
Packit bf408e
            STREQ(func, "__down_failed_interruptible")) {
Packit bf408e
		readmem(req->sp + 144, KVADDR, &req->pc, sizeof(ulong),
Packit bf408e
			"__down_failed r26", FAULT_ON_ERROR);
Packit bf408e
		req->sp += 160;
Packit bf408e
                return ALPHA_DOWN_FAILED;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	value = GET_STACK_ULONG(frame);
Packit bf408e
Packit bf408e
	if (STREQ(closest_symbol(value), "do_entInt") ||
Packit bf408e
	    STREQ(closest_symbol(value), "do_entArith") ||
Packit bf408e
	    STREQ(closest_symbol(value), "do_entIF") ||
Packit bf408e
	    STREQ(closest_symbol(value), "do_entDbg")) {
Packit bf408e
		req->addr = value;
Packit bf408e
		req->frame = 0;
Packit bf408e
Packit bf408e
		while (INSTACK(frame, bt)) {
Packit bf408e
			frame += sizeof(ulong);
Packit bf408e
			value = GET_STACK_ULONG(frame);
Packit bf408e
			if (STREQ(closest_symbol(value), "ret_from_sys_call")) {
Packit bf408e
				alpha_frame_offset(req, req->addr);
Packit bf408e
				/* req->frame = frame + req->value; XXX */
Packit bf408e
				break;
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
		return ALPHA_INTERRUPT_PENDING;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	return ALPHA_CONTINUE_TRACE;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Redo the gdb pt_regs structure output.
Packit bf408e
 */
Packit bf408e
enum regnames { _r0_, _r1_, _r2_, _r3_, _r4_, _r5_, _r6_, _r7_, _r8_, 
Packit bf408e
		_r19_, _r20_, _r21_, _r22_, _r23_, _r24_, _r25_, _r26_, 
Packit bf408e
		_r27_, _r28_, _hae_, _trap_a0_, _trap_a1_, _trap_a2_, 
Packit bf408e
        	_ps_, _pc_, _gp_, _r16_, _r17_, _r18_, NUMREGS};
Packit bf408e
Packit bf408e
struct alpha_eframe {
Packit bf408e
	char regs[30][30];
Packit bf408e
	ulong value[29];
Packit bf408e
};
Packit bf408e
Packit bf408e
static void
Packit bf408e
alpha_exception_frame(ulong addr, 
Packit bf408e
	              ulong flags, 
Packit bf408e
		      struct gnu_request *req,
Packit bf408e
		      struct bt_info *bt)
Packit bf408e
{
Packit bf408e
	int i, j;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	ulong value; 
Packit bf408e
	physaddr_t paddr;
Packit bf408e
	struct alpha_eframe eframe;
Packit bf408e
Packit bf408e
	if (CRASHDEBUG(4))
Packit bf408e
		fprintf(fp, "alpha_exception_frame: %lx\n", addr);
Packit bf408e
Packit bf408e
	if (flags & BT_SPECULATE) {
Packit bf408e
		req->pc = 0;
Packit bf408e
		fprintf(fp, "ALPHA EXCEPTION FRAME\n");
Packit bf408e
		return;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	BZERO(&eframe, sizeof(struct alpha_eframe));
Packit bf408e
Packit bf408e
        open_tmpfile();
Packit bf408e
	dump_struct("pt_regs", addr, RADIX(16));
Packit bf408e
        rewind(pc->tmpfile);
Packit bf408e
        while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit bf408e
		strip_comma(clean_line(buf));
Packit bf408e
		if (!strstr(buf, "0x"))
Packit bf408e
			continue;
Packit bf408e
Packit bf408e
		extract_hex(buf, &value, NULLCHAR, TRUE);
Packit bf408e
		if (CRASHDEBUG(4))
Packit bf408e
			fprintf(pc->saved_fp, "<%s> %lx\n", buf, value);
Packit bf408e
Packit bf408e
		if (STRNEQ(buf, "r0 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r0_], "  V0/R0: %016lx", value);
Packit bf408e
			eframe.value[_r0_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r1 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r1_], "  T0/R1: %016lx", value);
Packit bf408e
			eframe.value[_r1_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r2 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r2_], "  T1/R2: %016lx", value);
Packit bf408e
			eframe.value[_r2_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r3 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r3_], "  T2/R3: %016lx", value);
Packit bf408e
			eframe.value[_r3_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r4 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r4_], "  T3/R4: %016lx", value);
Packit bf408e
			eframe.value[_r4_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r5 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r5_], "  T4/R5: %016lx", value);
Packit bf408e
			eframe.value[_r5_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r6 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r6_], "  T5/R6: %016lx", value);
Packit bf408e
			eframe.value[_r6_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r7 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r7_], "  T6/R7: %016lx", value);
Packit bf408e
			eframe.value[_r7_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r8 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r8_], "  T7/R8: %016lx", value);
Packit bf408e
			eframe.value[_r8_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r19 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r19_], " A3/R19: %016lx", value);
Packit bf408e
			eframe.value[_r19_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r20 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r20_], " A4/R20: %016lx", value);
Packit bf408e
			eframe.value[_r20_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r21 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r21_], " A5/R21: %016lx", value);
Packit bf408e
			eframe.value[_r21_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r22 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r22_], " T8/R22: %016lx", value);
Packit bf408e
			eframe.value[_r22_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r23 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r23_], " T9/R23: %016lx", value);
Packit bf408e
			eframe.value[_r23_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r24 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r24_], "T10/R24: %016lx", value);
Packit bf408e
			eframe.value[_r24_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r25 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r25_], "T11/R25: %016lx", value);
Packit bf408e
			eframe.value[_r25_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r26 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r26_], " RA/R26: %016lx", value);
Packit bf408e
			eframe.value[_r26_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r27 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r27_], "T12/R27: %016lx", value);
Packit bf408e
			eframe.value[_r27_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r28 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r28_], " AT/R28: %016lx", value);
Packit bf408e
			eframe.value[_r28_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "hae = ")) {
Packit bf408e
			sprintf(eframe.regs[_hae_], "    HAE: %016lx", value);
Packit bf408e
			eframe.value[_hae_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "trap_a0 = ")) {
Packit bf408e
			sprintf(eframe.regs[_trap_a0_], "TRAP_A0: %016lx", 
Packit bf408e
				value);
Packit bf408e
			eframe.value[_trap_a0_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "trap_a1 = ")) {
Packit bf408e
			sprintf(eframe.regs[_trap_a1_], "TRAP_A1: %016lx", 
Packit bf408e
				value);
Packit bf408e
			eframe.value[_trap_a1_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "trap_a2 = ")) {
Packit bf408e
			sprintf(eframe.regs[_trap_a2_], "TRAP_A2: %016lx", 
Packit bf408e
				value);
Packit bf408e
			eframe.value[_trap_a2_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "ps = ")) {
Packit bf408e
			sprintf(eframe.regs[_ps_], "     PS: %016lx", value);
Packit bf408e
			eframe.value[_ps_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "pc = ")) {
Packit bf408e
			sprintf(eframe.regs[_pc_], "     PC: %016lx", value);
Packit bf408e
			eframe.value[_pc_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "gp = ")) {
Packit bf408e
			sprintf(eframe.regs[_gp_], " GP/R29: %016lx", value);
Packit bf408e
			eframe.value[_gp_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r16 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r16_], " A0/R16: %016lx", value);
Packit bf408e
			eframe.value[_r16_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r17 = ")) {
Packit bf408e
			sprintf(eframe.regs[_r17_], " A1/R17: %016lx", value);
Packit bf408e
			eframe.value[_r17_] = value;
Packit bf408e
		}
Packit bf408e
		if (STRNEQ(buf, "r18 =")) {
Packit bf408e
			sprintf(eframe.regs[_r18_], " A2/R18: %016lx", value);
Packit bf408e
			eframe.value[_r18_] = value;
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
        close_tmpfile();
Packit bf408e
Packit bf408e
	if ((flags & BT_EXCEPTION_FRAME) && !BT_REFERENCE_CHECK(bt)) {
Packit bf408e
dump_eframe:
Packit bf408e
		fprintf(fp, " EFRAME: %lx  ", addr);
Packit bf408e
		fprintf(fp, "%s\n", eframe.regs[_r24_]);
Packit bf408e
Packit bf408e
		for (i = 0; i < (((NUMREGS+1)/2)-1); i++) {
Packit bf408e
			fprintf(fp, "%s  ", eframe.regs[i]);
Packit bf408e
			pad_line(fp, 21 - strlen(eframe.regs[i]), ' ');
Packit bf408e
			j = i+((NUMREGS+1)/2);
Packit bf408e
			fprintf(fp, "%s", eframe.regs[j]);
Packit bf408e
			if (((j == _pc_) || (j == _r26_)) && 
Packit bf408e
			    is_kernel_text(eframe.value[j]))
Packit bf408e
				fprintf(fp, "  <%s>", 
Packit bf408e
				    value_to_symstr(eframe.value[j], buf, 0));
Packit bf408e
			fprintf(fp, "\n");
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	req->ra = eframe.value[_r26_];
Packit bf408e
	req->pc = eframe.value[_pc_];
Packit bf408e
	req->sp = addr + (29 * sizeof(ulong));
Packit bf408e
Packit bf408e
	if (flags & BT_USER_EFRAME) {
Packit bf408e
		flags &= ~BT_USER_EFRAME;
Packit bf408e
		if (!BT_REFERENCE_CHECK(bt) && (eframe.value[_ps_] == 8) &&
Packit bf408e
		    (((uvtop(task_to_context(req->task), req->pc, &paddr, 0) || 
Packit bf408e
	             (volatile ulong)paddr) &&
Packit bf408e
		    (uvtop(task_to_context(req->task), req->ra, &paddr, 0) ||
Packit bf408e
		     (volatile ulong)paddr)) ||
Packit bf408e
		     (IS_ZOMBIE(req->task) || IS_EXITING(req->task)))) {
Packit bf408e
			if (!(flags & 
Packit bf408e
			     (BT_RESCHEDULE|BT_RET_FROM_SMP_FORK|BT_STRACE)))
Packit bf408e
				fprintf(fp, 
Packit bf408e
				    "NOTE: kernel-entry exception frame:\n");
Packit bf408e
			goto dump_eframe;
Packit bf408e
		} 
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *   Look for likely exception frames in a stack.
Packit bf408e
 */
Packit bf408e
struct alpha_pt_regs {
Packit bf408e
	ulong reg_value[NUMREGS];
Packit bf408e
};
Packit bf408e
Packit bf408e
static int
Packit bf408e
alpha_eframe_search(struct bt_info *bt)
Packit bf408e
{
Packit bf408e
        ulong *first, *last;
Packit bf408e
	ulong eframe;
Packit bf408e
	struct alpha_pt_regs *pt;
Packit bf408e
	struct gnu_request *req;   /* needed for alpha_exception_frame */
Packit bf408e
	ulong *stack;
Packit bf408e
	int cnt;
Packit bf408e
Packit bf408e
	stack = (ulong *)bt->stackbuf;
Packit bf408e
        req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
Packit bf408e
        req->task = bt->task;
Packit bf408e
Packit bf408e
        first = stack +
Packit bf408e
           (roundup(SIZE(task_struct), sizeof(ulong)) / sizeof(ulong));
Packit bf408e
        last = stack +
Packit bf408e
           (((bt->stacktop - bt->stackbase) - SIZE(pt_regs)) / sizeof(ulong));
Packit bf408e
Packit bf408e
        for (cnt = 0; first <= last; first++) {
Packit bf408e
		pt = (struct alpha_pt_regs *)first;
Packit bf408e
Packit bf408e
		/* check for kernel exception frame */
Packit bf408e
Packit bf408e
		if (!(pt->reg_value[_ps_] & 0xfffffffffffffff8) &&
Packit bf408e
		    (is_kernel_text(pt->reg_value[_pc_]) ||
Packit bf408e
		     IS_MODULE_VADDR(pt->reg_value[_pc_])) &&
Packit bf408e
		    (is_kernel_text(pt->reg_value[_r26_]) ||
Packit bf408e
		     IS_MODULE_VADDR(pt->reg_value[_r26_])) &&
Packit bf408e
                    IS_KVADDR(pt->reg_value[_gp_])) {
Packit bf408e
			cnt++;
Packit bf408e
			if (bt->flags & BT_EFRAME_COUNT) 
Packit bf408e
				continue;
Packit bf408e
			fprintf(fp, "\nKERNEL-MODE EXCEPTION FRAME:\n");
Packit bf408e
			eframe = bt->task + ((ulong)first - (ulong)stack);
Packit bf408e
			alpha_exception_frame(eframe, BT_EXCEPTION_FRAME, 
Packit bf408e
				req, bt);
Packit bf408e
			continue;
Packit bf408e
		}
Packit bf408e
Packit bf408e
		/* check for user exception frame */
Packit bf408e
Packit bf408e
                if ((pt->reg_value[_ps_] == 0x8) &&
Packit bf408e
		    ((IN_TASK_VMA(bt->task, pt->reg_value[_pc_]) &&
Packit bf408e
                    IN_TASK_VMA(bt->task, pt->reg_value[_r26_]) &&
Packit bf408e
                    IS_UVADDR(pt->reg_value[_gp_], bt->tc)) ||
Packit bf408e
		    ((first == last) && 
Packit bf408e
			(IS_ZOMBIE(bt->task) || IS_EXITING(bt->task))))) {
Packit bf408e
			cnt++;
Packit bf408e
			if (bt->flags & BT_EFRAME_COUNT) 
Packit bf408e
				continue;
Packit bf408e
			fprintf(fp, "\nUSER-MODE EXCEPTION FRAME:\n");
Packit bf408e
			eframe = bt->task + ((ulong)first - (ulong)stack);
Packit bf408e
			alpha_exception_frame(eframe, BT_EXCEPTION_FRAME, 
Packit bf408e
				req, bt);
Packit bf408e
		}
Packit bf408e
        }
Packit bf408e
Packit bf408e
	FREEBUF(req);
Packit bf408e
Packit bf408e
	return cnt;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Before dumping a nonsensical exception frame, give it a quick test.
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
verify_user_eframe(struct bt_info *bt, ulong task, ulong sp)
Packit bf408e
{
Packit bf408e
	struct alpha_pt_regs ptbuf, *pt;
Packit bf408e
Packit bf408e
	readmem(sp, KVADDR, &ptbuf, sizeof(struct alpha_pt_regs),
Packit bf408e
		"pt_regs", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	pt = &ptbuf;
Packit bf408e
Packit bf408e
        if ((pt->reg_value[_ps_] == 0x8) &&
Packit bf408e
            ((IN_TASK_VMA(task, pt->reg_value[_pc_]) &&
Packit bf408e
            IN_TASK_VMA(task, pt->reg_value[_r26_]) &&
Packit bf408e
            IS_UVADDR(pt->reg_value[_gp_], bt->tc)) ||
Packit bf408e
            ((pt == (struct alpha_pt_regs *)USER_EFRAME_ADDR(task)) && 
Packit bf408e
	    (IS_ZOMBIE(task) || IS_EXITING(task))))) {
Packit bf408e
		return TRUE;
Packit bf408e
        }
Packit bf408e
Packit bf408e
	return FALSE;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Try to resync the stack location when there is no valid stack frame,
Packit bf408e
 *  typically just above an exception frame.  Use the req->ra value from the 
Packit bf408e
 *  exception frame as the new starting req->pc.  Then walk up the stack until 
Packit bf408e
 *  a text routine that calls the newly-assigned pc is found -- that stack 
Packit bf408e
 *  location then becomes the new req->sp.  
Packit bf408e
 *
Packit bf408e
 *  If we're not coming from an exception frame, req-ra and req->pc will be 
Packit bf408e
 *  purposely zeroed out.  In that case, use the prevsp value to find the 
Packit bf408e
 *  first pc that called the last frame's pc.
Packit bf408e
 *
Packit bf408e
 *  Add any other repeatable "special-case" frames to the beginning of this 
Packit bf408e
 *  routine (ex. debug_spin_lock).  Last ditch -- at the end of this routine, 
Packit bf408e
 *  speculate what might have happened (possibly in the background) -- and 
Packit bf408e
 *  if it looks good, run with it.
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
alpha_backtrace_resync(struct gnu_request *req, ulong flags, struct bt_info *bt)
Packit bf408e
{
Packit bf408e
	char addr[BUFSIZE];
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	char lookfor1[BUFSIZE];
Packit bf408e
	char lookfor2[BUFSIZE];
Packit bf408e
	ulong newpc;
Packit bf408e
	ulong *stkp; 
Packit bf408e
	ulong *stkp_newpc, *stkp_next;
Packit bf408e
	ulong value;
Packit bf408e
	int found;
Packit bf408e
	char *name;
Packit bf408e
	int exception;
Packit bf408e
Packit bf408e
	if (CRASHDEBUG(1))
Packit bf408e
		fprintf(fp, 
Packit bf408e
		    "RESYNC1: [%lx-%d] ra: %lx pc: %lx sp: %lx\n",
Packit bf408e
                        flags, req->curframe, req->ra, req->pc, req->sp);
Packit bf408e
Packit bf408e
	if (!req->ra && !req->pc) {
Packit bf408e
		req->ra = req->prevpc;
Packit bf408e
		exception = FALSE;
Packit bf408e
	} else
Packit bf408e
		exception = TRUE;
Packit bf408e
Packit bf408e
	if (!IS_KVADDR(req->ra)) 
Packit bf408e
		return FALSE;
Packit bf408e
Packit bf408e
	name = closest_symbol(req->ra);
Packit bf408e
	sprintf(lookfor1, "<%s>", name);
Packit bf408e
	sprintf(lookfor2, "<%s+", name);
Packit bf408e
Packit bf408e
        if (CRASHDEBUG(1))
Packit bf408e
                fprintf(fp, "RESYNC2: exception: %s lookfor: %s or %s\n",
Packit bf408e
                        exception ? "TRUE" : "FALSE",
Packit bf408e
			lookfor1, lookfor2);
Packit bf408e
Packit bf408e
	/*
Packit bf408e
	 *  This is common when a non-panicking active CPU is spinning
Packit bf408e
         *  in debug_spin_lock().  The next pc is offset by 0x30 from
Packit bf408e
         *  the top of the exception frame, and the next sp is equal
Packit bf408e
	 *  to the frame offset of debug_spin_lock().  I can't explain it...
Packit bf408e
	 */ 
Packit bf408e
	if ((flags & BT_FROM_EXCEPTION) && STREQ(name, "debug_spin_lock")) {
Packit bf408e
		alpha_print_stack_entry(req, req->ra, 
Packit bf408e
			closest_symbol(req->ra), flags, bt);
Packit bf408e
Packit bf408e
		if (BT_REFERENCE_FOUND(bt)) 
Packit bf408e
			return FALSE;
Packit bf408e
		
Packit bf408e
		alpha_frame_offset(req, req->ra);
Packit bf408e
		stkp = (ulong *)(req->sp + 0x30);
Packit bf408e
		value = GET_STACK_ULONG(stkp);
Packit bf408e
		if (!is_kernel_text(value)) {
Packit bf408e
			req->sp = req->prevsp;
Packit bf408e
			return FALSE;
Packit bf408e
		}
Packit bf408e
		req->pc = value;
Packit bf408e
		req->sp += req->value;
Packit bf408e
		return TRUE;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	/*
Packit bf408e
	 *  If the ra is a system call, then all we should have to do is
Packit bf408e
	 *  find the next reference to entSys on the stack, and set the
Packit bf408e
	 *  sp to that value.
Packit bf408e
	 */
Packit bf408e
        if (is_system_call(name, 0)) {
Packit bf408e
		/* stkp = (ulong *)req->sp; */
Packit bf408e
		stkp = (ulong *)req->prevsp;
Packit bf408e
Packit bf408e
        	for (stkp++; INSTACK(stkp, bt); stkp++) {
Packit bf408e
			value = GET_STACK_ULONG(stkp);
Packit bf408e
Packit bf408e
			if (IS_KVADDR(value) && is_kernel_text(value)) {
Packit bf408e
				if (STREQ(closest_symbol(value), "entSys")) {
Packit bf408e
					req->pc = value;
Packit bf408e
					req->sp = USER_EFRAME_ADDR(req->task);
Packit bf408e
					return TRUE;
Packit bf408e
				}
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	/*
Packit bf408e
	 *  Just find the next location containing text. (?)
Packit bf408e
	 */
Packit bf408e
        if (STREQ(name, "do_coredump")) {
Packit bf408e
                stkp = (ulong *)(req->sp + sizeof(long));
Packit bf408e
                for (stkp++; INSTACK(stkp, bt); stkp++) {
Packit bf408e
			value = GET_STACK_ULONG(stkp);
Packit bf408e
Packit bf408e
                        if (IS_KVADDR(value) && is_kernel_text(value)) {
Packit bf408e
                                req->pc = req->ra;
Packit bf408e
                                req->sp = (ulong)stkp;
Packit bf408e
                                return TRUE;
Packit bf408e
                        }
Packit bf408e
                }
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (flags & BT_SPECULATE)
Packit bf408e
		return FALSE;
Packit bf408e
Packit bf408e
	if (CRASHDEBUG(1)) {
Packit bf408e
		fprintf(fp, "RESYNC3: prevsp: %lx  ra: %lx name: %s\n", 
Packit bf408e
			req->prevsp, req->ra, name);
Packit bf408e
		fprintf(fp, "RESYNC3: prevpc: %lx\n", req->prevpc); 
Packit bf408e
	}
Packit bf408e
Packit bf408e
	stkp_newpc = stkp_next = 0;
Packit bf408e
	newpc = 0;
Packit bf408e
	found = FALSE;
Packit bf408e
	if (exception) {
Packit bf408e
		newpc = req->ra;
Packit bf408e
		stkp = (ulong *)req->sp;
Packit bf408e
	} else 
Packit bf408e
		stkp = (ulong *)req->prevsp;
Packit bf408e
Packit bf408e
	if (CRASHDEBUG(1))
Packit bf408e
		fprintf(fp, "RESYNC4: stkp: %lx  newpc: %lx\n",
Packit bf408e
			(ulong)stkp, newpc);
Packit bf408e
Packit bf408e
	for (stkp++; INSTACK(stkp, bt); stkp++) {
Packit bf408e
		value = GET_STACK_ULONG(stkp);
Packit bf408e
		/*
Packit bf408e
		 *  First find the new pc on the stack.
Packit bf408e
		 */
Packit bf408e
		if (!found) {
Packit bf408e
			if (!exception && is_kernel_text(value)) {
Packit bf408e
				found = TRUE;
Packit bf408e
			} else if (value == newpc) {
Packit bf408e
				found = TRUE;
Packit bf408e
				stkp_newpc = stkp;
Packit bf408e
				continue;
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
Packit bf408e
		if (!IS_KVADDR(value))
Packit bf408e
			continue;
Packit bf408e
Packit bf408e
		if (is_kernel_text(value)) {
Packit bf408e
			if (!stkp_next)
Packit bf408e
				stkp_next = stkp;
Packit bf408e
			if (CRASHDEBUG(2)) {
Packit bf408e
				fprintf(fp, 
Packit bf408e
				    "RESYNC6: disassemble %lx (%s)\n",
Packit bf408e
					value - sizeof(uint),
Packit bf408e
					value_to_symstr(value - sizeof(uint),
Packit bf408e
					buf, 0));
Packit bf408e
			}
Packit bf408e
			req->command = GNU_DISASSEMBLE;
Packit bf408e
			req->addr = value - sizeof(uint);
Packit bf408e
			sprintf(addr, "0x%lx", req->addr);
Packit bf408e
			open_tmpfile();
Packit bf408e
			req->fp = pc->tmpfile;
Packit bf408e
			gdb_interface(req);
Packit bf408e
			rewind(pc->tmpfile);
Packit bf408e
			while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit bf408e
				clean_line(buf);
Packit bf408e
                                if (STRNEQ(buf, "Dump of") ||
Packit bf408e
                                    STRNEQ(buf, "End of"))
Packit bf408e
                                        continue;
Packit bf408e
Packit bf408e
                                if (STRNEQ(buf, addr)) {
Packit bf408e
					if (LASTCHAR(buf) == ':') {
Packit bf408e
						fgets(buf, BUFSIZE, 
Packit bf408e
							pc->tmpfile);
Packit bf408e
						clean_line(buf);
Packit bf408e
					}
Packit bf408e
					if (CRASHDEBUG(2) && 
Packit bf408e
					    (strstr(buf, "jsr") 
Packit bf408e
					    || strstr(buf, "bsr"))) 
Packit bf408e
						fprintf(pc->saved_fp, "%s\n",
Packit bf408e
							buf);
Packit bf408e
					if ((strstr(buf, "jsr") ||
Packit bf408e
					     strstr(buf, "bsr")) &&
Packit bf408e
					    (strstr(buf, lookfor1) ||
Packit bf408e
					     strstr(buf, lookfor2))) {
Packit bf408e
						if (exception) {
Packit bf408e
							req->pc = newpc;
Packit bf408e
							req->sp = (ulong)stkp;
Packit bf408e
						} else 
Packit bf408e
							req->pc = req->addr;
Packit bf408e
						close_tmpfile();
Packit bf408e
						return TRUE;
Packit bf408e
					}
Packit bf408e
				}
Packit bf408e
			}
Packit bf408e
			close_tmpfile();
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (CRASHDEBUG(1)) {
Packit bf408e
		fprintf(fp, "RESYNC9: [%d] name: %s pc: %lx ra: %lx\n",
Packit bf408e
			req->curframe, name, req->pc, req->ra);
Packit bf408e
		fprintf(fp, "RESYNC9: sp: %lx lastsp: %lx\n",
Packit bf408e
			req->sp, req->lastsp);
Packit bf408e
		fprintf(fp, "RESYNC9: prevpc: %lx prevsp: %lx\n",
Packit bf408e
			req->prevpc, req->prevsp);
Packit bf408e
	}
Packit bf408e
Packit bf408e
	/*
Packit bf408e
	 *  At this point, all we can do is speculate based upon 
Packit bf408e
	 *  past experiences...
Packit bf408e
	 */
Packit bf408e
	return (alpha_resync_speculate(req, flags, bt));
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Try one level of speculation.  If it works, fine -- if not, give up.
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
alpha_resync_speculate(struct gnu_request *req, ulong flags, struct bt_info *bt)
Packit bf408e
{
Packit bf408e
	ulong *stkp;
Packit bf408e
	ulong value;
Packit bf408e
	ulong found_sp, found_ra;
Packit bf408e
        struct stack_hook hook;
Packit bf408e
	struct bt_info bt_info, *btloc;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	int kernel_thread;
Packit bf408e
	int looks_good;
Packit bf408e
Packit bf408e
	if (flags & BT_SPECULATE)   /* already been here on this trace... */
Packit bf408e
		return FALSE;
Packit bf408e
Packit bf408e
	if (pc->tmpfile)
Packit bf408e
		return FALSE;
Packit bf408e
Packit bf408e
        found_ra = found_sp = 0;
Packit bf408e
	kernel_thread = is_kernel_thread(req->task);
Packit bf408e
Packit bf408e
	/*
Packit bf408e
	 *  Add "known" possibilities here.
Packit bf408e
	 */
Packit bf408e
	switch (flags & (BT_FROM_EXCEPTION|BT_FROM_CALLFRAME))
Packit bf408e
	{
Packit bf408e
	case BT_FROM_EXCEPTION:
Packit bf408e
        	if (STREQ(closest_symbol(req->prevpc), "read_lock") ||
Packit bf408e
                    STREQ(closest_symbol(req->ra), "do_select") ||
Packit bf408e
                    STREQ(closest_symbol(req->ra), "schedule")) {
Packit bf408e
			stkp = (ulong *)req->sp;
Packit bf408e
			for (stkp++; INSTACK(stkp, bt); stkp++) {
Packit bf408e
				value = GET_STACK_ULONG(stkp);
Packit bf408e
	
Packit bf408e
				if (found_ra) {
Packit bf408e
					if (is_kernel_text_offset(value)) {
Packit bf408e
						found_sp = (ulong)stkp;
Packit bf408e
						break;
Packit bf408e
					}
Packit bf408e
					continue;
Packit bf408e
				}
Packit bf408e
	
Packit bf408e
				if (value == req->ra) 
Packit bf408e
					found_ra = value; 
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	case BT_FROM_CALLFRAME:
Packit bf408e
                if (STREQ(closest_symbol(req->ra), "sys_read")) {
Packit bf408e
			value = GET_STACK_ULONG(req->prevsp - 32);
Packit bf408e
                        if (STREQ(closest_symbol(value), "entSys")) {
Packit bf408e
                                found_ra = value;
Packit bf408e
                                found_sp = req->prevsp - 32;
Packit bf408e
                        }
Packit bf408e
                } else if (STREQ(closest_symbol(req->ra), "exit_autofs4_fs")) {
Packit bf408e
                        stkp = (ulong *)req->sp;
Packit bf408e
                        for (stkp++; INSTACK(stkp, bt); stkp++) {
Packit bf408e
				value = GET_STACK_ULONG(stkp);
Packit bf408e
Packit bf408e
                                if (found_ra && (value != found_ra)) {
Packit bf408e
                                        if (is_kernel_text_offset(value)) {
Packit bf408e
                                                found_sp = (ulong)stkp;
Packit bf408e
                                                break;
Packit bf408e
                                        }
Packit bf408e
                                        continue;
Packit bf408e
                                }
Packit bf408e
Packit bf408e
				if (is_kernel_text_offset(value)) 
Packit bf408e
					found_ra = value;
Packit bf408e
                        }
Packit bf408e
		}
Packit bf408e
Packit bf408e
		break;
Packit bf408e
Packit bf408e
	default:
Packit bf408e
		if (req->hookp &&
Packit bf408e
		    STREQ(closest_symbol(req->prevpc), "filemap_nopage") &&
Packit bf408e
	            !STREQ(closest_symbol(req->hookp->eip), "do_no_page")) {
Packit bf408e
			found_ra = found_sp = 0;
Packit bf408e
			stkp = (ulong *)req->prevsp;
Packit bf408e
                        for (stkp++; INSTACK(stkp, bt); stkp++) {
Packit bf408e
				value = GET_STACK_ULONG(stkp);
Packit bf408e
Packit bf408e
                                if (found_ra && (value != found_ra)) {
Packit bf408e
                                        if (is_kernel_text_offset(value)) {
Packit bf408e
                                                found_sp = (ulong)stkp;
Packit bf408e
                                                break;
Packit bf408e
                                        }
Packit bf408e
                                        continue;
Packit bf408e
                                }
Packit bf408e
Packit bf408e
                                if (is_kernel_text_offset(value) &&
Packit bf408e
				    STREQ(closest_symbol(value), "do_no_page")) 
Packit bf408e
                                        found_ra = value;
Packit bf408e
                        }
Packit bf408e
			if (found_ra && found_sp) {
Packit bf408e
                        	req->hookp->eip = found_ra;
Packit bf408e
                        	req->hookp->esp = found_sp;
Packit bf408e
				return TRUE;
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
		
Packit bf408e
                if (req->hookp) {
Packit bf408e
                        found_ra = req->hookp->eip;
Packit bf408e
                        found_sp = req->hookp->esp;
Packit bf408e
                }
Packit bf408e
Packit bf408e
		break;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (found_ra && found_sp) {
Packit bf408e
		looks_good = FALSE;
Packit bf408e
		hook.esp = found_sp;
Packit bf408e
		hook.eip = found_ra;
Packit bf408e
Packit bf408e
		if (CRASHDEBUG(1))
Packit bf408e
			fprintf(pc->saved_fp, 
Packit bf408e
			    "----- RESYNC SPECULATE START -----\n");
Packit bf408e
Packit bf408e
		open_tmpfile();
Packit bf408e
		btloc = &bt_info;
Packit bf408e
		BZERO(btloc, sizeof(struct bt_info));
Packit bf408e
		btloc->task = req->task;
Packit bf408e
		btloc->tc = bt->tc;
Packit bf408e
		btloc->stackbase = bt->stackbase;
Packit bf408e
		btloc->stacktop = bt->stacktop;
Packit bf408e
		btloc->flags = BT_SPECULATE;
Packit bf408e
		btloc->hp = &hook;
Packit bf408e
        	back_trace(btloc);
Packit bf408e
        	rewind(pc->tmpfile);
Packit bf408e
        	while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit bf408e
			if (CRASHDEBUG(1))
Packit bf408e
				fprintf(pc->saved_fp, "%s", buf);
Packit bf408e
Packit bf408e
                        if (strstr(buf, "NOTE: cannot resolve")) {
Packit bf408e
                                looks_good = FALSE;
Packit bf408e
                                break;
Packit bf408e
                        }
Packit bf408e
Packit bf408e
			if (strstr(buf, "ALPHA EXCEPTION FRAME")) {
Packit bf408e
				looks_good = TRUE;
Packit bf408e
				break;
Packit bf408e
			}
Packit bf408e
Packit bf408e
			if (kernel_thread) {
Packit bf408e
				if (strstr(buf, " kernel_thread ") ||
Packit bf408e
				    strstr(buf, " __kernel_thread ") ||
Packit bf408e
				    strstr(buf, " start_kernel ") ||
Packit bf408e
				    strstr(buf, " smp_callin ")) {
Packit bf408e
					looks_good = TRUE;
Packit bf408e
					break;
Packit bf408e
				}
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
		close_tmpfile();
Packit bf408e
Packit bf408e
		if (CRASHDEBUG(1))
Packit bf408e
			fprintf(pc->saved_fp, 
Packit bf408e
			    "----- RESYNC SPECULATE DONE ------\n");
Packit bf408e
Packit bf408e
		if (looks_good) {
Packit bf408e
                	req->pc = found_ra;
Packit bf408e
                	req->sp = found_sp;
Packit bf408e
			return TRUE;
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	return FALSE;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Translates a user virtual address to its physical address.  cmd_vtop()
Packit bf408e
 *  sets the verbose flag so that the pte translation gets displayed; all
Packit bf408e
 *  other callers quietly accept the translation.
Packit bf408e
 *
Packit bf408e
 *  This routine can also take mapped kernel virtual addresses if the -u flag
Packit bf408e
 *  was passed to cmd_vtop().  If so, it makes the translation using the
Packit bf408e
 *  kernel-memory PGD entry instead of swapper_pg_dir.
Packit bf408e
 */
Packit bf408e
Packit bf408e
static int
Packit bf408e
alpha_uvtop(struct task_context *tc, ulong vaddr, physaddr_t *paddr, int verbose)
Packit bf408e
{
Packit bf408e
	ulong mm;
Packit bf408e
	ulong *pgd;
Packit bf408e
	ulong *page_dir;
Packit bf408e
	ulong *page_middle;
Packit bf408e
	ulong *page_table;
Packit bf408e
	ulong pgd_pte;
Packit bf408e
	ulong pmd_pte;
Packit bf408e
	ulong pte;
Packit bf408e
Packit bf408e
        if (!tc)
Packit bf408e
                error(FATAL, "current context invalid\n");
Packit bf408e
Packit bf408e
	*paddr = 0;
Packit bf408e
Packit bf408e
        if (is_kernel_thread(tc->task) && IS_KVADDR(vaddr)) {
Packit bf408e
		pgd = (ulong *)machdep->get_task_pgd(tc->task);
Packit bf408e
	} else {
Packit bf408e
		if (!tc->mm_struct)
Packit bf408e
			pgd = (ulong *)machdep->get_task_pgd(tc->task);
Packit bf408e
		else {
Packit bf408e
                	if ((mm = task_mm(tc->task, TRUE)))
Packit bf408e
                        	pgd = ULONG_PTR(tt->mm_struct +
Packit bf408e
                                	OFFSET(mm_struct_pgd));
Packit bf408e
			else
Packit bf408e
				readmem(tc->mm_struct + OFFSET(mm_struct_pgd), 
Packit bf408e
					KVADDR, &pgd, sizeof(long), 
Packit bf408e
					"mm_struct pgd", FAULT_ON_ERROR);
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (verbose) 
Packit bf408e
		fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
Packit bf408e
Packit bf408e
	page_dir = pgd + ((vaddr >> PGDIR_SHIFT) & (PTRS_PER_PAGE - 1));
Packit bf408e
Packit bf408e
	FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE());
Packit bf408e
	pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));
Packit bf408e
Packit bf408e
	if (verbose)
Packit bf408e
		fprintf(fp, "  PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte);
Packit bf408e
Packit bf408e
	if (!(pgd_pte & _PAGE_VALID))
Packit bf408e
		goto no_upage;
Packit bf408e
Packit bf408e
	page_middle = (ulong *)
Packit bf408e
		(PTOV((pgd_pte & _PFN_MASK) >> (32-PAGESHIFT()))) + 
Packit bf408e
	  	((vaddr >> PMD_SHIFT) & (PTRS_PER_PAGE - 1));
Packit bf408e
Packit bf408e
	FILL_PMD(PAGEBASE(page_middle), KVADDR, PAGESIZE());
Packit bf408e
	pmd_pte = ULONG(machdep->pmd + PAGEOFFSET(page_middle));
Packit bf408e
Packit bf408e
	if (verbose)
Packit bf408e
		fprintf(fp, "  PMD: %lx => %lx\n", (ulong)page_middle, pmd_pte);
Packit bf408e
Packit bf408e
	if (!(pmd_pte & _PAGE_VALID))
Packit bf408e
		goto no_upage;
Packit bf408e
Packit bf408e
	page_table = (ulong *)
Packit bf408e
		(PTOV((pmd_pte & _PFN_MASK) >> (32-PAGESHIFT()))) +
Packit bf408e
     		(BTOP(vaddr) & (PTRS_PER_PAGE - 1));
Packit bf408e
	
Packit bf408e
	FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE());
Packit bf408e
	pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
Packit bf408e
Packit bf408e
        if (verbose) 
Packit bf408e
                fprintf(fp, "  PTE: %lx => %lx\n", (ulong)page_table, pte);
Packit bf408e
Packit bf408e
	if (!(pte & (_PAGE_VALID))) {
Packit bf408e
		*paddr = pte;
Packit bf408e
		if (pte && verbose) {
Packit bf408e
			fprintf(fp, "\n");
Packit bf408e
			alpha_translate_pte(pte, 0, 0);
Packit bf408e
		}
Packit bf408e
		goto no_upage;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	*paddr = ((pte & _PFN_MASK) >> (32-PAGESHIFT())) + PAGEOFFSET(vaddr);
Packit bf408e
Packit bf408e
        if (verbose) {
Packit bf408e
                fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr));
Packit bf408e
		alpha_translate_pte(pte, 0, 0);
Packit bf408e
	}
Packit bf408e
Packit bf408e
	return TRUE;
Packit bf408e
Packit bf408e
no_upage:
Packit bf408e
	return FALSE;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Translates a kernel virtual address to its physical address.  cmd_vtop()
Packit bf408e
 *  sets the verbose flag so that the pte translation gets displayed; all
Packit bf408e
 *  other callers quietly accept the translation.
Packit bf408e
 */
Packit bf408e
Packit bf408e
static int
Packit bf408e
alpha_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose)
Packit bf408e
{
Packit bf408e
	ulong *pgd;
Packit bf408e
	ulong *page_dir;
Packit bf408e
	ulong *page_middle;
Packit bf408e
	ulong *page_table;
Packit bf408e
        ulong pgd_pte;
Packit bf408e
        ulong pmd_pte;
Packit bf408e
        ulong pte;
Packit bf408e
Packit bf408e
	if (!IS_KVADDR(kvaddr))
Packit bf408e
		return FALSE;
Packit bf408e
Packit bf408e
	if (!vt->vmalloc_start) {         /* presume KSEG this early */
Packit bf408e
		*paddr = VTOP(kvaddr);
Packit bf408e
		return TRUE;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (!IS_VMALLOC_ADDR(kvaddr)) { 
Packit bf408e
		*paddr = VTOP(kvaddr);
Packit bf408e
		return TRUE;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	pgd = (ulong *)vt->kernel_pgd[0];
Packit bf408e
Packit bf408e
	if (verbose) 
Packit bf408e
		fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
Packit bf408e
Packit bf408e
	page_dir = pgd + ((kvaddr >> PGDIR_SHIFT) & (PTRS_PER_PAGE - 1));
Packit bf408e
Packit bf408e
        FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE());
Packit bf408e
        pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));
Packit bf408e
Packit bf408e
	if (verbose)
Packit bf408e
		fprintf(fp, "  PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte);
Packit bf408e
Packit bf408e
	if (!(pgd_pte & _PAGE_VALID))
Packit bf408e
		goto no_kpage;
Packit bf408e
Packit bf408e
	page_middle = (ulong *)
Packit bf408e
		(PTOV((pgd_pte & _PFN_MASK) >> (32-PAGESHIFT()))) + 
Packit bf408e
	  	((kvaddr >> PMD_SHIFT) & (PTRS_PER_PAGE - 1));
Packit bf408e
Packit bf408e
        FILL_PMD(PAGEBASE(page_middle), KVADDR, PAGESIZE());
Packit bf408e
        pmd_pte = ULONG(machdep->pmd + PAGEOFFSET(page_middle));
Packit bf408e
Packit bf408e
	if (verbose)
Packit bf408e
		fprintf(fp, "  PMD: %lx => %lx\n", (ulong)page_middle, pmd_pte);
Packit bf408e
Packit bf408e
	if (!(pmd_pte & _PAGE_VALID))
Packit bf408e
		goto no_kpage;
Packit bf408e
Packit bf408e
	page_table = (ulong *)
Packit bf408e
		(PTOV((pmd_pte & _PFN_MASK) >> (32-PAGESHIFT()))) +
Packit bf408e
     		(BTOP(kvaddr) & (PTRS_PER_PAGE - 1));
Packit bf408e
	
Packit bf408e
        FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE());
Packit bf408e
        pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
Packit bf408e
Packit bf408e
        if (verbose) 
Packit bf408e
                fprintf(fp, "  PTE: %lx => %lx\n", (ulong)page_table, pte);
Packit bf408e
Packit bf408e
	if (!(pte & (_PAGE_VALID))) {
Packit bf408e
		if (pte && verbose) {
Packit bf408e
			fprintf(fp, "\n");
Packit bf408e
			alpha_translate_pte(pte, 0, 0);
Packit bf408e
		}
Packit bf408e
		goto no_kpage;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	*paddr = ((pte & _PFN_MASK) >> (32-PAGESHIFT())) + PAGEOFFSET(kvaddr);
Packit bf408e
Packit bf408e
        if (verbose) {
Packit bf408e
                fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr));
Packit bf408e
		alpha_translate_pte(pte, 0, 0);
Packit bf408e
	}
Packit bf408e
Packit bf408e
	return TRUE;
Packit bf408e
Packit bf408e
no_kpage:
Packit bf408e
	return FALSE;
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Get the relevant page directory pointer from a task structure.
Packit bf408e
 */
Packit bf408e
static ulong
Packit bf408e
alpha_get_task_pgd(ulong task)
Packit bf408e
{
Packit bf408e
	long offset;
Packit bf408e
	ulong ptbr;
Packit bf408e
Packit bf408e
	offset = OFFSET_OPTION(task_struct_thread, task_struct_tss);
Packit bf408e
Packit bf408e
	offset += OFFSET(thread_struct_ptbr);
Packit bf408e
Packit bf408e
        readmem(task + offset, KVADDR, &ptbr,
Packit bf408e
                sizeof(ulong), "task thread ptbr", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	return(PTOV(PTOB(ptbr)));
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Calculate and return the speed of the processor.
Packit bf408e
 */
Packit bf408e
static ulong
Packit bf408e
alpha_processor_speed(void)
Packit bf408e
{
Packit bf408e
	ulong hwrpb;
Packit bf408e
	long offset;
Packit bf408e
	long cycle_freq;
Packit bf408e
	ulong mhz;
Packit bf408e
Packit bf408e
	if (machdep->mhz)
Packit bf408e
		return machdep->mhz;
Packit bf408e
Packit bf408e
	mhz = 0;
Packit bf408e
Packit bf408e
	get_symbol_data("hwrpb", sizeof(void *), &hwrpb);
Packit bf408e
	offset = OFFSET(hwrpb_struct_cycle_freq);
Packit bf408e
Packit bf408e
	if (!hwrpb || (offset == -1) || 
Packit bf408e
	    !readmem(hwrpb+offset, KVADDR, &cycle_freq,
Packit bf408e
            sizeof(ulong), "hwrpb cycle_freq", RETURN_ON_ERROR))
Packit bf408e
		return (machdep->mhz = mhz);
Packit bf408e
Packit bf408e
	mhz = cycle_freq/1000000;
Packit bf408e
Packit bf408e
	return (machdep->mhz = mhz);
Packit bf408e
}
Packit bf408e
Packit bf408e
void
Packit bf408e
alpha_dump_machdep_table(ulong arg)
Packit bf408e
{
Packit bf408e
	int others;
Packit bf408e
Packit bf408e
	others = 0;
Packit bf408e
	fprintf(fp, "              flags: %lx (", machdep->flags);
Packit bf408e
        if (machdep->flags & HWRESET)
Packit bf408e
                fprintf(fp, "%sHWRESET", others++ ? "|" : "");
Packit bf408e
        fprintf(fp, ")\n");
Packit bf408e
	fprintf(fp, "             kvbase: %lx\n", machdep->kvbase);
Packit bf408e
	fprintf(fp, "  identity_map_base: %lx\n", machdep->identity_map_base);
Packit bf408e
        fprintf(fp, "           pagesize: %d\n", machdep->pagesize);
Packit bf408e
        fprintf(fp, "          pageshift: %d\n", machdep->pageshift);
Packit bf408e
        fprintf(fp, "           pagemask: %llx\n", machdep->pagemask);
Packit bf408e
        fprintf(fp, "         pageoffset: %lx\n", machdep->pageoffset);
Packit bf408e
	fprintf(fp, "          stacksize: %ld\n", machdep->stacksize);
Packit bf408e
	fprintf(fp, "                 hz: %d\n", machdep->hz);
Packit bf408e
	fprintf(fp, "                mhz: %ld\n", machdep->mhz);
Packit bf408e
        fprintf(fp, "            memsize: %ld (0x%lx)\n", 
Packit bf408e
		machdep->memsize, machdep->memsize);
Packit bf408e
	fprintf(fp, "               bits: %d\n", machdep->bits);
Packit bf408e
	fprintf(fp, "            nr_irqs: %d\n", machdep->nr_irqs);
Packit bf408e
        fprintf(fp, "      eframe_search: alpha_eframe_search()\n");
Packit bf408e
        fprintf(fp, "         back_trace: alpha_back_trace_cmd()\n");
Packit bf408e
        fprintf(fp, "    processor_speed: alpha_processor_speed()\n");
Packit bf408e
        fprintf(fp, "              uvtop: alpha_uvtop()\n");
Packit bf408e
        fprintf(fp, "              kvtop: alpha_uvtop()\n");
Packit bf408e
        fprintf(fp, "       get_task_pgd: alpha_get_task_pgd()\n");
Packit bf408e
	if (machdep->dump_irq == generic_dump_irq)
Packit bf408e
		fprintf(fp, "           dump_irq: generic_dump_irq()\n");
Packit bf408e
	else
Packit bf408e
		fprintf(fp, "           dump_irq: alpha_dump_irq()\n");
Packit bf408e
	fprintf(fp, "    get_stack_frame: alpha_get_stack_frame()\n");
Packit bf408e
	fprintf(fp, "      get_stackbase: generic_get_stackbase()\n");
Packit bf408e
	fprintf(fp, "       get_stacktop: generic_get_stacktop()\n");
Packit bf408e
        fprintf(fp, "      translate_pte: alpha_translate_pte()\n");
Packit bf408e
	fprintf(fp, "        memory_size: alpha_get_memory_size()\n");
Packit bf408e
	fprintf(fp, "      vmalloc_start: alpha_get_vmalloc_start()\n");
Packit bf408e
	fprintf(fp, "       is_task_addr: alpha_is_task_addr()\n");
Packit bf408e
	fprintf(fp, "      verify_symbol: alpha_verify_symbol()\n");
Packit bf408e
	fprintf(fp, "         dis_filter: alpha_dis_filter()\n");
Packit bf408e
	fprintf(fp, "           cmd_mach: alpha_cmd_mach()\n");
Packit bf408e
	fprintf(fp, "       get_smp_cpus: alpha_get_smp_cpus()\n");
Packit bf408e
        fprintf(fp, "          is_kvaddr: generic_is_kvaddr()\n");
Packit bf408e
        fprintf(fp, "          is_uvaddr: generic_is_uvaddr()\n");
Packit bf408e
        fprintf(fp, "       verify_paddr: generic_verify_paddr()\n");
Packit bf408e
	fprintf(fp, "    init_kernel_pgd: NULL\n");
Packit bf408e
	fprintf(fp, "    value_to_symbol: generic_machdep_value_to_symbol()\n");
Packit bf408e
	fprintf(fp, "  line_number_hooks: alpha_line_number_hooks\n");
Packit bf408e
        fprintf(fp, "      last_pgd_read: %lx\n", machdep->last_pgd_read);
Packit bf408e
        fprintf(fp, "      last_pmd_read: %lx\n", machdep->last_pmd_read);
Packit bf408e
        fprintf(fp, "     last_ptbl_read: %lx\n", machdep->last_ptbl_read);
Packit bf408e
        fprintf(fp, "                pgd: %lx\n", (ulong)machdep->pgd);
Packit bf408e
        fprintf(fp, "                pmd: %lx\n", (ulong)machdep->pmd);
Packit bf408e
        fprintf(fp, "               ptbl: %lx\n", (ulong)machdep->ptbl);
Packit bf408e
	fprintf(fp, "       ptrs_per_pgd: %d\n", machdep->ptrs_per_pgd);
Packit bf408e
        fprintf(fp, "           machspec: %lx\n", (ulong)machdep->machspec);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Fix up jsr's to show the right target.
Packit bf408e
 *
Packit bf408e
 *  If a value is passed with no buf, then cmd_dis is fishing for whether
Packit bf408e
 *  the GP can be calculated from the first couple of instructions of the
Packit bf408e
 *  target routine:
Packit bf408e
 *
Packit bf408e
 *    0xfffffc0000349fa0 <sys_read>:  	      ldah    gp,35(t12)
Packit bf408e
 *    0xfffffc0000349fa4 <sys_read+4>:        lda     gp,6216(gp)
Packit bf408e
 *
Packit bf408e
 *  If a buf pointer is passed, then check whether the t12 register
Packit bf408e
 *  is being set up as an offset from gp, then calculate the target address:
Packit bf408e
 *
Packit bf408e
 *    0xfffffc000042c364 <start_tty+228>:     ldq     t12,-29336(gp)
Packit bf408e
 *    0xfffffc000042c368 <start_tty+232>:     
Packit bf408e
 *       jsr ra,(t12),0xfffffc0000429dc0 <decr_console+96>
Packit bf408e
 * 
Packit bf408e
 *  If the next instruction is a jsr ra,(t12), then correct the bracketed 
Packit bf408e
 *  target address translation.
Packit bf408e
 *  
Packit bf408e
 */
Packit bf408e
Packit bf408e
#define LDAH_GP_T12  (0x27bb0000)
Packit bf408e
#define LDA_GP_GP    (0x23bd0000)
Packit bf408e
#define LDQ_T12_GP   (0xa77d0000)   
Packit bf408e
#define JSR_RA_T12   (0x6b5b0000)
Packit bf408e
Packit bf408e
#define OPCODE_OPERAND_MASK  (0xffff0000)
Packit bf408e
#define OPCODE_MEM_DISP_MASK (0x0000ffff)
Packit bf408e
Packit bf408e
static struct instruction_data {
Packit bf408e
	uint inst[2];
Packit bf408e
	short mem_disp[2];
Packit bf408e
	ulong gp;
Packit bf408e
	ulong target;
Packit bf408e
	char *curfunc;
Packit bf408e
} instruction_data = { {0} };
Packit bf408e
Packit bf408e
static int
Packit bf408e
alpha_dis_filter(ulong vaddr, char *buf, unsigned int output_radix)
Packit bf408e
{
Packit bf408e
	struct syment *sp;
Packit bf408e
	struct instruction_data *id;
Packit bf408e
	char buf2[BUFSIZE], *p1;
Packit bf408e
Packit bf408e
	id = &instruction_data;
Packit bf408e
Packit bf408e
	if (!buf) {
Packit bf408e
		BZERO(id, sizeof(struct instruction_data));
Packit bf408e
Packit bf408e
		if (!(sp = value_search(vaddr, NULL)))   
Packit bf408e
			return FALSE;
Packit bf408e
Packit bf408e
		readmem(sp->value, KVADDR, &id->inst[0], 
Packit bf408e
			sizeof(uint) * 2, "two instructions", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
		if (((id->inst[0] & OPCODE_OPERAND_MASK) == LDAH_GP_T12) &&
Packit bf408e
		    ((id->inst[1] & OPCODE_OPERAND_MASK) == LDA_GP_GP)) {
Packit bf408e
			id->mem_disp[0] = (short)(id->inst[0] & 
Packit bf408e
				OPCODE_MEM_DISP_MASK);
Packit bf408e
			id->mem_disp[1] = (short)(id->inst[1] & 
Packit bf408e
				OPCODE_MEM_DISP_MASK);
Packit bf408e
			id->gp = sp->value + (65536*id->mem_disp[0]) +
Packit bf408e
				id->mem_disp[1];
Packit bf408e
			id->curfunc = sp->name;
Packit bf408e
Packit bf408e
			if (CRASHDEBUG(1))
Packit bf408e
                            console("%s: ldah(%d) and lda(%d) gp: %lx\n",
Packit bf408e
                                id->curfunc,
Packit bf408e
                                id->mem_disp[0], id->mem_disp[1],
Packit bf408e
                                id->gp);
Packit bf408e
Packit bf408e
			return TRUE;
Packit bf408e
		} 
Packit bf408e
                               /* send all lines through the generic */
Packit bf408e
		return TRUE;   /* dis_address_translation() filter */
Packit bf408e
	}
Packit bf408e
Packit bf408e
	dis_address_translation(vaddr, buf, output_radix);
Packit bf408e
Packit bf408e
	if (!id->gp || !(sp = value_search(vaddr, NULL)) || 
Packit bf408e
	    !STREQ(id->curfunc, sp->name)) {
Packit bf408e
		BZERO(id, sizeof(struct instruction_data));
Packit bf408e
		return FALSE;
Packit bf408e
	}
Packit bf408e
Packit bf408e
        readmem(vaddr, KVADDR, &id->inst[0],
Packit bf408e
        	sizeof(uint), "one instruction", FAULT_ON_ERROR);
Packit bf408e
        
Packit bf408e
	if ((id->inst[0] & OPCODE_OPERAND_MASK) == JSR_RA_T12) {
Packit bf408e
Packit bf408e
		if (!id->target || !strstr(buf, "jsr\tra,(t12)") ||
Packit bf408e
		    !strstr(buf, "<"))
Packit bf408e
			return FALSE;
Packit bf408e
Packit bf408e
		p1 = strstr(strstr(buf, "jsr"), "0x");
Packit bf408e
		sprintf(p1, "0x%lx <%s>%s", 
Packit bf408e
			id->target,
Packit bf408e
			value_to_symstr(id->target, buf2, output_radix),
Packit bf408e
			CRASHDEBUG(1) ? "  [PATCHED]\n" : "\n");
Packit bf408e
		return TRUE;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if ((id->inst[0] & OPCODE_OPERAND_MASK) == LDQ_T12_GP) {
Packit bf408e
		id->mem_disp[0] = (short)(id->inst[0] & OPCODE_MEM_DISP_MASK);
Packit bf408e
        	readmem(id->gp + id->mem_disp[0], KVADDR, &id->target,
Packit bf408e
                	sizeof(ulong), "jsr target", FAULT_ON_ERROR);
Packit bf408e
	} else
Packit bf408e
		id->target = 0;
Packit bf408e
Packit bf408e
	return TRUE;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  For some reason gdb can go off into the weeds translating text addresses,
Packit bf408e
 *  so this routine both fixes the references as well as imposing the current
Packit bf408e
 *  output radix on the translations.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
dis_address_translation(ulong vaddr, char *inbuf, unsigned int output_radix)
Packit bf408e
{
Packit bf408e
	char buf1[BUFSIZE];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	char *colon, *p1;
Packit bf408e
	int argc;
Packit bf408e
	char *argv[MAXARGS];
Packit bf408e
	ulong value;
Packit bf408e
Packit bf408e
	console("IN: %s", inbuf);
Packit bf408e
Packit bf408e
	colon = strstr(inbuf, ":");
Packit bf408e
Packit bf408e
	if (colon) {
Packit bf408e
		sprintf(buf1, "0x%lx <%s>", vaddr,
Packit bf408e
			value_to_symstr(vaddr, buf2, output_radix));
Packit bf408e
		sprintf(buf2, "%s%s", buf1, colon);
Packit bf408e
		strcpy(inbuf, buf2);
Packit bf408e
	}
Packit bf408e
Packit bf408e
	strcpy(buf1, inbuf);
Packit bf408e
	argc = parse_line(buf1, argv);
Packit bf408e
Packit bf408e
	if ((FIRSTCHAR(argv[argc-1]) == '<') && 
Packit bf408e
	    (LASTCHAR(argv[argc-1]) == '>')) {
Packit bf408e
		p1 = rindex(inbuf, '<');
Packit bf408e
		while ((p1 > inbuf) && (*p1 != ',')) 
Packit bf408e
			p1--;
Packit bf408e
Packit bf408e
		if (!STRNEQ(p1, ",0x"))
Packit bf408e
			return;
Packit bf408e
		p1++;
Packit bf408e
Packit bf408e
		if (!extract_hex(p1, &value, NULLCHAR, TRUE))
Packit bf408e
			return;
Packit bf408e
Packit bf408e
		sprintf(buf1, "0x%lx <%s>\n", value,	
Packit bf408e
			value_to_symstr(value, buf2, output_radix));
Packit bf408e
Packit bf408e
		sprintf(p1, "%s", buf1);
Packit bf408e
	}
Packit bf408e
Packit bf408e
	console("    %s", inbuf);
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  If we're generically-inclined, call generic_dump_irq().  Otherwise
Packit bf408e
 *  dump the IRQ table the old-fashioned way.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
alpha_dump_irq(int irq)
Packit bf408e
{
Packit bf408e
	ulong action;
Packit bf408e
	ulong value;
Packit bf408e
        char *arglist[MAXARGS];
Packit bf408e
	int argc, others;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
Packit bf408e
	if (symbol_exists("irq_desc")) {
Packit bf408e
		machdep->dump_irq = generic_dump_irq;
Packit bf408e
		return(generic_dump_irq(irq));
Packit bf408e
	}
Packit bf408e
Packit bf408e
	action = symbol_value("irq_action") + (sizeof(void *) * irq);
Packit bf408e
Packit bf408e
        readmem(action, KVADDR, &action,
Packit bf408e
                sizeof(void *), "irq_action pointer", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	if (!action) {
Packit bf408e
		fprintf(fp, "    IRQ: %d\n", irq);
Packit bf408e
		fprintf(fp, "handler:\n"); 
Packit bf408e
		fprintf(fp, "  flags: \n");
Packit bf408e
		fprintf(fp, "   mask: \n");
Packit bf408e
		fprintf(fp, "   name: \n");
Packit bf408e
		fprintf(fp, " dev_id: \n");
Packit bf408e
		fprintf(fp, "   next: \n\n");
Packit bf408e
		return;	
Packit bf408e
	}
Packit bf408e
Packit bf408e
        fprintf(fp, "    IRQ: %d\n", irq);
Packit bf408e
Packit bf408e
	open_tmpfile();
Packit bf408e
Packit bf408e
do_linked_action:
Packit bf408e
	dump_struct("irqaction", action, RADIX(16));
Packit bf408e
	action = 0;
Packit bf408e
        rewind(pc->tmpfile);
Packit bf408e
        while (fgets(buf, BUFSIZE, pc->tmpfile)) {
Packit bf408e
		strip_comma(buf);
Packit bf408e
		argc = parse_line(buf, arglist);
Packit bf408e
		if (STREQ(arglist[0], "struct") || STREQ(buf, "};"))
Packit bf408e
			continue;
Packit bf408e
Packit bf408e
                if (STREQ(arglist[0], "handler")) {
Packit bf408e
                        fprintf(pc->saved_fp, "handler: %s  ",
Packit bf408e
                        	strip_hex(arglist[2]));
Packit bf408e
			if (argc == 4)
Packit bf408e
                        	fprintf(pc->saved_fp, "%s", arglist[3]);
Packit bf408e
			fprintf(pc->saved_fp, "\n");
Packit bf408e
                }
Packit bf408e
                if (STREQ(arglist[0], "flags")) {
Packit bf408e
			value = htol(strip_comma(arglist[2]), 
Packit bf408e
				FAULT_ON_ERROR, NULL);
Packit bf408e
                        fprintf(pc->saved_fp, 
Packit bf408e
				"  flags: %lx  ", value);
Packit bf408e
				
Packit bf408e
			if (value) {
Packit bf408e
				others = 0;
Packit bf408e
				fprintf(pc->saved_fp, "(");
Packit bf408e
	
Packit bf408e
				if (value & SA_INTERRUPT)
Packit bf408e
					fprintf(pc->saved_fp,
Packit bf408e
					    "%sSA_INTERRUPT",
Packit bf408e
						others++ ? "|" : "");
Packit bf408e
				if (value & SA_PROBE)
Packit bf408e
                                        fprintf(pc->saved_fp,
Packit bf408e
                                            "%sSA_PROBE",
Packit bf408e
                                                others++ ? "|" : "");
Packit bf408e
				if (value & SA_SAMPLE_RANDOM)
Packit bf408e
                                         fprintf(pc->saved_fp,
Packit bf408e
                                             "%sSA_SAMPLE_RANDOM",
Packit bf408e
                                                 others++ ? "|" : "");
Packit bf408e
				if (value & SA_SHIRQ)
Packit bf408e
                                         fprintf(pc->saved_fp,
Packit bf408e
                                             "%sSA_SHIRQ",
Packit bf408e
                                                 others++ ? "|" : "");
Packit bf408e
				fprintf(pc->saved_fp, ")");
Packit bf408e
				if (value & ~ACTION_FLAGS) {
Packit bf408e
					fprintf(pc->saved_fp,
Packit bf408e
					    "  (bits %lx not translated)",
Packit bf408e
						value & ~ACTION_FLAGS);
Packit bf408e
				}
Packit bf408e
			} 
Packit bf408e
Packit bf408e
			fprintf(pc->saved_fp, "\n");
Packit bf408e
Packit bf408e
		}
Packit bf408e
                if (STREQ(arglist[0], "mask")) {
Packit bf408e
			value = htol(strip_comma(arglist[2]), 
Packit bf408e
				FAULT_ON_ERROR, NULL);
Packit bf408e
                        fprintf(pc->saved_fp,
Packit bf408e
                        	"   mask: %lx\n", value);
Packit bf408e
		}
Packit bf408e
		if (STREQ(arglist[0], "name")) {
Packit bf408e
                        fprintf(pc->saved_fp, "   name: %s  ",
Packit bf408e
                        	strip_hex(arglist[2]));
Packit bf408e
			if (argc == 4)
Packit bf408e
				fprintf(pc->saved_fp, "\"%s\"", arglist[3]);
Packit bf408e
                        fprintf(pc->saved_fp, "\n");
Packit bf408e
                }
Packit bf408e
		if (STREQ(arglist[0], "dev_id")) {
Packit bf408e
                        value = htol(strip_comma(arglist[2]), 
Packit bf408e
				FAULT_ON_ERROR, NULL);
Packit bf408e
                        fprintf(pc->saved_fp,
Packit bf408e
                                " dev_id: %lx\n", value);
Packit bf408e
                }
Packit bf408e
		if (STREQ(arglist[0], "next")) {
Packit bf408e
                        value = htol(strip_comma(arglist[2]), 
Packit bf408e
				FAULT_ON_ERROR, NULL);
Packit bf408e
                        fprintf(pc->saved_fp,
Packit bf408e
                                "   next: %s\n",
Packit bf408e
                                	strip_hex(arglist[2]));
Packit bf408e
			if (value)
Packit bf408e
				action = value;
Packit bf408e
                }
Packit bf408e
	}
Packit bf408e
	close_tmpfile();
Packit bf408e
Packit bf408e
	fprintf(fp, "\n");
Packit bf408e
Packit bf408e
        if (action)
Packit bf408e
                goto do_linked_action;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Get a stack frame combination of pc and ra from the most relevent spot.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
alpha_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
Packit bf408e
{
Packit bf408e
        struct syment *sp;
Packit bf408e
        ulong ksp;
Packit bf408e
	ulong ip;
Packit bf408e
Packit bf408e
	if (pcp) {
Packit bf408e
	        if (DUMPFILE() && is_panic_thread(bt->task)) {
Packit bf408e
			sp = next_symbol("crash_save_current_state", NULL);	
Packit bf408e
Packit bf408e
	                if (HWRESET_TASK(bt->task))
Packit bf408e
	                        ip = get_percpu_data(0, GET_HALT_PC, 0);
Packit bf408e
			else if (sp) 
Packit bf408e
	                        ip = sp->value - 4;
Packit bf408e
			else
Packit bf408e
	                       	ip = symbol_value("crash_save_current_state") 
Packit bf408e
					+ 16;
Packit bf408e
	        } else 
Packit bf408e
	        	get_alpha_frame(bt, &ip, NULL);
Packit bf408e
Packit bf408e
        	*pcp = ip;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (spp) {
Packit bf408e
		ip = 0;
Packit bf408e
       		if (!get_panic_ksp(bt, &ksp))
Packit bf408e
                	get_alpha_frame(bt, 
Packit bf408e
				HWRESET_TASK(bt->task) ? &ip : NULL, &ksp;;
Packit bf408e
Packit bf408e
        	if (!INSTACK(ksp, bt)) 
Packit bf408e
                	error(FATAL, 
Packit bf408e
			    "cannot determine starting stack address\n", 
Packit bf408e
				bt->task);
Packit bf408e
Packit bf408e
		*spp = ksp;
Packit bf408e
		if (ip)
Packit bf408e
			*pcp = ip;
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Do the work formerly done by alpha_get_sp() and alpha_get_pc().
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
get_alpha_frame(struct bt_info *bt, ulong *getpc, ulong *getsp)
Packit bf408e
{
Packit bf408e
	int i;
Packit bf408e
	ulong ip;
Packit bf408e
	ulong r26;
Packit bf408e
	ulong ksp, sp;
Packit bf408e
	ulong *spp;
Packit bf408e
	ulong percpu_ra;
Packit bf408e
	ulong percpu_pv;
Packit bf408e
	struct percpu_data percpu_data;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	ulong task;
Packit bf408e
	ulong *stack;
Packit bf408e
Packit bf408e
	task = bt->task;
Packit bf408e
	stack = (ulong *)bt->stackbuf;
Packit bf408e
Packit bf408e
	if (tt->flags & THREAD_INFO) { /* pcb.ksp is 1st word in thread_info */
Packit bf408e
		readmem(bt->tc->thread_info, KVADDR, &ksp, sizeof(ulong),
Packit bf408e
                	"thread_info pcb ksp", FAULT_ON_ERROR);
Packit bf408e
		sp = ksp;
Packit bf408e
	} else if (VALID_MEMBER(task_struct_tss_ksp))
Packit bf408e
                ksp = sp = stack[OFFSET(task_struct_tss_ksp)/sizeof(long)];
Packit bf408e
	else 
Packit bf408e
                ksp = sp = stack[OFFSET(task_struct_thread_ksp)/sizeof(long)];
Packit bf408e
Packit bf408e
	ip = 0;
Packit bf408e
	percpu_ra = percpu_pv = 0;
Packit bf408e
	spp = &stack[(sp - task)/sizeof(long)];
Packit bf408e
Packit bf408e
        if (DUMPFILE() && getsp) { 
Packit bf408e
		if (HWRESET_TASK(task)) {
Packit bf408e
			if (INSTACK(sp, bt)) {
Packit bf408e
				*getsp = sp;
Packit bf408e
				return;
Packit bf408e
			} else {
Packit bf408e
				get_percpu_data(0, 0, &percpu_data);
Packit bf408e
				percpu_ra = percpu_data.halt_ra;
Packit bf408e
				percpu_pv = percpu_data.halt_pv;
Packit bf408e
				spp = &stack[roundup(SIZE(task_struct), 
Packit bf408e
					sizeof(ulong)) / sizeof(ulong)];
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
Packit bf408e
            	if (!percpu_ra && (STREQ(closest_symbol(*spp), "panic") ||
Packit bf408e
                    STREQ(closest_symbol(*spp), "handle_ipi"))) {
Packit bf408e
                	*getsp = sp;
Packit bf408e
                	return;
Packit bf408e
		}
Packit bf408e
        }
Packit bf408e
Packit bf408e
percpu_retry:
Packit bf408e
Packit bf408e
	if (CRASHDEBUG(1) && percpu_ra) {
Packit bf408e
		fprintf(fp, "get_alpha_frame: look for %lx (%s)\n",
Packit bf408e
			percpu_ra, value_to_symstr(percpu_ra, buf, 0));
Packit bf408e
	}
Packit bf408e
Packit bf408e
	for (i = 0, spp++; spp < &stack[LONGS_PER_STACK]; spp++,i++) {
Packit bf408e
Packit bf408e
		if (CRASHDEBUG(1) && (percpu_ra || percpu_pv) && 
Packit bf408e
		    is_kernel_text(*spp)) {
Packit bf408e
			fprintf(fp, "%lx: %lx (%s)\n", 
Packit bf408e
				((ulong)spp - (ulong)stack) + task,
Packit bf408e
				*spp, value_to_symstr(*spp, buf, 0)); 
Packit bf408e
		}
Packit bf408e
Packit bf408e
                if (percpu_ra) {
Packit bf408e
                        if (*spp == percpu_ra) {
Packit bf408e
				*getsp = ((ulong)spp - (ulong)stack) + task;
Packit bf408e
				return;
Packit bf408e
			}
Packit bf408e
                        continue;
Packit bf408e
                } else if (percpu_pv) {
Packit bf408e
                        if (*spp == percpu_pv) {
Packit bf408e
                                *getsp = ((ulong)spp - (ulong)stack) + task;
Packit bf408e
				if (getpc)
Packit bf408e
					*getpc = percpu_pv;
Packit bf408e
                                return;
Packit bf408e
                        }
Packit bf408e
                        continue;
Packit bf408e
		}
Packit bf408e
Packit bf408e
		if (!INSTACK(*spp, bt))
Packit bf408e
			continue;
Packit bf408e
Packit bf408e
		if (is_kernel_text(*(spp+1))) {
Packit bf408e
			sp = *spp;
Packit bf408e
			ip = *(spp+1);
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (percpu_ra) {
Packit bf408e
		percpu_ra = 0;
Packit bf408e
Packit bf408e
		error(INFO,
Packit bf408e
            "cannot find return address (percpu_ra) in HARDWARE RESET stack\n");
Packit bf408e
		error(INFO,
Packit bf408e
         "looking for procedure address (percpu_pv) in HARDWARE RESET stack\n");
Packit bf408e
Packit bf408e
        	if (CRASHDEBUG(1)) {
Packit bf408e
                	fprintf(fp, "get_alpha_frame: look for %lx (%s)\n",
Packit bf408e
                        	percpu_pv, value_to_symstr(percpu_pv, buf, 0));
Packit bf408e
        	}
Packit bf408e
		spp = &stack[roundup(SIZE(task_struct), 
Packit bf408e
			sizeof(ulong)) / sizeof(ulong)];
Packit bf408e
Packit bf408e
		goto percpu_retry;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (percpu_pv) {
Packit bf408e
		error(INFO,
Packit bf408e
         "cannot find procedure address (percpu_pv) in HARDWARE RESET stack\n");
Packit bf408e
	}
Packit bf408e
Packit bf408e
	/*
Packit bf408e
	 *  Check for a forked task that has not yet run in user space.
Packit bf408e
	 */
Packit bf408e
	if (!ip) {
Packit bf408e
                if (INSTACK(ksp + OFFSET(switch_stack_r26), bt)) {
Packit bf408e
                        readmem(ksp + OFFSET(switch_stack_r26), KVADDR, 
Packit bf408e
				&r26, sizeof(ulong),
Packit bf408e
                                "ret_from_smp_fork check", FAULT_ON_ERROR);
Packit bf408e
                        if (STREQ(closest_symbol(r26), "ret_from_smp_fork") ||
Packit bf408e
			    STREQ(closest_symbol(r26), "ret_from_smpfork")) {
Packit bf408e
				ip = r26;
Packit bf408e
				sp = ksp;
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if (getsp)
Packit bf408e
		*getsp = sp;
Packit bf408e
	if (getpc)
Packit bf408e
		*getpc = ip;
Packit bf408e
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Fill the percpu_data structure with information from the 
Packit bf408e
 *  hwrpb/percpu_data structures for a given CPU.  If requested,
Packit bf408e
 *  return one of the specified entries.
Packit bf408e
 */
Packit bf408e
static ulong
Packit bf408e
get_percpu_data(int cpu, ulong flag, struct percpu_data *pd)
Packit bf408e
{
Packit bf408e
        ulong hwrpb, halt_ra, halt_PC, halt_pv;
Packit bf408e
        unsigned long processor_offset, processor_size;
Packit bf408e
Packit bf408e
        get_symbol_data("hwrpb", sizeof(void *), &hwrpb);
Packit bf408e
Packit bf408e
        readmem(hwrpb+OFFSET(hwrpb_struct_processor_offset), KVADDR,
Packit bf408e
                &processor_offset, sizeof(ulong),
Packit bf408e
                "hwrpb processor_offset", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
        readmem(hwrpb+OFFSET(hwrpb_struct_processor_size), KVADDR,
Packit bf408e
                &processor_size, sizeof(ulong),
Packit bf408e
                "hwrpb processor_size", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
        readmem(hwrpb + processor_offset + (cpu * processor_size) +
Packit bf408e
                OFFSET(percpu_struct_halt_PC),
Packit bf408e
                KVADDR, &halt_PC, sizeof(ulong),
Packit bf408e
                "percpu halt_PC", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
        readmem(hwrpb + processor_offset + (cpu * processor_size) +
Packit bf408e
                OFFSET(percpu_struct_halt_ra),
Packit bf408e
                KVADDR, &halt_ra, sizeof(ulong),
Packit bf408e
                "percpu halt_ra", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
        readmem(hwrpb + processor_offset + (cpu * processor_size) +
Packit bf408e
                OFFSET(percpu_struct_halt_pv),
Packit bf408e
                KVADDR, &halt_pv, sizeof(ulong),
Packit bf408e
                "percpu halt_pv", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	if (pd) {
Packit bf408e
		pd->halt_PC = halt_PC;
Packit bf408e
		pd->halt_ra = halt_ra;
Packit bf408e
		pd->halt_pv = halt_pv;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	switch (flag)
Packit bf408e
	{
Packit bf408e
	case GET_HALT_PC:
Packit bf408e
		return halt_PC;
Packit bf408e
		
Packit bf408e
	case GET_HALT_RA:
Packit bf408e
		return halt_ra;
Packit bf408e
Packit bf408e
	case GET_HALT_PV:
Packit bf408e
		return halt_pv;
Packit bf408e
Packit bf408e
	default:
Packit bf408e
		return 0;
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Translate a PTE, returning TRUE if the page is _PAGE_VALID or _PAGE_PRESENT,
Packit bf408e
 *  whichever is appropriate for the machine type.  If a physaddr pointer is
Packit bf408e
 *  passed in, don't print anything.
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
alpha_translate_pte(ulong pte, void *physaddr, ulonglong unused)
Packit bf408e
{
Packit bf408e
	int c, len1, len2, len3, others, page_present;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
        char buf2[BUFSIZE];
Packit bf408e
        char buf3[BUFSIZE];
Packit bf408e
	char ptebuf[BUFSIZE];
Packit bf408e
	char physbuf[BUFSIZE];
Packit bf408e
        char *arglist[MAXARGS];
Packit bf408e
	physaddr_t paddr;
Packit bf408e
Packit bf408e
        paddr = PTOB(pte >> 32);
Packit bf408e
	page_present = (pte & _PAGE_VALID);
Packit bf408e
Packit bf408e
	if (physaddr) {
Packit bf408e
		*((ulong *)physaddr) = paddr;
Packit bf408e
		return page_present;
Packit bf408e
	}
Packit bf408e
Packit bf408e
	sprintf(ptebuf, "%lx", pte);
Packit bf408e
	len1 = MAX(strlen(ptebuf), strlen("PTE"));
Packit bf408e
	fprintf(fp, "%s  ", mkstring(buf, len1, CENTER|LJUST, "PTE"));
Packit bf408e
Packit bf408e
        if (!page_present && pte) {
Packit bf408e
                swap_location(pte, buf);
Packit bf408e
                if ((c = parse_line(buf, arglist)) != 3)
Packit bf408e
			error(FATAL, "cannot determine swap location\n");
Packit bf408e
Packit bf408e
                len2 = MAX(strlen(arglist[0]), strlen("SWAP"));
Packit bf408e
                len3 = MAX(strlen(arglist[2]), strlen("OFFSET"));
Packit bf408e
Packit bf408e
                fprintf(fp, "%s  %s\n",
Packit bf408e
                        mkstring(buf2, len2, CENTER|LJUST, "SWAP"),
Packit bf408e
                        mkstring(buf3, len3, CENTER|LJUST, "OFFSET"));
Packit bf408e
Packit bf408e
                strcpy(buf2, arglist[0]);
Packit bf408e
                strcpy(buf3, arglist[2]);
Packit bf408e
                fprintf(fp, "%s  %s  %s\n",
Packit bf408e
                        mkstring(ptebuf, len1, CENTER|RJUST, NULL),
Packit bf408e
                        mkstring(buf2, len2, CENTER|RJUST, NULL),
Packit bf408e
                        mkstring(buf3, len3, CENTER|RJUST, NULL));
Packit bf408e
Packit bf408e
                return page_present;
Packit bf408e
        }
Packit bf408e
Packit bf408e
	sprintf(physbuf, "%llx", paddr);
Packit bf408e
	len2 = MAX(strlen(physbuf), strlen("PHYSICAL"));
Packit bf408e
	fprintf(fp, "%s  ", mkstring(buf, len2, CENTER|LJUST, "PHYSICAL"));
Packit bf408e
Packit bf408e
	fprintf(fp, "FLAGS\n");
Packit bf408e
Packit bf408e
	fprintf(fp, "%s  %s  ",  
Packit bf408e
		mkstring(ptebuf, len1, CENTER|RJUST, NULL),
Packit bf408e
		mkstring(physbuf, len2, CENTER|RJUST, NULL)); 
Packit bf408e
	fprintf(fp, "(");
Packit bf408e
	others = 0;
Packit bf408e
Packit bf408e
	if (pte) {
Packit bf408e
		if (pte & _PAGE_VALID)
Packit bf408e
			fprintf(fp, "%sVALID", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_FOR)
Packit bf408e
			fprintf(fp, "%sFOR", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_FOW)
Packit bf408e
			fprintf(fp, "%sFOW", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_FOE)
Packit bf408e
			fprintf(fp, "%sFOE", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_ASM)
Packit bf408e
			fprintf(fp, "%sASM", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_KRE)
Packit bf408e
			fprintf(fp, "%sKRE", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_URE)
Packit bf408e
			fprintf(fp, "%sURE", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_KWE)
Packit bf408e
			fprintf(fp, "%sKWE", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_UWE)
Packit bf408e
			fprintf(fp, "%sUWE", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_DIRTY)
Packit bf408e
			fprintf(fp, "%sDIRTY", others++ ? "|" : "");
Packit bf408e
		if (pte & _PAGE_ACCESSED)
Packit bf408e
			fprintf(fp, "%sACCESSED", others++ ? "|" : "");
Packit bf408e
	} else {
Packit bf408e
		fprintf(fp, "no mapping");
Packit bf408e
	}
Packit bf408e
Packit bf408e
	fprintf(fp, ")\n");
Packit bf408e
Packit bf408e
	return page_present;
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  This is currently not machine-dependent, but eventually I'd prefer to use
Packit bf408e
 *  the HWPCB for the real physical memory size.
Packit bf408e
 */
Packit bf408e
static uint64_t
Packit bf408e
alpha_memory_size(void)
Packit bf408e
{
Packit bf408e
	return (generic_memory_size());
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Determine where vmalloc'd memory starts.
Packit bf408e
 */
Packit bf408e
static ulong
Packit bf408e
alpha_vmalloc_start(void)
Packit bf408e
{
Packit bf408e
	return VMALLOC_START;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  ALPHA tasks are all stacksize-aligned.
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
alpha_is_task_addr(ulong task)
Packit bf408e
{
Packit bf408e
        return (IS_KVADDR(task) && (ALIGNED_STACK_OFFSET(task) == 0));
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Keep or reject a symbol from the kernel namelist.
Packit bf408e
 */
Packit bf408e
int
Packit bf408e
alpha_verify_symbol(const char *name, ulong value, char type)
Packit bf408e
{
Packit bf408e
        if (CRASHDEBUG(8) && name && strlen(name))
Packit bf408e
                fprintf(fp, "%016lx %s\n", value, name);
Packit bf408e
Packit bf408e
	return (name && strlen(name) && (value > MIN_SYMBOL_VALUE));
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *   Override smp_num_cpus if possible and necessary.
Packit bf408e
 */
Packit bf408e
int
Packit bf408e
alpha_get_smp_cpus(void)
Packit bf408e
{
Packit bf408e
	int cpus;
Packit bf408e
Packit bf408e
        if ((cpus = get_cpus_online()))
Packit bf408e
                return cpus;
Packit bf408e
        else
Packit bf408e
        	return kt->cpus;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Machine dependent command.
Packit bf408e
 */
Packit bf408e
void
Packit bf408e
alpha_cmd_mach(void)
Packit bf408e
{
Packit bf408e
        int c, cflag;
Packit bf408e
	unsigned int radix;
Packit bf408e
Packit bf408e
	cflag = radix = 0;
Packit bf408e
Packit bf408e
        while ((c = getopt(argcnt, args, "cxd")) != EOF) {
Packit bf408e
                switch(c)
Packit bf408e
                {
Packit bf408e
		case 'c':
Packit bf408e
			cflag++;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case 'x':
Packit bf408e
			if (radix == 10)
Packit bf408e
				error(FATAL,
Packit bf408e
					"-d and -x are mutually exclusive\n");
Packit bf408e
			radix = 16;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case 'd':
Packit bf408e
			if (radix == 16)
Packit bf408e
				error(FATAL,
Packit bf408e
					"-d and -x are mutually exclusive\n");
Packit bf408e
			radix = 10;
Packit bf408e
			break;
Packit bf408e
Packit bf408e
                default:
Packit bf408e
                        argerrs++;
Packit bf408e
                        break;
Packit bf408e
                }
Packit bf408e
        }
Packit bf408e
Packit bf408e
        if (argerrs)
Packit bf408e
                cmd_usage(pc->curcmd, SYNOPSIS);
Packit bf408e
Packit bf408e
	if (cflag)
Packit bf408e
		display_hwrpb(radix);
Packit bf408e
	else
Packit bf408e
		alpha_display_machine_stats();
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  "mach" command output.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
alpha_display_machine_stats(void)
Packit bf408e
{
Packit bf408e
        struct new_utsname *uts;
Packit bf408e
        char buf[BUFSIZE];
Packit bf408e
        ulong mhz;
Packit bf408e
Packit bf408e
        uts = &kt->utsname;
Packit bf408e
Packit bf408e
        fprintf(fp, "       MACHINE TYPE: %s\n", uts->machine);
Packit bf408e
        fprintf(fp, "        MEMORY SIZE: %s\n", get_memory_size(buf));
Packit bf408e
        fprintf(fp, "               CPUS: %d\n", kt->cpus);
Packit bf408e
        fprintf(fp, "    PROCESSOR SPEED: ");
Packit bf408e
        if ((mhz = machdep->processor_speed()))
Packit bf408e
                fprintf(fp, "%ld Mhz\n", mhz);
Packit bf408e
        else
Packit bf408e
                fprintf(fp, "(unknown)\n");
Packit bf408e
        fprintf(fp, "                 HZ: %d\n", machdep->hz);
Packit bf408e
        fprintf(fp, "          PAGE SIZE: %d\n", PAGESIZE());
Packit bf408e
        fprintf(fp, "      L1 CACHE SIZE: %d\n", l1_cache_size());
Packit bf408e
        fprintf(fp, "KERNEL VIRTUAL BASE: %lx\n", machdep->kvbase);
Packit bf408e
        fprintf(fp, "KERNEL VMALLOC BASE: %lx\n", vt->vmalloc_start);
Packit bf408e
        fprintf(fp, "  KERNEL STACK SIZE: %ld\n", STACKSIZE());
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Display the hwrpb_struct and each percpu_struct.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
display_hwrpb(unsigned int radix)
Packit bf408e
{
Packit bf408e
	int cpu;
Packit bf408e
	ulong hwrpb, percpu;
Packit bf408e
        ulong processor_offset, processor_size;
Packit bf408e
	
Packit bf408e
        get_symbol_data("hwrpb", sizeof(void *), &hwrpb);
Packit bf408e
Packit bf408e
        readmem(hwrpb+OFFSET(hwrpb_struct_processor_offset), KVADDR,
Packit bf408e
                &processor_offset, sizeof(ulong),
Packit bf408e
                "hwrpb processor_offset", FAULT_ON_ERROR);
Packit bf408e
        readmem(hwrpb+OFFSET(hwrpb_struct_processor_size), KVADDR,
Packit bf408e
                &processor_size, sizeof(ulong),
Packit bf408e
                "hwrpb processor_size", FAULT_ON_ERROR);
Packit bf408e
Packit bf408e
	fprintf(fp, "HWRPB:\n");
Packit bf408e
	dump_struct("hwrpb_struct", hwrpb, radix);
Packit bf408e
Packit bf408e
	for (cpu = 0; cpu < kt->cpus; cpu++) {
Packit bf408e
		fprintf(fp, "\nCPU %d:\n", cpu); 
Packit bf408e
		percpu = hwrpb + processor_offset + (processor_size * cpu);
Packit bf408e
		dump_struct("percpu_struct", percpu, radix);
Packit bf408e
	}
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Perform any leftover pre-prompt machine-specific initialization tasks here.
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
alpha_post_init(void)
Packit bf408e
{
Packit bf408e
	modify_signame(7, "SIGEMT", NULL);
Packit bf408e
	modify_signame(10, "SIGBUS", NULL);
Packit bf408e
	modify_signame(12, "SIGSYS", NULL);
Packit bf408e
	modify_signame(16, "SIGURG", NULL);
Packit bf408e
	modify_signame(17, "SIGSTOP", NULL);
Packit bf408e
	modify_signame(18, "SIGTSTP", NULL);
Packit bf408e
	modify_signame(19, "SIGCONT", NULL);
Packit bf408e
	modify_signame(20, "SIGCHLD", NULL);
Packit bf408e
	modify_signame(23, "SIGIO", "SIGPOLL");
Packit bf408e
	modify_signame(29, "SIGINFO", "SIGPWR");
Packit bf408e
	modify_signame(30, "SIGUSR1", NULL);
Packit bf408e
	modify_signame(31, "SIGUSR2", NULL);
Packit bf408e
}
Packit bf408e
Packit bf408e
Packit bf408e
#endif /* ALPHA */