Linux boots again on all.

Added fault handler, PDC32 fixes
diff --git a/src/parisc/head.S b/src/parisc/head.S
index e5c3408..b6289b5 100644
--- a/src/parisc/head.S
+++ b/src/parisc/head.S
@@ -249,6 +249,10 @@
 	rsm	PSW_I, %r0	/* disable local irqs */
 	mtctl	%r0, CR_EIEM
 
+	/* Load IVT to detect and report crashes */
+	load32_firmware	BOOTADDR(firmware_default_ivt),%r1
+	mtctl	%r1, CR_IVA
+
 	/* provide PDCE_PROC entry in arg0 (required on 64-bit) */
 	load32	MEM_PDC_ENTRY, %arg0
 
@@ -295,6 +299,10 @@
 	cmpb,<<,n %r3,%r4,$bss_loop
 	STREGM	%r0,WORD_LEN(%r3)
 
+	/* Load IVT to detect and report crashes */
+	load32_firmware	BOOTADDR(firmware_default_ivt),%r1
+	mtctl	%r1, CR_IVA
+
 	load32_firmware	BOOTADDR(start_parisc_firmware),%r3
 	bv	0(%r3)
 	copy	%r0,%r2
@@ -433,6 +441,20 @@
 	.endr
 END(smp_ivt)
 
+	.align 32
+ENTRY(firmware_default_ivt)	/* to detect crashes */
+	.set loop,0
+	.import firmware_fault_handler,code
+	.rept 32
+	.align 32
+	load32_firmware firmware_fault_handler,%arg0
+	loadgp
+	bv	0(%arg0)
+	ldi  loop,%arg0
+	.set loop,loop+1
+	.endr
+END(smp_ivt)
+
 
 /*******************************************************
 	PDC and IODC entry
@@ -475,6 +497,7 @@
 	loadgp
 	load32		MEM_PDC_ENTRY + 1f - pdc_entry_table,%rp
 	load32 parisc_pdc_entry, %r1
+	clear_PSW_W
 	bv              0(%r1)
 	ldo FRAME_SIZE(%sp),%sp
 1:
@@ -553,10 +576,15 @@
 	cmpb,=,n %r1,%r0,5f	/* skip copy results */
 #endif
 
-	cmpib,>=,n 15,%arg2,5f /* skip copy results if target buffer in PAGE0 */
+	cmpb,=,n %r0,%arg2,5f   /* skip copy results if target buffer is NULL */
+	cmpb,<   %ret0,%r0,5f	/* skip copy results if return value was negative (=error) */
+	ldi MEM_PDC_ENTRY,%r1
+	cmpb,>=,n %arg2,%r1,convert_ret64_buffer  /* copy results if target buffer >= MEM_PDC_ENTRY */
+	b,n .
+	.word 0xfffdead0	/* immediately halt the emulator */
 
+convert_ret64_buffer:
 	/* copy 64-bit-wide PDC result to 32-bit wide results */
-	/* TODO?: skip copy results if return value was < 0 */
 	ldi 32,%r1
 	copy %arg2,%arg3
 .L1:	ldd,ma 8(%arg2),%arg1
diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c
index c502d07..f46b9d9 100644
--- a/src/parisc/parisc.c
+++ b/src/parisc/parisc.c
@@ -67,6 +67,9 @@
 
 #define COMPAT_VAL(val)   ((long)(int)(val))    // (is_compat_mode() ? (long)(int)(val) : (val))
 
+/* Do not write back result buffer in compat mode */
+#define NO_COMPAT_RETURN_VALUE(res)     { res = 0; }
+
 u8 BiosChecksum;
 
 char zonefseg_start, zonefseg_end;  // SYMBOLS
@@ -244,6 +247,14 @@
     while (1);
 }
 
