Source to machdep/ppc/kdp_machdep.c
/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @[email protected]
*
* "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License."
*
* @[email protected]
*/
/*
* Copyright (c) 1997 Apple Computer, Inc. All rights reserved.
* Copyright (c) 1994 NeXT Computer, Inc. All rights reserved.
*
* machdep/ppc/kdp_machdep.c
*
* Machine-dependent code for Remote Debugging Protocol
*
* History:
* March, 1997 Umesh Vaishampayan [[email protected]]
* Created.
* 03 Nov 1997 Herb Ruth [[email protected]]
* Added extern declarations for implicit function
* declarations. Changed dprintf macro to call kprintf()
* instead of kdp_printf() when KDP_TEST_HARNESS==1
* Added sync and isync ppc instructions to kdp_flush_cache().
*
*/
#import <sys/param.h>
#import <sys/systm.h>
#import <sys/mbuf.h>
#import <sys/socket.h>
#import <net/if.h>
#import <net/route.h>
#import <netinet/in.h>
#import <netinet/in_systm.h>
#import <netinet/ip.h>
#import <netinet/ip_var.h>
#import <netinet/in_pcb.h>
#import <mach/mach_types.h>
#import <kern/kdp_internal.h>
#import <kern/miniMon.h>
#import <bsd/sys/conf.h>
#import <bsd/sys/reboot.h>
#include <stdarg.h>
#import <sys/subr_prf.h>
#include <mach/exception.h>
#define KDP_TEST_HARNESS 0
#if KDP_TEST_HARNESS
/*#define dprintf(x) kdp_printf x*/
#define dprintf(x) kprintf x
#else
#define dprintf(x)
#endif
/* 03 Nov 1997 */
#warning extern declarations -- FIXME XXX
extern int cnputc(char c);
extern void kprintf(const char *format, ...);
extern boot(int paniced, int howto, char *command);
extern unsigned splhigh(void);
extern void splx(unsigned level);
extern void us_spin(int usec);
void
kdp_printf(
const char *format,
...
)
{
va_list ap;
static char rdpPrintfBuf[512];
char *p = rdpPrintfBuf;
va_start(ap, format);
prf(format, ap, TOSTR, (struct tty *)&p);
va_end(ap);
*p++ = '\0';
p = rdpPrintfBuf;
while (*p)
cnputc(*p++);
}
void
kdp_exception(
unsigned char *pkt,
int *len,
unsigned short *remote_port,
unsigned int exception,
unsigned int code,
unsigned int subcode
)
{
struct {
kdp_exception_t pkt;
kdp_exc_info_t exc;
} aligned_pkt;
kdp_exception_t *rq = (kdp_exception_t *)&aligned_pkt;
bcopy(pkt, rq, sizeof(*rq));
rq->hdr.request = KDP_EXCEPTION;
rq->hdr.is_reply = 0;
rq->hdr.seq = kdp.exception_seq;
rq->hdr.key = 0;
rq->hdr.len = sizeof (*rq) + sizeof(kdp_exc_info_t);
rq->n_exc_info = 1;
rq->exc_info[0].cpu = 0;
rq->exc_info[0].exception = exception;
rq->exc_info[0].code = code;
rq->exc_info[0].subcode = subcode;
rq->hdr.len += rq->n_exc_info * sizeof (kdp_exc_info_t);
bcopy(rq, pkt, rq->hdr.len);
kdp.exception_ack_needed = TRUE;
*remote_port = kdp.exception_port;
*len = rq->hdr.len;
}
void
kdp_exception_ack(
unsigned char *pkt,
int len
)
{
kdp_exception_ack_t aligned_pkt;
kdp_exception_ack_t *rq = (kdp_exception_ack_t *)&aligned_pkt;
if (len < sizeof (*rq))
return;
bcopy(pkt, rq, sizeof(*rq));
if (!rq->hdr.is_reply || rq->hdr.request != KDP_EXCEPTION)
return;
dprintf(("kdp_exception_ack: seq 0x%08x 0x%08x\n",
rq->hdr.seq, kdp.exception_seq));
if (rq->hdr.seq == kdp.exception_seq) {
kdp.exception_ack_needed = FALSE;
kdp.exception_seq++;
}
}
static void
kdp_getintegerstate(
struct ppc_thread_state *state
)
{
struct ppc_thread_state *saved_state;
saved_state = kdp.saved_state;
*state = (struct ppc_thread_state) { 0 };
state->srr0 = saved_state->srr0;
state->srr1 = saved_state->srr1;
state->r0 = saved_state->r0;
state->r1 = saved_state->r1;
state->r2 = saved_state->r2;
state->r3 = saved_state->r3;
state->r4 = saved_state->r4;
state->r5 = saved_state->r5;
state->r6 = saved_state->r6;
state->r7 = saved_state->r7;
state->r8 = saved_state->r8;
state->r9 = saved_state->r9;
state->r10 = saved_state->r10;
state->r11 = saved_state->r11;
state->r12 = saved_state->r12;
state->r13 = saved_state->r13;
state->r14 = saved_state->r14;
state->r15 = saved_state->r15;
state->r16 = saved_state->r16;
state->r17 = saved_state->r17;
state->r18 = saved_state->r18;
state->r19 = saved_state->r19;
state->r20 = saved_state->r20;
state->r21 = saved_state->r21;
state->r22 = saved_state->r22;
state->r23 = saved_state->r23;
state->r24 = saved_state->r24;
state->r25 = saved_state->r25;
state->r26 = saved_state->r26;
state->r27 = saved_state->r27;
state->r28 = saved_state->r28;
state->r29 = saved_state->r29;
state->r30 = saved_state->r30;
state->r31 = saved_state->r31;
state->cr = saved_state->cr;
state->xer = saved_state->xer;
state->lr = saved_state->lr;
state->ctr = saved_state->ctr;
state->mq = saved_state->mq; /* This is BOGUS ! (601) ONLY */
state->pad = saved_state->pad;
}
kdp_error_t
kdp_machine_read_regs(
unsigned int cpu,
unsigned int flavor,
char *data,
int *size
)
{
switch (flavor) {
case PPC_THREAD_STATE:
// dprintf(("kdp_machine_read_regs: THREAD_STATE\n"));
dprintf(("kdp_machine_read_regs\n"));
kdp_getintegerstate((struct ppc_thread_state *)data);
*size = sizeof (struct ppc_thread_state);
return KDPERR_NO_ERROR;
case PPC_FLOAT_STATE:
dprintf(("kdp_machine_read_regs: THREAD_FPSTATE\n"));
*(struct ppc_float_state *)data = (struct ppc_float_state) { {0.0}, 0, 0 };
*size = sizeof (struct ppc_float_state);
return KDPERR_NO_ERROR;
default:
dprintf(("kdp_machine_read_regs: bad flavor %d\n"));
return KDPERR_BADFLAVOR;
}
}
static void
kdp_setintegerstate(
struct ppc_thread_state *state
)
{
struct ppc_thread_state *saved_state;
saved_state = kdp.saved_state;
saved_state->srr0 = state->srr0 ;
saved_state->srr1 = state->srr1 ;
saved_state->r0 = state->r0 ;
saved_state->r1 = state->r1 ;
saved_state->r2 = state->r2 ;
saved_state->r3 = state->r3 ;
saved_state->r4 = state->r4 ;
saved_state->r5 = state->r5 ;
saved_state->r6 = state->r6 ;
saved_state->r7 = state->r7 ;
saved_state->r8 = state->r8 ;
saved_state->r9 = state->r9 ;
saved_state->r10 = state->r10 ;
saved_state->r11 = state->r11 ;
saved_state->r12 = state->r12 ;
saved_state->r13 = state->r13 ;
saved_state->r14 = state->r14 ;
saved_state->r15 = state->r15 ;
saved_state->r16 = state->r16 ;
saved_state->r17 = state->r17 ;
saved_state->r18 = state->r18 ;
saved_state->r19 = state->r19 ;
saved_state->r20 = state->r20 ;
saved_state->r21 = state->r21 ;
saved_state->r22 = state->r22 ;
saved_state->r23 = state->r23 ;
saved_state->r24 = state->r24 ;
saved_state->r25 = state->r25 ;
saved_state->r26 = state->r26 ;
saved_state->r27 = state->r27 ;
saved_state->r28 = state->r28 ;
saved_state->r29 = state->r29 ;
saved_state->r30 = state->r30 ;
saved_state->r31 = state->r31 ;
saved_state->cr = state->cr ;
saved_state->xer = state->xer ;
saved_state->lr = state->lr ;
saved_state->ctr = state->ctr ;
saved_state->mq = state->mq ; /* BOGUS! (601)ONLY */
saved_state->pad = state->pad ;
}
kdp_error_t
kdp_machine_write_regs(
unsigned int cpu,
unsigned int flavor,
char *data,
int *size
)
{
switch (flavor) {
case PPC_THREAD_STATE:
// dprintf(("kdp_machine_write_regs: THREAD_STATE\n"));
dprintf(("kdp_machine_write_regs\n"));
kdp_setintegerstate((struct ppc_thread_state *)data);
return KDPERR_NO_ERROR;
case PPC_FLOAT_STATE:
dprintf(("kdp_machine_write_regs: THREAD_FPSTATE\n"));
return KDPERR_NO_ERROR;
default:
dprintf(("kdp_machine_write_regs: bad flavor %d\n"));
return KDPERR_BADFLAVOR;
}
}
void
kdp_machine_hostinfo(
kdp_hostinfo_t *hostinfo
)
{
machine_slot_t m;
int i;
hostinfo->cpus_mask = 0;
for (i = 0; i < machine_info.max_cpus; i++) {
m = &machine_slot[i];
if (!m->is_cpu)
continue;
hostinfo->cpus_mask |= (1 << i);
if (hostinfo->cpu_type == 0) {
hostinfo->cpu_type = m->cpu_type;
hostinfo->cpu_subtype = m->cpu_subtype;
}
}
}
void
kdp_panic(
const char *msg
)
{
dprintf(("kdp_panic: exception, code & subcode not passed to safe_prf.\n"));
safe_prf("kdp panic: %s\n", msg);
while(1) {}
}
void
kdp_reboot(void)
{
boot(RB_BOOT, RB_AUTOBOOT | RB_NOSYNC, "");
}
int
kdp_intr_disbl(void)
{
return splhigh();
}
void
kdp_intr_enbl(int s)
{
splx(s);
}
void
kdp_us_spin(int usec)
{
us_spin(usec);
}
void print_saved_state(void *state)
{
struct ppc_thread_state *saved_state;
saved_state = state;
safe_prf("pc = 0x%x\n", saved_state->srr0);
safe_prf("msr = 0x%x\n", saved_state->srr1);
safe_prf("rp = 0x%x\n", saved_state->lr);
safe_prf("sp = 0x%x\n", saved_state->r1);
}
void
kdp_flush_cache(void)
{
__asm__ volatile ("sync");
__asm__ volatile ("isync");
}
#if 1
void
kdp_init_integerstate(struct ppc_thread_state *instate)
{
__asm__ volatile (".set SS_R0,8");
__asm__ volatile (".set SS_R1,12");
__asm__ volatile (".set SS_R2,16");
__asm__ volatile (".set SS_R3,20");
__asm__ volatile (".set SS_R4,24");
__asm__ volatile (".set SS_R5,28");
__asm__ volatile (".set SS_R6,32");
__asm__ volatile (".set SS_R7,36");
__asm__ volatile (".set SS_R8,40");
__asm__ volatile (".set SS_R9,44");
__asm__ volatile (".set SS_R10,48");
__asm__ volatile (".set SS_R11,52");
__asm__ volatile (".set SS_R12,56");
__asm__ volatile (".set SS_R13,60");
__asm__ volatile (".set SS_R14,64");
__asm__ volatile (".set SS_R15,68");
__asm__ volatile (".set SS_R16,72");
__asm__ volatile (".set SS_R17,76");
__asm__ volatile (".set SS_R18,80");
__asm__ volatile (".set SS_R19,84");
__asm__ volatile (".set SS_R20,88");
__asm__ volatile (".set SS_R21,92");
__asm__ volatile (".set SS_R22,96");
__asm__ volatile (".set SS_R23,100");
__asm__ volatile (".set SS_R24,104");
__asm__ volatile (".set SS_R25,108");
__asm__ volatile (".set SS_R26,112");
__asm__ volatile (".set SS_R27,116");
__asm__ volatile (".set SS_R28,120");
__asm__ volatile (".set SS_R29,124");
__asm__ volatile (".set SS_R30,128");
__asm__ volatile (".set SS_R31,132");
__asm__ volatile (".set SS_CR,136");
__asm__ volatile (".set SS_XER,140");
__asm__ volatile (".set SS_LR,144");
__asm__ volatile (".set SS_CTR,148");
__asm__ volatile (".set SS_SRR0,0");
__asm__ volatile (".set SS_SRR1,4");
__asm__ volatile("stw r0, SS_R0(r3)");
__asm__ volatile("stw r5, SS_R5(r3)");
__asm__ volatile("addis r5, 0, hi16(L_kdbmarker)");
__asm__ volatile("ori r5, r5, lo16(L_kdbmarker)");
__asm__ volatile("lwz r0, 0(r1)");
__asm__ volatile("stw r0, SS_R1(r3)");
__asm__ volatile(".noflag_reg 2");
__asm__ volatile("stw r2, SS_R2(r3)");
__asm__ volatile(".flag_reg 2");
__asm__ volatile("stw r3, SS_R3(r3)");
__asm__ volatile("stw r4, SS_R4(r3)");
__asm__ volatile("stw r6, SS_R6(r3)");
__asm__ volatile("stw r7, SS_R7(r3)");
__asm__ volatile("stw r8, SS_R8(r3)");
__asm__ volatile("stw r9, SS_R9(r3)");
__asm__ volatile("stw r10, SS_R10(r3)");
__asm__ volatile("stw r11, SS_R11(r3)");
__asm__ volatile("stw r12, SS_R12(r3)");
__asm__ volatile(".noflag_reg 13");
__asm__ volatile("stw r13, SS_R13(r3)");
__asm__ volatile(".flag_reg 13");
__asm__ volatile("stw r14, SS_R14(r3)");
__asm__ volatile("stw r15, SS_R15(r3)");
__asm__ volatile("stw r16, SS_R16(r3)");
__asm__ volatile("stw r17, SS_R17(r3)");
__asm__ volatile("stw r18, SS_R18(r3)");
__asm__ volatile("stw r19, SS_R19(r3)");
__asm__ volatile("stw r20, SS_R20(r3)");
__asm__ volatile("stw r21, SS_R21(r3)");
__asm__ volatile("stw r22, SS_R22(r3)");
__asm__ volatile("stw r23, SS_R23(r3)");
__asm__ volatile("stw r24, SS_R24(r3)");
__asm__ volatile("stw r25, SS_R25(r3)");
__asm__ volatile("stw r26, SS_R26(r3)");
__asm__ volatile("stw r27, SS_R27(r3)");
__asm__ volatile("stw r28, SS_R28(r3)");
__asm__ volatile("stw r29, SS_R29(r3)");
__asm__ volatile("stw r30, SS_R30(r3)");
__asm__ volatile("stw r31, SS_R31(r3)");
__asm__ volatile("mfcr r0");
__asm__ volatile("stw r0, SS_CR(r3)");
__asm__ volatile("stw r5, SS_SRR0(r3)");
// __asm__ volatile("mfsrr0 r0");
// __asm__ volatile("stw r0, SS_SRR0(r3)");
__asm__ volatile("mfsrr1 r0");
__asm__ volatile("stw r0, SS_SRR1(r3)");
__asm__ volatile("mfxer r0");
__asm__ volatile("stw r0, SS_XER(r3)");
__asm__ volatile("mflr r0");
__asm__ volatile("stw r0, SS_LR(r3)");
__asm__ volatile("mfctr r0");
__asm__ volatile("stw r0, SS_CTR(r3)");
}
void
call_kdp()
{
static struct ppc_thread_state __kdp_space;
kdp_init_integerstate(&__kdp_space);
kdp_raise_exception(EXC_SOFTWARE, 0, 0, &__kdp_space);
__asm__ volatile("L_kdbmarker:");
__asm__ volatile("nop");
}
#endif
/*
* table to convert system specific code to generic codes for kdb
*/
int kdp_trap_codes[] = {
EXC_BAD_ACCESS, /* 0x0000 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x0100 System reset */
EXC_BAD_ACCESS, /* 0x0200 Machine check */
EXC_BAD_ACCESS, /* 0x0300 Data access */
EXC_BAD_ACCESS, /* 0x0400 Instruction access */
EXC_BAD_ACCESS, /* 0x0500 External interrupt */
EXC_BAD_ACCESS, /* 0x0600 Alignment */
EXC_BREAKPOINT, /* 0x0700 Program - fp exc, ill/priv instr, trap */
EXC_ARITHMETIC, /* 0x0800 Floating point disabled */
EXC_SOFTWARE, /* 0x0900 Decrementer */
EXC_BAD_ACCESS, /* 0x0A00 I/O controller interface */
EXC_BAD_ACCESS, /* 0x0B00 INVALID EXCEPTION */
EXC_SOFTWARE, /* 0x0C00 System call exception */
EXC_BREAKPOINT, /* 0x0D00 Trace */
EXC_SOFTWARE, /* 0x0E00 FP assist */
EXC_SOFTWARE, /* 0x0F00 Performance monitoring */
EXC_BAD_ACCESS, /* 0x1000 Instruction PTE miss */
EXC_BAD_ACCESS, /* 0x1100 Data load PTE miss */
EXC_BAD_ACCESS, /* 0x1200 Data store PTE miss */
EXC_BREAKPOINT, /* 0x1300 Instruction bkpt */
EXC_SOFTWARE, /* 0x1400 System management */
EXC_BAD_ACCESS, /* 0x1500 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1600 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1700 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1800 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1900 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1A00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1B00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1C00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1D00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1E00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x1F00 INVALID EXCEPTION */
EXC_BREAKPOINT, /* 0x2000 Run Mode/Trace */
EXC_BAD_ACCESS, /* 0x2100 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2200 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2300 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2400 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2500 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2600 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2700 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2800 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2900 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2A00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2B00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2C00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2D00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2E00 INVALID EXCEPTION */
EXC_BAD_ACCESS, /* 0x2F00 INVALID EXCEPTION */
EXC_SOFTWARE /* 0x3000 AST trap (software) */
};
int kdp_segments[16] = {
-1, -1, 0, 3,
4, 5, 0xB, -1,
-1, -1, -1, -1,
-1, -1, -1, -1
};
int kdp_space;
int
kdp_map_segment(unsigned int segment)
{
segment &= 0xF;
return kdp_segments[segment];
}