Index: sys/arch/hp700/hp700/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/hp700/hp700/machdep.c,v retrieving revision 1.62 diff -u -r1.62 machdep.c --- sys/arch/hp700/hp700/machdep.c 9 May 2009 11:39:30 -0000 1.62 +++ sys/arch/hp700/hp700/machdep.c 14 May 2009 06:24:23 -0000 @@ -357,7 +357,7 @@ #endif #ifdef HP8200_CPU { "PA8200", "Vulcan", "PCXU+", - hpcxup,HPPA_CPU_PCXUP, HPPA_FTRS_W32B, "2.0", + hpcxup, HPPA_CPU_PCXUP, HPPA_FTRS_W32B, "2.0", desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, ibtlb_u, NULL, pbtlb_u }, #endif @@ -1414,22 +1414,10 @@ * 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 */ +/* XXX assumed to be big enough */ +static char pim_data_buffer[4096] __attribute__((__aligned__(8))); static char in_check = 0; -void -hppa_machine_check(int check_type) -{ - int pdc_pim_type; - struct hp700_pim_hpmc *hpmc; - struct hp700_pim_lpmc *lpmc; - struct hp700_pim_toc *toc; - struct hp700_pim_regs *regs; - struct hp700_pim_checks *checks; - u_int *regarray; - 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),\ @@ -1437,41 +1425,39 @@ printf("%s %s", name, bitmask_buffer); \ } while (/* CONSTCOND */ 0) - /* Do an fcacheall(). */ - fcacheall(); - /* Dispatch on the check type. */ +static inline void +hppa_machine_check_1_1(int check_type, const char *name) +{ + struct hp700_1_1_pim_hpmc *hpmc; + struct hp700_1_1_pim_lpmc *lpmc; + struct hp700_1_1_pim_toc *toc; + struct hp700_1_1_pim_regs *regs; + struct hp700_1_1_pim_checks *checks; + int reg_i, reg_j, reg_k; + u_int *regarray; + char bitmask_buffer[64]; + 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; + hpmc = (struct hp700_1_1_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; + lpmc = (struct hp700_1_1_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; + toc = (struct hp700_1_1_pim_toc *) pim_data_buffer; regs = &toc->pim_toc_regs; break; default: - panic("unknown machine check type"); + 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) { @@ -1528,6 +1514,158 @@ printf("\n\tPath Info 0x%08x", checks->pim_check_path_info); } +} + +static inline void +hppa_machine_check_2_0(int check_type, const char *name) +{ + struct hp700_2_0_pim_hpmc *hpmc; + struct hp700_2_0_pim_lpmc *lpmc; + struct hp700_2_0_pim_toc *toc; + struct hp700_2_0_pim_regs *regs; + struct hp700_2_0_pim_checks *checks; + int reg_i, reg_j, reg_k; + uint64_t *regarray; + char bitmask_buffer[64]; + + printf("Sizeof hpmc %lu, sizeof pim_regs %lu, sizeof pim_checks %lu\n", + sizeof(*hpmc), sizeof(*regs), sizeof(*checks)); + + regs = NULL; + checks = NULL; + switch (check_type) { + case T_HPMC: + hpmc = (struct hp700_2_0_pim_hpmc *) pim_data_buffer; + regs = &hpmc->pim_hpmc_regs; + checks = &hpmc->pim_hpmc_checks; + break; + case T_LPMC: + lpmc = (struct hp700_2_0_pim_lpmc *) pim_data_buffer; + checks = &lpmc->pim_lpmc_checks; + break; + case T_INTERRUPT: + toc = (struct hp700_2_0_pim_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("%s0x%016lx", + (reg_k & 1) ? " " : "\n\t", + (unsigned long)regarray[reg_k]); + } + + /* Print out some interesting registers. */ + printf("\n\n\tIIA 0x%lx:0x%016lx 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); + + /* + * 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_machine_check_2_0(check_type, name); + else + hppa_machine_check_1_1(check_type, name); + printf("\n"); /* If this is our first check, panic. */ Index: sys/arch/hp700/hp700/pim.h =================================================================== RCS file: /cvsroot/src/sys/arch/hp700/hp700/pim.h,v retrieving revision 1.2 diff -u -r1.2 pim.h --- sys/arch/hp700/hp700/pim.h 28 Apr 2008 20:23:19 -0000 1.2 +++ sys/arch/hp700/hp700/pim.h 14 May 2009 06:24:28 -0000 @@ -36,10 +36,13 @@ * * "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. */ -struct hp700_pim_regs { +struct hp700_1_1_pim_regs { /* The general registers. */ u_int pim_regs_r0; @@ -125,7 +128,7 @@ }; /* The PIM data for HPMC and LPMC contains this check information. */ -struct hp700_pim_checks { +struct hp700_1_1_pim_checks { /* The Check Type. */ u_int pim_check_type; @@ -242,23 +245,158 @@ u_int64_t pim_fpregs_fp31; }; -/* The HPMC PIM data. */ -struct hp700_pim_hpmc { - struct hp700_pim_regs pim_hpmc_regs; - struct hp700_pim_checks pim_hpmc_checks; +/* The PARISC 1.1 HPMC PIM data. */ +struct hp700_1_1_pim_hpmc { + struct hp700_1_1_pim_regs pim_hpmc_regs; + struct hp700_1_1_pim_checks pim_hpmc_checks; struct hp700_pim_fpregs pim_hpmc_fpregs; }; -/* The LPMC PIM data. */ -struct hp700_pim_lpmc { +/* The PARISC 1.1 LPMC PIM data. */ +struct hp700_1_1_pim_lpmc { u_int pim_lpmc_hversion_dep[74]; - struct hp700_pim_checks pim_lpmc_checks; + struct hp700_1_1_pim_checks pim_lpmc_checks; struct hp700_pim_fpregs pim_lpmc_fpregs; }; -/* The TOC PIM data. */ -struct hp700_pim_toc { - struct hp700_pim_regs pim_toc_regs; +/* The PARISC 1.1 TOC PIM data. */ +struct hp700_1_1_pim_toc { + struct hp700_1_1_pim_regs pim_toc_regs; + u_int pim_toc_hversion_dep; + u_int pim_toc_cpu_state; +}; + +struct hp700_2_0_pim_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_2_0_pim_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_2_0_pim_hpmc { + struct hp700_2_0_pim_regs pim_hpmc_regs; + struct hp700_2_0_pim_checks pim_hpmc_checks; + struct hp700_pim_fpregs pim_hpmc_fpregs; +}; + +/* The PARISC 2.0 LPMC PIM data. */ +struct hp700_2_0_pim_lpmc { + u_int64_t pim_lmpc_hversion_dep[74]; + struct hp700_2_0_pim_checks pim_lpmc_checks; + struct hp700_pim_fpregs pim_lpmc_fpregs; +}; + +/* The PARISC 2.0 TOC PIM data. */ +struct hp700_2_0_pim_toc { + struct hp700_2_0_pim_regs pim_toc_regs; u_int pim_toc_hversion_dep; u_int pim_toc_cpu_state; };