+void __VISIBLE __noreturn firmware_fault_handler(unsigned long fault)
+{
+    printf("\n***************************\n"
+        "SeaBIOS: Detected trap #%lu, at 0x%lx:0x%lx, IIR=0x%lx, IOR addr=0x%lx:0x%lx\n", fault,
+        mfctl(17), mfctl(18), mfctl(19), mfctl(20), mfctl(21));
+    while (1) { asm("or %r10,%r10,%r10"); };
+}
+
 #undef BUG_ON
 #define BUG_ON(cond) \
     if (unlikely(cond)) { \
@@ -1120,7 +1131,6 @@
     struct disk_op_s disk_op;
 
     dev = find_hpa_device(hpa);
-printf("HPA = %lx  dev %p\n", hpa, dev);
     if (!dev) {
 
         BUG_ON(1);
@@ -1416,9 +1426,8 @@
         case PDC_CHASSIS_DISP:
             ARG3 = ARG2;
             /* WARNING: Avoid copyig the 64-bit result array to ARG2 */
-            ARG2 = 0;   /* do not write back in compat mode */
+            NO_COMPAT_RETURN_VALUE(ARG2);
             result = (unsigned long *)&ARG4; // do not write to ARG2, use &ARG4 instead
-    printf("\nPDC_CHASSIS: %p ARG3 = %lx\n", result, ARG3);
             // fall through
         case PDC_CHASSIS_DISPWARN:
             ARG4 = (ARG3 >> 17) & 7;
@@ -1631,7 +1640,6 @@
     switch (option) {
         case PDC_HPA_PROCESSOR:
             hpa = mfctl(CPU_HPA_CR_REG); /* get CPU HPA from cr7 */
-printf("HPA = %lx\n", hpa);
             i = index_of_CPU_HPA(hpa);
             BUG_ON(i < 0 || i >= smp_cpus); /* ARGH, someone modified cr7! */
             result[0] = hpa;    /* CPU_HPA */
@@ -1678,7 +1686,7 @@
             // dev = find_hpa_device(hpa);
             // searches for 0xf1041000
             dev = find_hppa_device_by_hpa(hpa);
-            printf("pdc_iodc found dev %p\n", dev);
+            // printf("pdc_iodc found dev %p\n", dev);
             if (!dev)
                 return -4; // not found
 
@@ -1704,10 +1712,10 @@
             memcpy((void*) ARG5, &iodc_entry, *result);
             c = (unsigned char *) &iodc_entry_table;
             /* calculate offset into jump table. */
-            entry_len = &iodc_entry_table_one_entry - &iodc_entry[0];
+            entry_len = &iodc_entry_table_one_entry - &iodc_entry_table;
             c += (ARG4 - PDC_IODC_RI_INIT) * entry_len;
             memcpy((void*) ARG5, c, entry_len);
-            printf("\n\nSeaBIOS: Info PDC_IODC function OK\n");
+            // printf("\n\nSeaBIOS: Info PDC_IODC function OK\n");
             flush_data_cache((char*)ARG5, *result);
             return PDC_OK;
             break;
@@ -1765,19 +1773,23 @@
             if ((ARG2 + ARG4) > STABLE_STORAGE_SIZE)
                 return PDC_INVALID_ARG;
             memcpy((unsigned char *) ARG3, &stable_storage[ARG2], ARG4);
+            NO_COMPAT_RETURN_VALUE(ARG2);
             return PDC_OK;
         case PDC_STABLE_WRITE:
             if ((ARG2 + ARG4) > STABLE_STORAGE_SIZE)
                 return PDC_INVALID_ARG;
             memcpy(&stable_storage[ARG2], (unsigned char *) ARG3, ARG4);
+            NO_COMPAT_RETURN_VALUE(ARG2);
             return PDC_OK;
         case PDC_STABLE_RETURN_SIZE:
             result[0] = STABLE_STORAGE_SIZE;
             return PDC_OK;
         case PDC_STABLE_VERIFY_CONTENTS:
+            NO_COMPAT_RETURN_VALUE(ARG2);
             return PDC_OK;
         case PDC_STABLE_INITIALIZE:
             init_stable_storage();
+            NO_COMPAT_RETURN_VALUE(ARG2);
             return PDC_OK;
     }
     return PDC_BAD_OPTION;
@@ -1793,19 +1805,23 @@
             if ((ARG2 + ARG4) > NVOLATILE_STORAGE_SIZE)
                 return PDC_INVALID_ARG;
             memcpy((unsigned char *) ARG3, &nvolatile_storage[ARG2], ARG4);
+            NO_COMPAT_RETURN_VALUE(ARG2);
             return PDC_OK;
         case PDC_NVOLATILE_WRITE:
             if ((ARG2 + ARG4) > NVOLATILE_STORAGE_SIZE)
                 return PDC_INVALID_ARG;
             memcpy(&nvolatile_storage[ARG2], (unsigned char *) ARG3, ARG4);
+            NO_COMPAT_RETURN_VALUE(ARG2);
             return PDC_OK;
         case PDC_NVOLATILE_RETURN_SIZE:
             result[0] = NVOLATILE_STORAGE_SIZE;
             return PDC_OK;
         case PDC_NVOLATILE_VERIFY_CONTENTS:
+            NO_COMPAT_RETURN_VALUE(ARG2);
             return PDC_OK;
         case PDC_NVOLATILE_INITIALIZE:
             memset(nvolatile_storage, 0, sizeof(nvolatile_storage));
+            NO_COMPAT_RETURN_VALUE(ARG2);
             return PDC_OK;
     }
     return PDC_BAD_OPTION;
@@ -1814,23 +1830,25 @@
 static int pdc_add_valid(unsigned long *arg)
 {
     unsigned long option = ARG1;
+    unsigned long arg2 = is_compat_mode() ? COMPAT_VAL(ARG2) : ARG2;
 
-    // dprintf(0, "\n\nSeaBIOS: PDC_ADD_VALID function %ld ARG2=%x called.\n", option, ARG2);
+    NO_COMPAT_RETURN_VALUE(ARG2);
+    // dprintf(0, "\n\nSeaBIOS: PDC_ADD_VALID function %ld arg2=%x called.\n", option, arg2);
     if (option != 0)
         return PDC_BAD_OPTION;
-    if (0 && ARG2 == 0) // should PAGE0 be valid?  HP-UX asks for it, but maybe due a bug in our code...
+    if (0 && arg2 == 0) // should PAGE0 be valid?  HP-UX asks for it, but maybe due a bug in our code...
         return 1;
-    // if (ARG2 < PAGE_SIZE) return PDC_ERROR;
-    if (ARG2 < ram_size)
+    // if (arg2 < PAGE_SIZE) return PDC_ERROR;
+    if (arg2 < ram_size)
         return PDC_OK;
-    if (ARG2 >= (unsigned long)_sti_rom_start &&
-        ARG2 <= (unsigned long)_sti_rom_end)
+    if (arg2 >= (unsigned long)_sti_rom_start &&
+        arg2 <= (unsigned long)_sti_rom_end)
         return PDC_OK;
-    if (ARG2 < FIRMWARE_END)
+    if (arg2 < FIRMWARE_END)
         return 1;
-    if (ARG2 <= 0xffffffff)
+    if (arg2 <= 0xffffffff)
         return PDC_OK;
-    dprintf(0, "\n\nSeaBIOS: FAILED!!!! PDC_ADD_VALID function %ld ARG2=%lx called.\n", option, ARG2);
+    dprintf(0, "\n\nSeaBIOS: FAILED!!!! PDC_ADD_VALID function %ld arg2=%lx called.\n", option, arg2);
     return PDC_REQ_ERR_0; /* Operation completed with a requestor bus error. */
 }
 
@@ -1951,6 +1969,7 @@
         mtctl(psw_defaults, CR_PSW_DEFAULT);
         /* let model know that we support 64-bit */
         current_machine->pdc_model.width = (psw_defaults & PDC_PSW_WIDE_BIT) ? 1 : 0;
+        NO_COMPAT_RETURN_VALUE(ARG2);
     }
     return PDC_OK;
 }
