1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/kernel.h>
4 #include <linux/kgdb.h>
5 #include <linux/printk.h>
6 #include <linux/sched/debug.h>
7 #include <linux/delay.h>
8 #include <linux/reboot.h>
11 #include <asm/pdc_chassis.h>
13 #include <asm/processor.h>
15 static unsigned int __aligned(16) toc_lock
= 1;
16 DEFINE_PER_CPU_PAGE_ALIGNED(char [16384], toc_stack
) __visible
;
18 static void toc20_to_pt_regs(struct pt_regs
*regs
, struct pdc_toc_pim_20
*toc
)
22 regs
->gr
[0] = (unsigned long)toc
->cr
[22];
24 for (i
= 1; i
< 32; i
++)
25 regs
->gr
[i
] = (unsigned long)toc
->gr
[i
];
27 for (i
= 0; i
< 8; i
++)
28 regs
->sr
[i
] = (unsigned long)toc
->sr
[i
];
30 regs
->iasq
[0] = (unsigned long)toc
->cr
[17];
31 regs
->iasq
[1] = (unsigned long)toc
->iasq_back
;
32 regs
->iaoq
[0] = (unsigned long)toc
->cr
[18];
33 regs
->iaoq
[1] = (unsigned long)toc
->iaoq_back
;
35 regs
->sar
= (unsigned long)toc
->cr
[11];
36 regs
->iir
= (unsigned long)toc
->cr
[19];
37 regs
->isr
= (unsigned long)toc
->cr
[20];
38 regs
->ior
= (unsigned long)toc
->cr
[21];
41 static void toc11_to_pt_regs(struct pt_regs
*regs
, struct pdc_toc_pim_11
*toc
)
45 regs
->gr
[0] = toc
->cr
[22];
47 for (i
= 1; i
< 32; i
++)
48 regs
->gr
[i
] = toc
->gr
[i
];
50 for (i
= 0; i
< 8; i
++)
51 regs
->sr
[i
] = toc
->sr
[i
];
53 regs
->iasq
[0] = toc
->cr
[17];
54 regs
->iasq
[1] = toc
->iasq_back
;
55 regs
->iaoq
[0] = toc
->cr
[18];
56 regs
->iaoq
[1] = toc
->iaoq_back
;
58 regs
->sar
= toc
->cr
[11];
59 regs
->iir
= toc
->cr
[19];
60 regs
->isr
= toc
->cr
[20];
61 regs
->ior
= toc
->cr
[21];
64 void notrace __noreturn __cold
toc_intr(struct pt_regs
*regs
)
66 struct pdc_toc_pim_20 pim_data20
;
67 struct pdc_toc_pim_11 pim_data11
;
69 /* verify we wrote regs to the correct stack */
70 BUG_ON(regs
!= (struct pt_regs
*)&per_cpu(toc_stack
, raw_smp_processor_id()));
72 if (boot_cpu_data
.cpu_type
>= pcxu
) {
73 if (pdc_pim_toc20(&pim_data20
))
74 panic("Failed to get PIM data");
75 toc20_to_pt_regs(regs
, &pim_data20
);
77 if (pdc_pim_toc11(&pim_data11
))
78 panic("Failed to get PIM data");
79 toc11_to_pt_regs(regs
, &pim_data11
);
85 if (atomic_read(&kgdb_active
) != -1)
86 kgdb_nmicallback(raw_smp_processor_id(), regs
);
87 kgdb_handle_exception(9, SIGTRAP
, 0, regs
);
90 /* serialize output, otherwise all CPUs write backtrace at once */
91 while (__ldcw(&toc_lock
) == 0)
94 toc_lock
= 1; /* release lock for next CPU */
96 if (raw_smp_processor_id() != 0)
97 while (1) ; /* all but monarch CPU will wait endless. */
99 /* give other CPUs time to show their backtrace */
102 machine_restart("TOC");
104 /* should never reach this */
108 static __init
int setup_toc(void)
110 unsigned int csum
= 0;
111 unsigned long toc_code
= (unsigned long)dereference_function_descriptor(toc_handler
);
114 PAGE0
->vec_toc
= __pa(toc_code
) & 0xffffffff;
116 PAGE0
->vec_toc_hi
= __pa(toc_code
) >> 32;
118 PAGE0
->vec_toclen
= toc_handler_size
;
120 for (i
= 0; i
< toc_handler_size
/4; i
++)
121 csum
+= ((u32
*)toc_code
)[i
];
122 toc_handler_csum
= -csum
;
123 pr_info("TOC handler registered\n");
126 early_initcall(setup_toc
);