@@ -34,6 +34,7 @@ static int riscv64_kvtop(struct task_context *tc, ulong kvaddr,
34
34
physaddr_t * paddr , int verbose );
35
35
static void riscv64_cmd_mach (void );
36
36
static void riscv64_irq_stack_init (void );
37
+ static void riscv64_overflow_stack_init (void );
37
38
static void riscv64_stackframe_init (void );
38
39
static void riscv64_back_trace_cmd (struct bt_info * bt );
39
40
static int riscv64_eframe_search (struct bt_info * bt );
@@ -59,6 +60,8 @@ static int riscv64_on_irq_stack(int , ulong);
59
60
static int riscv64_on_process_stack (struct bt_info * , ulong );
60
61
static void riscv64_set_process_stack (struct bt_info * );
61
62
static void riscv64_set_irq_stack (struct bt_info * );
63
+ static int riscv64_on_overflow_stack (int , ulong );
64
+ static void riscv64_set_overflow_stack (struct bt_info * );
62
65
63
66
#define REG_FMT "%016lx"
64
67
#define SZ_2G 0x80000000
@@ -206,6 +209,8 @@ riscv64_dump_machdep_table(ulong arg)
206
209
fprintf (fp , "%sKSYMS_START" , others ++ ? "|" : "" );
207
210
if (machdep -> flags & IRQ_STACKS )
208
211
fprintf (fp , "%sIRQ_STACKS" , others ++ ? "|" : "" );
212
+ if (machdep -> flags & OVERFLOW_STACKS )
213
+ fprintf (fp , "%sOVERFLOW_STACKS" , others ++ ? "|" : "" );
209
214
fprintf (fp , ")\n" );
210
215
211
216
fprintf (fp , " kvbase: %lx\n" , machdep -> kvbase );
@@ -270,6 +275,15 @@ riscv64_dump_machdep_table(ulong arg)
270
275
fprintf (fp , " irq_stack_size: (unused)\n" );
271
276
fprintf (fp , " irq_stacks: (unused)\n" );
272
277
}
278
+ if (machdep -> flags & OVERFLOW_STACKS ) {
279
+ fprintf (fp , " overflow_stack_size: %ld\n" , ms -> overflow_stack_size );
280
+ for (i = 0 ; i < kt -> cpus ; i ++ )
281
+ fprintf (fp , " overflow_stacks[%d]: %lx\n" ,
282
+ i , ms -> overflow_stacks [i ]);
283
+ } else {
284
+ fprintf (fp , " overflow_stack_size: (unused)\n" );
285
+ fprintf (fp , " overflow_stacks: (unused)\n" );
286
+ }
273
287
}
274
288
275
289
static ulong
@@ -684,6 +698,48 @@ riscv64_display_full_frame(struct bt_info *bt, struct riscv64_unwind_frame *curr
684
698
fprintf (fp , "\n" );
685
699
}
686
700
701
+
702
+ /*
703
+ * Gather Overflow stack values.
704
+ */
705
+ static void
706
+ riscv64_overflow_stack_init (void )
707
+ {
708
+ int i ;
709
+ struct syment * sp ;
710
+ struct gnu_request request , * req ;
711
+ struct machine_specific * ms = machdep -> machspec ;
712
+ req = & request ;
713
+
714
+ if (symbol_exists ("overflow_stack" ) &&
715
+ (sp = per_cpu_symbol_search ("overflow_stack" )) &&
716
+ get_symbol_type ("overflow_stack" , NULL , req )) {
717
+ if (CRASHDEBUG (1 )) {
718
+ fprintf (fp , "overflow_stack: \n" );
719
+ fprintf (fp , " type: %x, %s\n" ,
720
+ (int )req -> typecode ,
721
+ (req -> typecode == TYPE_CODE_ARRAY ) ?
722
+ "TYPE_CODE_ARRAY" : "other" );
723
+ fprintf (fp , " target_typecode: %x, %s\n" ,
724
+ (int )req -> target_typecode ,
725
+ req -> target_typecode == TYPE_CODE_INT ?
726
+ "TYPE_CODE_INT" : "other" );
727
+ fprintf (fp , " target_length: %ld\n" ,
728
+ req -> target_length );
729
+ fprintf (fp , " length: %ld\n" , req -> length );
730
+ }
731
+
732
+ if (!(ms -> overflow_stacks = (ulong * )malloc ((size_t )(kt -> cpus * sizeof (ulong )))))
733
+ error (FATAL , "cannot malloc overflow_stack addresses\n" );
734
+
735
+ ms -> overflow_stack_size = RISCV64_OVERFLOW_STACK_SIZE ;
736
+ machdep -> flags |= OVERFLOW_STACKS ;
737
+
738
+ for (i = 0 ; i < kt -> cpus ; i ++ )
739
+ ms -> overflow_stacks [i ] = kt -> __per_cpu_offset [i ] + sp -> value ;
740
+ }
741
+ }
742
+
687
743
/*
688
744
* Gather IRQ stack values.
689
745
*/
@@ -757,6 +813,23 @@ riscv64_on_irq_stack(int cpu, ulong stkptr)
757
813
return FALSE;
758
814
}
759
815
816
+ static int
817
+ riscv64_on_overflow_stack (int cpu , ulong stkptr )
818
+ {
819
+ struct machine_specific * ms = machdep -> machspec ;
820
+ ulong * stacks = ms -> overflow_stacks ;
821
+ ulong stack_size = ms -> overflow_stack_size ;
822
+
823
+ if ((cpu >= kt -> cpus ) || (stacks == NULL ) || !stack_size )
824
+ return FALSE;
825
+
826
+ if ((stkptr >= stacks [cpu ]) &&
827
+ (stkptr < (stacks [cpu ] + stack_size )))
828
+ return TRUE;
829
+
830
+ return FALSE;
831
+ }
832
+
760
833
static int
761
834
riscv64_on_process_stack (struct bt_info * bt , ulong stkptr )
762
835
{
@@ -781,6 +854,16 @@ riscv64_set_irq_stack(struct bt_info *bt)
781
854
alter_stackbuf (bt );
782
855
}
783
856
857
+ static void
858
+ riscv64_set_overflow_stack (struct bt_info * bt )
859
+ {
860
+ struct machine_specific * ms = machdep -> machspec ;
861
+
862
+ bt -> stackbase = ms -> overflow_stacks [bt -> tc -> processor ];
863
+ bt -> stacktop = bt -> stackbase + ms -> overflow_stack_size ;
864
+ alter_stackbuf (bt );
865
+ }
866
+
784
867
static void
785
868
riscv64_set_process_stack (struct bt_info * bt )
786
869
{
@@ -875,7 +958,7 @@ riscv64_back_trace_cmd(struct bt_info *bt)
875
958
{
876
959
struct riscv64_unwind_frame current , previous ;
877
960
struct stackframe curr_frame ;
878
- struct riscv64_register * regs , * irq_regs ;
961
+ struct riscv64_register * regs , * irq_regs , * overflow_regs ;
879
962
int level = 0 ;
880
963
881
964
if (bt -> flags & BT_REGS_NOT_FOUND )
@@ -888,6 +971,11 @@ riscv64_back_trace_cmd(struct bt_info *bt)
888
971
bt -> flags |= BT_IRQSTACK ;
889
972
}
890
973
974
+ if (riscv64_on_overflow_stack (bt -> tc -> processor , bt -> frameptr )) {
975
+ riscv64_set_overflow_stack (bt );
976
+ bt -> flags |= BT_OVERFLOW_STACK ;
977
+ }
978
+
891
979
current .pc = bt -> instptr ;
892
980
current .sp = bt -> stkptr ;
893
981
current .fp = bt -> frameptr ;
@@ -971,6 +1059,28 @@ riscv64_back_trace_cmd(struct bt_info *bt)
971
1059
}
972
1060
}
973
1061
1062
+ /*
1063
+ * When backtracing to handle_kernel_stack_overflow()
1064
+ * use pt_regs saved in overflow stack to continue
1065
+ */
1066
+ if ((bt -> flags & BT_OVERFLOW_STACK ) &&
1067
+ !riscv64_on_overflow_stack (bt -> tc -> processor , current .fp )) {
1068
+
1069
+ overflow_regs = (struct riscv64_register * )
1070
+ & bt -> stackbuf [(ulong )(STACK_OFFSET_TYPE (current .sp ))];
1071
+
1072
+ riscv64_print_exception_frame (bt , current .sp , KERNEL_MODE );
1073
+
1074
+ current .pc = overflow_regs -> regs [RISCV64_REGS_EPC ];
1075
+ current .fp = overflow_regs -> regs [RISCV64_REGS_FP ];
1076
+ current .sp = overflow_regs -> regs [RISCV64_REGS_SP ];
1077
+
1078
+ riscv64_set_process_stack (bt );
1079
+
1080
+ bt -> flags &= ~BT_OVERFLOW_STACK ;
1081
+ fprintf (fp , "--- <OVERFLOW stack> ---\n" );
1082
+ }
1083
+
974
1084
if (CRASHDEBUG (8 ))
975
1085
fprintf (fp , "next %d pc %#lx sp %#lx fp %lx\n" ,
976
1086
level , current .pc , current .sp , current .fp );
@@ -1583,6 +1693,7 @@ riscv64_init(int when)
1583
1693
machdep -> max_physmem_bits = _MAX_PHYSMEM_BITS ;
1584
1694
1585
1695
riscv64_irq_stack_init ();
1696
+ riscv64_overflow_stack_init ();
1586
1697
riscv64_stackframe_init ();
1587
1698
riscv64_page_type_init ();
1588
1699
0 commit comments