@@ -1989,7 +2008,8 @@
             result[0] = dev->mod_info->mod_addr; //  for PDC_IODC
             result[1] = dev->mod_info->mod_pgs;
             result[2] = dev->num_addr;           //  dev->mod_info->add_addr;
-            dprintf(1, "PDC_FIND_MODULE %lx %ld %ld \n", result[0], result[1],result[2]);
+            if (0)
+                dprintf(1, "PDC_FIND_MODULE %lx %ld %ld \n", result[0], result[1],result[2]);
 
             return PDC_OK;
 
@@ -2311,7 +2331,7 @@
 
     if (pdc_debug & DEBUG_PDC) {
         printf("\nSeaBIOS: Start PDC%d proc %s(%ld) option %ld result=0x%lx ARG3=0x%lx %s ",
-                is_compat_mode() ? 32 : 64, pdc_name(ARG0), ARG0, ARG1, ARG2, ARG3,
+                (!is_64bit_PDC() || is_compat_mode()) ? 32 : 64, pdc_name(ARG0), ARG0, ARG1, ARG2, ARG3,
                 (proc == PDC_IODC)?hpa_name(ARG3):"");
         printf("ARG4=0x%lx ARG5=0x%lx ARG6=0x%lx ARG7=0x%lx\n", ARG4, ARG5, ARG6, ARG7);
     }
@@ -2996,10 +3016,11 @@
     firmware_width_locked = 1;
 
     psw_defaults = PDC_PSW_ENDIAN_BIT;
-    if (is_64bit_CPU() && 0) {
+    if (0 && is_64bit_PDC()) {
         /* enable 64-bit PSW by default */
         psw_defaults |= PDC_PSW_WIDE_BIT;
         current_machine->pdc_model.width = 1;
+        firmware_width_locked = 0;
     }
     mtctl(psw_defaults, CR_PSW_DEFAULT);