Add PA-RISC 2.0 PIM support.
Fix the HPMC exception handler so that, if we're running on a PA-RISC 2.0 machine, we use the 64-bit PIM data structures. There was also a bug in the HPMC exception handler that stopped output being written to the console after we'd taken the exception. We need to make a PDC_IO pdc call to reset I/O.
This commit is contained in:
parent
87e79748d0
commit
9c6bc36bdd
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.63 2009/05/13 14:33:42 skrll Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.64 2009/05/16 16:06:06 mjf Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -58,7 +58,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.63 2009/05/13 14:33:42 skrll Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.64 2009/05/16 16:06:06 mjf Exp $");
|
||||
|
||||
#include "opt_cputype.h"
|
||||
#include "opt_ddb.h"
|
||||
|
@ -1455,12 +1455,20 @@ cpu_dumpsize(void)
|
|||
* an LPMC, or a TOC. The check type is passed in as a trap
|
||||
* type, one of T_HPMC, T_LPMC, or T_INTERRUPT (for TOC).
|
||||
*/
|
||||
static char pim_data_buffer[4096]; /* XXX assumed to be big enough */
|
||||
static char pim_data_buffer[896] __attribute__((__aligned__(8)));
|
||||
static char in_check = 0;
|
||||
void
|
||||
hppa_machine_check(int check_type)
|
||||
|
||||
#define PIM_WORD(name, word, bits) \
|
||||
do { \
|
||||
snprintb(bitmask_buffer, sizeof(bitmask_buffer),\
|
||||
bits, word); \
|
||||
printf("%s %s", name, bitmask_buffer); \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
|
||||
static inline void
|
||||
hppa_pim_dump(int check_type)
|
||||
{
|
||||
int pdc_pim_type;
|
||||
struct hp700_pim_hpmc *hpmc;
|
||||
struct hp700_pim_lpmc *lpmc;
|
||||
struct hp700_pim_toc *toc;
|
||||
|
@ -1470,37 +1478,20 @@ hppa_machine_check(int check_type)
|
|||
int reg_i, reg_j, reg_k;
|
||||
char bitmask_buffer[64];
|
||||
const char *name;
|
||||
int error;
|
||||
#define PIM_WORD(name, word, bits) \
|
||||
do { \
|
||||
snprintb(bitmask_buffer, sizeof(bitmask_buffer),\
|
||||
bits, word); \
|
||||
printf("%s %s", name, bitmask_buffer); \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
/* Do an fcacheall(). */
|
||||
fcacheall();
|
||||
|
||||
/* Dispatch on the check type. */
|
||||
regs = NULL;
|
||||
checks = NULL;
|
||||
switch (check_type) {
|
||||
case T_HPMC:
|
||||
name = "HPMC";
|
||||
pdc_pim_type = PDC_PIM_HPMC;
|
||||
hpmc = (struct hp700_pim_hpmc *) pim_data_buffer;
|
||||
regs = &hpmc->pim_hpmc_regs;
|
||||
checks = &hpmc->pim_hpmc_checks;
|
||||
break;
|
||||
case T_LPMC:
|
||||
name = "LPMC";
|
||||
pdc_pim_type = PDC_PIM_LPMC;
|
||||
lpmc = (struct hp700_pim_lpmc *) pim_data_buffer;
|
||||
checks = &lpmc->pim_lpmc_checks;
|
||||
break;
|
||||
case T_INTERRUPT:
|
||||
name = "TOC";
|
||||
pdc_pim_type = PDC_PIM_TOC;
|
||||
toc = (struct hp700_pim_toc *) pim_data_buffer;
|
||||
regs = &toc->pim_toc_regs;
|
||||
break;
|
||||
|
@ -1508,11 +1499,6 @@ do { \
|
|||
panic("unknown machine check type");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
printf("\nmachine check: %s", name);
|
||||
error = pdc_call((iodcio_t)pdc, 0, PDC_PIM, pdc_pim_type,
|
||||
&pdc_pim, pim_data_buffer, sizeof(pim_data_buffer));
|
||||
if (error < 0)
|
||||
printf(" - WARNING: could not transfer PIM info (%d)", error);
|
||||
|
||||
/* If we have register arrays, display them. */
|
||||
if (regs != NULL) {
|
||||
|
@ -1538,7 +1524,8 @@ do { \
|
|||
}
|
||||
|
||||
/* Print out some interesting registers. */
|
||||
printf("\n\n\tIIA 0x%x:0x%08x 0x%x:0x%08x",
|
||||
printf("\n\n\tIIA head 0x%x:0x%08x\n"
|
||||
"\tIIA tail 0x%x:0x%08x",
|
||||
regs->pim_regs_cr17, regs->pim_regs_cr18,
|
||||
regs->pim_regs_iisq_tail, regs->pim_regs_iioq_tail);
|
||||
PIM_WORD("\n\tIPSW", regs->pim_regs_cr22, PSW_BITS);
|
||||
|
@ -1569,6 +1556,164 @@ do { \
|
|||
printf("\n\tPath Info 0x%08x",
|
||||
checks->pim_check_path_info);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
hppa_pim64_dump(int check_type)
|
||||
{
|
||||
struct hp700_pim64_hpmc *hpmc;
|
||||
struct hp700_pim64_lpmc *lpmc;
|
||||
struct hp700_pim64_toc *toc;
|
||||
struct hp700_pim64_regs *regs;
|
||||
struct hp700_pim64_checks *checks;
|
||||
int reg_i, reg_j, reg_k;
|
||||
uint64_t *regarray;
|
||||
char bitmask_buffer[64];
|
||||
const char *name;
|
||||
|
||||
regs = NULL;
|
||||
checks = NULL;
|
||||
switch (check_type) {
|
||||
case T_HPMC:
|
||||
hpmc = (struct hp700_pim64_hpmc *) pim_data_buffer;
|
||||
regs = &hpmc->pim_hpmc_regs;
|
||||
checks = &hpmc->pim_hpmc_checks;
|
||||
break;
|
||||
case T_LPMC:
|
||||
lpmc = (struct hp700_pim64_lpmc *) pim_data_buffer;
|
||||
checks = &lpmc->pim_lpmc_checks;
|
||||
break;
|
||||
case T_INTERRUPT:
|
||||
toc = (struct hp700_pim64_toc *) pim_data_buffer;
|
||||
regs = &toc->pim_toc_regs;
|
||||
break;
|
||||
default:
|
||||
panic("unknown machine check type");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* If we have register arrays, display them. */
|
||||
if (regs != NULL) {
|
||||
for (reg_i = 0; reg_i < 3; reg_i++) {
|
||||
if (reg_i == 0) {
|
||||
name = "General";
|
||||
regarray = ®s->pim_regs_r0;
|
||||
reg_j = 32;
|
||||
} else if (reg_i == 1) {
|
||||
name = "Control";
|
||||
regarray = ®s->pim_regs_cr0;
|
||||
reg_j = 32;
|
||||
} else {
|
||||
name = "Space";
|
||||
regarray = ®s->pim_regs_sr0;
|
||||
reg_j = 8;
|
||||
}
|
||||
printf("\n\n\t%s Registers:", name);
|
||||
for (reg_k = 0; reg_k < reg_j; reg_k++) {
|
||||
printf("%s",
|
||||
(reg_k & 1) ? " " : "\n\t");
|
||||
if (!(reg_k & 1))
|
||||
printf("%2d: ", reg_k);
|
||||
printf("0x%016lx",
|
||||
(unsigned long)regarray[reg_k]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Print out some interesting registers. */
|
||||
printf("\n\n\tIIA head 0x%lx:0x%016lx\n"
|
||||
"\tIIA tail 0x%lx:0x%016lx",
|
||||
(unsigned long)regs->pim_regs_cr17,
|
||||
(unsigned long)regs->pim_regs_cr18,
|
||||
(unsigned long)regs->pim_regs_iisq_tail,
|
||||
(unsigned long)regs->pim_regs_iioq_tail);
|
||||
PIM_WORD("\n\tIPSW", regs->pim_regs_cr22, PSW_BITS);
|
||||
printf("\n\tSP 0x%lx:0x%016lx\n\tFP 0x%lx:0x%016lx",
|
||||
(unsigned long)regs->pim_regs_sr0,
|
||||
(unsigned long)regs->pim_regs_r30,
|
||||
(unsigned long)regs->pim_regs_sr0,
|
||||
(unsigned long)regs->pim_regs_r3);
|
||||
}
|
||||
|
||||
/* If we have check words, display them. */
|
||||
if (checks != NULL) {
|
||||
PIM_WORD("\n\n\tCheck Type", checks->pim_check_type,
|
||||
PIM_CHECK_BITS);
|
||||
PIM_WORD("\n\tCPU State", checks->pim_check_cpu_state,
|
||||
PIM_CPU_BITS PIM_CPU_HPMC_BITS);
|
||||
PIM_WORD("\n\tCache Check", checks->pim_check_cache,
|
||||
PIM_CACHE_BITS);
|
||||
PIM_WORD("\n\tTLB Check", checks->pim_check_tlb,
|
||||
PIM_TLB_BITS);
|
||||
PIM_WORD("\n\tBus Check", checks->pim_check_bus,
|
||||
PIM_BUS_BITS);
|
||||
PIM_WORD("\n\tAssist Check", checks->pim_check_assist,
|
||||
PIM_ASSIST_BITS);
|
||||
printf("\tAssist State %u", checks->pim_check_assist_state);
|
||||
printf("\n\tSystem Responder 0x%016lx",
|
||||
(unsigned long)checks->pim_check_responder);
|
||||
printf("\n\tSystem Requestor 0x%016lx",
|
||||
(unsigned long)checks->pim_check_requestor);
|
||||
printf("\n\tPath Info 0x%08x",
|
||||
checks->pim_check_path_info);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hppa_machine_check(int check_type)
|
||||
{
|
||||
int pdc_pim_type;
|
||||
const char *name;
|
||||
int error;
|
||||
|
||||
/* Do an fcacheall(). */
|
||||
fcacheall();
|
||||
|
||||
/* Dispatch on the check type. */
|
||||
switch (check_type) {
|
||||
case T_HPMC:
|
||||
name = "HPMC";
|
||||
pdc_pim_type = PDC_PIM_HPMC;
|
||||
break;
|
||||
case T_LPMC:
|
||||
name = "LPMC";
|
||||
pdc_pim_type = PDC_PIM_LPMC;
|
||||
break;
|
||||
case T_INTERRUPT:
|
||||
name = "TOC";
|
||||
pdc_pim_type = PDC_PIM_TOC;
|
||||
break;
|
||||
default:
|
||||
panic("unknown machine check type");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
error = pdc_call((iodcio_t)pdc, 0, PDC_PIM, pdc_pim_type,
|
||||
&pdc_pim, pim_data_buffer, sizeof(pim_data_buffer));
|
||||
if (error < 0)
|
||||
printf(" - WARNING: could not transfer PIM info (%d)", error);
|
||||
|
||||
CTASSERT(pdc_pim.count <= sizeof(pim_data_buffer));
|
||||
|
||||
/*
|
||||
* Reset IO and log errors.
|
||||
*
|
||||
* This seems to be needed in order to output to the console
|
||||
* if we take a HPMC interrupt. This PDC procedure may not be
|
||||
* implemented by some machines.
|
||||
*/
|
||||
error = pdc_call((iodcio_t)pdc, 0, PDC_IO, 0, 0, 0, 0);
|
||||
if (error != PDC_ERR_OK && error != PDC_ERR_NOPROC)
|
||||
/* This seems futile if we can't print to the console. */
|
||||
panic("PDC_IO failed");
|
||||
|
||||
printf("\nmachine check: %s", name);
|
||||
|
||||
if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B)
|
||||
hppa_pim64_dump(check_type);
|
||||
else
|
||||
hppa_pim_dump(check_type);
|
||||
|
||||
printf("\n");
|
||||
|
||||
/* If this is our first check, panic. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pim.h,v 1.2 2008/04/28 20:23:19 martin Exp $ */
|
||||
/* $NetBSD: pim.h,v 1.3 2009/05/16 16:06:06 mjf Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -36,6 +36,9 @@
|
|||
*
|
||||
* "PA/RISC 1.1 I/O Firmware Architecture Reference Specification",
|
||||
* Version 1.0, August 22, 2001.
|
||||
*
|
||||
* "PA/RISC 2.0 I/O Firmware Architecture Reference Specification",
|
||||
* Version 1.0, August 22, 2001.
|
||||
*/
|
||||
|
||||
/* The PIM data for HPMC and TOC contains these register arrays. */
|
||||
|
@ -262,3 +265,138 @@ struct hp700_pim_toc {
|
|||
u_int pim_toc_hversion_dep;
|
||||
u_int pim_toc_cpu_state;
|
||||
};
|
||||
|
||||
struct hp700_pim64_regs {
|
||||
|
||||
/* The general registers. */
|
||||
u_int64_t pim_regs_r0;
|
||||
u_int64_t pim_regs_r1;
|
||||
u_int64_t pim_regs_r2;
|
||||
u_int64_t pim_regs_r3;
|
||||
u_int64_t pim_regs_r4;
|
||||
u_int64_t pim_regs_r5;
|
||||
u_int64_t pim_regs_r6;
|
||||
u_int64_t pim_regs_r7;
|
||||
u_int64_t pim_regs_r8;
|
||||
u_int64_t pim_regs_r9;
|
||||
u_int64_t pim_regs_r10;
|
||||
u_int64_t pim_regs_r11;
|
||||
u_int64_t pim_regs_r12;
|
||||
u_int64_t pim_regs_r13;
|
||||
u_int64_t pim_regs_r14;
|
||||
u_int64_t pim_regs_r15;
|
||||
u_int64_t pim_regs_r16;
|
||||
u_int64_t pim_regs_r17;
|
||||
u_int64_t pim_regs_r18;
|
||||
u_int64_t pim_regs_r19;
|
||||
u_int64_t pim_regs_r20;
|
||||
u_int64_t pim_regs_r21;
|
||||
u_int64_t pim_regs_r22;
|
||||
u_int64_t pim_regs_r23;
|
||||
u_int64_t pim_regs_r24;
|
||||
u_int64_t pim_regs_r25;
|
||||
u_int64_t pim_regs_r26;
|
||||
u_int64_t pim_regs_r27;
|
||||
u_int64_t pim_regs_r28;
|
||||
u_int64_t pim_regs_r29;
|
||||
u_int64_t pim_regs_r30;
|
||||
u_int64_t pim_regs_r31;
|
||||
|
||||
/* The control registers. */
|
||||
u_int64_t pim_regs_cr0;
|
||||
u_int64_t pim_regs_cr1;
|
||||
u_int64_t pim_regs_cr2;
|
||||
u_int64_t pim_regs_cr3;
|
||||
u_int64_t pim_regs_cr4;
|
||||
u_int64_t pim_regs_cr5;
|
||||
u_int64_t pim_regs_cr6;
|
||||
u_int64_t pim_regs_cr7;
|
||||
u_int64_t pim_regs_cr8;
|
||||
u_int64_t pim_regs_cr9;
|
||||
u_int64_t pim_regs_cr10;
|
||||
u_int64_t pim_regs_cr11;
|
||||
u_int64_t pim_regs_cr12;
|
||||
u_int64_t pim_regs_cr13;
|
||||
u_int64_t pim_regs_cr14;
|
||||
u_int64_t pim_regs_cr15;
|
||||
u_int64_t pim_regs_cr16;
|
||||
u_int64_t pim_regs_cr17;
|
||||
u_int64_t pim_regs_cr18;
|
||||
u_int64_t pim_regs_cr19;
|
||||
u_int64_t pim_regs_cr20;
|
||||
u_int64_t pim_regs_cr21;
|
||||
u_int64_t pim_regs_cr22;
|
||||
u_int64_t pim_regs_cr23;
|
||||
u_int64_t pim_regs_cr24;
|
||||
u_int64_t pim_regs_cr25;
|
||||
u_int64_t pim_regs_cr26;
|
||||
u_int64_t pim_regs_cr27;
|
||||
u_int64_t pim_regs_cr28;
|
||||
u_int64_t pim_regs_cr29;
|
||||
u_int64_t pim_regs_cr30;
|
||||
u_int64_t pim_regs_cr31;
|
||||
|
||||
/* The space registers. */
|
||||
u_int64_t pim_regs_sr0;
|
||||
u_int64_t pim_regs_sr1;
|
||||
u_int64_t pim_regs_sr2;
|
||||
u_int64_t pim_regs_sr3;
|
||||
u_int64_t pim_regs_sr4;
|
||||
u_int64_t pim_regs_sr5;
|
||||
u_int64_t pim_regs_sr6;
|
||||
u_int64_t pim_regs_sr7;
|
||||
|
||||
/* The back entries of the instruction address queues. */
|
||||
u_int64_t pim_regs_iisq_tail;
|
||||
u_int64_t pim_regs_iioq_tail;
|
||||
};
|
||||
|
||||
struct hp700_pim64_checks {
|
||||
/* The Check Type. */
|
||||
u_int pim_check_type;
|
||||
|
||||
/*
|
||||
* The CPU State. In addition to the common PIM_CPU_
|
||||
* bits defined below, some fields are HPMC-specific.
|
||||
*/
|
||||
u_int pim_check_cpu_state;
|
||||
|
||||
/* The Cache Check word. */
|
||||
u_int pim_check_cache;
|
||||
|
||||
/* The TLB Check word. */
|
||||
u_int pim_check_tlb;
|
||||
|
||||
/* The Bus Check word. */
|
||||
u_int pim_check_bus;
|
||||
|
||||
/* The Assist Check word. */
|
||||
u_int pim_check_assist;
|
||||
|
||||
/* Additional information about the check. */
|
||||
u_int pim_check_assist_state;
|
||||
u_int pim_check_path_info;
|
||||
u_int64_t pim_check_responder;
|
||||
u_int64_t pim_check_requestor;
|
||||
};
|
||||
|
||||
/* The PARISC 2.0 HPMC PIM data. */
|
||||
struct hp700_pim64_hpmc {
|
||||
struct hp700_pim64_regs pim_hpmc_regs;
|
||||
struct hp700_pim64_checks pim_hpmc_checks;
|
||||
struct hp700_pim_fpregs pim_hpmc_fpregs;
|
||||
};
|
||||
|
||||
/* The PARISC 2.0 LPMC PIM data. */
|
||||
struct hp700_pim64_lpmc {
|
||||
u_int64_t pim_lmpc_hversion_dep[74];
|
||||
struct hp700_pim64_checks pim_lpmc_checks;
|
||||
struct hp700_pim_fpregs pim_lpmc_fpregs;
|
||||
};
|
||||
|
||||
/* The PARISC 2.0 TOC PIM data. */
|
||||
struct hp700_pim64_toc {
|
||||
struct hp700_pim64_regs pim_toc_regs;
|
||||
u_int pim_toc_hversion_dep;
|
||||
u_int pim_toc_cpu_state;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue