Commit f0514ae323f19ba1ad4bea4174ea274c812f7eee

Authored by James Bottomley
Committed by Kyle McMartin
1 parent 0be7d1fe43

parisc: initialize unwinder much earlier

The unwinder was being initialized way too late to be any use
debugging early boot crashes. Instead of relying on module_init
initcalls to initialize it, let's do it explicitly as early as
we can.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>

Showing 3 changed files with 5 additions and 3 deletions Inline Diff

arch/parisc/include/asm/unwind.h
1 #ifndef _UNWIND_H_ 1 #ifndef _UNWIND_H_
2 #define _UNWIND_H_ 2 #define _UNWIND_H_
3 3
4 #include <linux/list.h> 4 #include <linux/list.h>
5 5
6 /* From ABI specifications */ 6 /* From ABI specifications */
7 struct unwind_table_entry { 7 struct unwind_table_entry {
8 unsigned int region_start; 8 unsigned int region_start;
9 unsigned int region_end; 9 unsigned int region_end;
10 unsigned int Cannot_unwind:1; /* 0 */ 10 unsigned int Cannot_unwind:1; /* 0 */
11 unsigned int Millicode:1; /* 1 */ 11 unsigned int Millicode:1; /* 1 */
12 unsigned int Millicode_save_sr0:1; /* 2 */ 12 unsigned int Millicode_save_sr0:1; /* 2 */
13 unsigned int Region_description:2; /* 3..4 */ 13 unsigned int Region_description:2; /* 3..4 */
14 unsigned int reserved1:1; /* 5 */ 14 unsigned int reserved1:1; /* 5 */
15 unsigned int Entry_SR:1; /* 6 */ 15 unsigned int Entry_SR:1; /* 6 */
16 unsigned int Entry_FR:4; /* number saved *//* 7..10 */ 16 unsigned int Entry_FR:4; /* number saved *//* 7..10 */
17 unsigned int Entry_GR:5; /* number saved *//* 11..15 */ 17 unsigned int Entry_GR:5; /* number saved *//* 11..15 */
18 unsigned int Args_stored:1; /* 16 */ 18 unsigned int Args_stored:1; /* 16 */
19 unsigned int Variable_Frame:1; /* 17 */ 19 unsigned int Variable_Frame:1; /* 17 */
20 unsigned int Separate_Package_Body:1; /* 18 */ 20 unsigned int Separate_Package_Body:1; /* 18 */
21 unsigned int Frame_Extension_Millicode:1; /* 19 */ 21 unsigned int Frame_Extension_Millicode:1; /* 19 */
22 unsigned int Stack_Overflow_Check:1; /* 20 */ 22 unsigned int Stack_Overflow_Check:1; /* 20 */
23 unsigned int Two_Instruction_SP_Increment:1; /* 21 */ 23 unsigned int Two_Instruction_SP_Increment:1; /* 21 */
24 unsigned int Ada_Region:1; /* 22 */ 24 unsigned int Ada_Region:1; /* 22 */
25 unsigned int cxx_info:1; /* 23 */ 25 unsigned int cxx_info:1; /* 23 */
26 unsigned int cxx_try_catch:1; /* 24 */ 26 unsigned int cxx_try_catch:1; /* 24 */
27 unsigned int sched_entry_seq:1; /* 25 */ 27 unsigned int sched_entry_seq:1; /* 25 */
28 unsigned int reserved2:1; /* 26 */ 28 unsigned int reserved2:1; /* 26 */
29 unsigned int Save_SP:1; /* 27 */ 29 unsigned int Save_SP:1; /* 27 */
30 unsigned int Save_RP:1; /* 28 */ 30 unsigned int Save_RP:1; /* 28 */
31 unsigned int Save_MRP_in_frame:1; /* 29 */ 31 unsigned int Save_MRP_in_frame:1; /* 29 */
32 unsigned int extn_ptr_defined:1; /* 30 */ 32 unsigned int extn_ptr_defined:1; /* 30 */
33 unsigned int Cleanup_defined:1; /* 31 */ 33 unsigned int Cleanup_defined:1; /* 31 */
34 34
35 unsigned int MPE_XL_interrupt_marker:1; /* 0 */ 35 unsigned int MPE_XL_interrupt_marker:1; /* 0 */
36 unsigned int HP_UX_interrupt_marker:1; /* 1 */ 36 unsigned int HP_UX_interrupt_marker:1; /* 1 */
37 unsigned int Large_frame:1; /* 2 */ 37 unsigned int Large_frame:1; /* 2 */
38 unsigned int Pseudo_SP_Set:1; /* 3 */ 38 unsigned int Pseudo_SP_Set:1; /* 3 */
39 unsigned int reserved4:1; /* 4 */ 39 unsigned int reserved4:1; /* 4 */
40 unsigned int Total_frame_size:27; /* 5..31 */ 40 unsigned int Total_frame_size:27; /* 5..31 */
41 }; 41 };
42 42
43 struct unwind_table { 43 struct unwind_table {
44 struct list_head list; 44 struct list_head list;
45 const char *name; 45 const char *name;
46 unsigned long gp; 46 unsigned long gp;
47 unsigned long base_addr; 47 unsigned long base_addr;
48 unsigned long start; 48 unsigned long start;
49 unsigned long end; 49 unsigned long end;
50 const struct unwind_table_entry *table; 50 const struct unwind_table_entry *table;
51 unsigned long length; 51 unsigned long length;
52 }; 52 };
53 53
54 struct unwind_frame_info { 54 struct unwind_frame_info {
55 struct task_struct *t; 55 struct task_struct *t;
56 /* Eventually we would like to be able to get at any of the registers 56 /* Eventually we would like to be able to get at any of the registers
57 available; but for now we only try to get the sp and ip for each 57 available; but for now we only try to get the sp and ip for each
58 frame */ 58 frame */
59 /* struct pt_regs regs; */ 59 /* struct pt_regs regs; */
60 unsigned long sp, ip, rp, r31; 60 unsigned long sp, ip, rp, r31;
61 unsigned long prev_sp, prev_ip; 61 unsigned long prev_sp, prev_ip;
62 }; 62 };
63 63
64 struct unwind_table * 64 struct unwind_table *
65 unwind_table_add(const char *name, unsigned long base_addr, 65 unwind_table_add(const char *name, unsigned long base_addr,
66 unsigned long gp, void *start, void *end); 66 unsigned long gp, void *start, void *end);
67 void 67 void
68 unwind_table_remove(struct unwind_table *table); 68 unwind_table_remove(struct unwind_table *table);
69 69
70 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 70 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
71 struct pt_regs *regs); 71 struct pt_regs *regs);
72 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t); 72 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t);
73 void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs); 73 void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs);
74 int unwind_once(struct unwind_frame_info *info); 74 int unwind_once(struct unwind_frame_info *info);
75 int unwind_to_user(struct unwind_frame_info *info); 75 int unwind_to_user(struct unwind_frame_info *info);
76 76
77 int unwind_init(void);
78
77 #endif 79 #endif
78 80
arch/parisc/kernel/setup.c
1 /* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $ 1 /* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $
2 * 2 *
3 * Initial setup-routines for HP 9000 based hardware. 3 * Initial setup-routines for HP 9000 based hardware.
4 * 4 *
5 * Copyright (C) 1991, 1992, 1995 Linus Torvalds 5 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
6 * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de> 6 * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
7 * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf) 7 * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
8 * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net> 8 * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
9 * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org> 9 * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
10 * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net> 10 * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
11 * 11 *
12 * Initial PA-RISC Version: 04-23-1999 by Helge Deller 12 * Initial PA-RISC Version: 04-23-1999 by Helge Deller
13 * 13 *
14 * This program is free software; you can redistribute it and/or modify 14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option) 16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version. 17 * any later version.
18 * 18 *
19 * This program is distributed in the hope that it will be useful, 19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details. 22 * GNU General Public License for more details.
23 * 23 *
24 * You should have received a copy of the GNU General Public License 24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software 25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 * 27 *
28 */ 28 */
29 29
30 #include <linux/kernel.h> 30 #include <linux/kernel.h>
31 #include <linux/initrd.h> 31 #include <linux/initrd.h>
32 #include <linux/init.h> 32 #include <linux/init.h>
33 #include <linux/console.h> 33 #include <linux/console.h>
34 #include <linux/seq_file.h> 34 #include <linux/seq_file.h>
35 #define PCI_DEBUG 35 #define PCI_DEBUG
36 #include <linux/pci.h> 36 #include <linux/pci.h>
37 #undef PCI_DEBUG 37 #undef PCI_DEBUG
38 #include <linux/proc_fs.h> 38 #include <linux/proc_fs.h>
39 39
40 #include <asm/processor.h> 40 #include <asm/processor.h>
41 #include <asm/pdc.h> 41 #include <asm/pdc.h>
42 #include <asm/led.h> 42 #include <asm/led.h>
43 #include <asm/machdep.h> /* for pa7300lc_init() proto */ 43 #include <asm/machdep.h> /* for pa7300lc_init() proto */
44 #include <asm/pdc_chassis.h> 44 #include <asm/pdc_chassis.h>
45 #include <asm/io.h> 45 #include <asm/io.h>
46 #include <asm/setup.h> 46 #include <asm/setup.h>
47 #include <asm/unwind.h>
47 48
48 static char __initdata command_line[COMMAND_LINE_SIZE]; 49 static char __initdata command_line[COMMAND_LINE_SIZE];
49 50
50 /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */ 51 /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
51 struct proc_dir_entry * proc_runway_root __read_mostly = NULL; 52 struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
52 struct proc_dir_entry * proc_gsc_root __read_mostly = NULL; 53 struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
53 struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL; 54 struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL;
54 55
55 #if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA)) 56 #if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA))
56 int parisc_bus_is_phys __read_mostly = 1; /* Assume no IOMMU is present */ 57 int parisc_bus_is_phys __read_mostly = 1; /* Assume no IOMMU is present */
57 EXPORT_SYMBOL(parisc_bus_is_phys); 58 EXPORT_SYMBOL(parisc_bus_is_phys);
58 #endif 59 #endif
59 60
60 /* This sets the vmerge boundary and size, it's here because it has to 61 /* This sets the vmerge boundary and size, it's here because it has to
61 * be available on all platforms (zero means no-virtual merging) */ 62 * be available on all platforms (zero means no-virtual merging) */
62 unsigned long parisc_vmerge_boundary = 0; 63 unsigned long parisc_vmerge_boundary = 0;
63 unsigned long parisc_vmerge_max_size = 0; 64 unsigned long parisc_vmerge_max_size = 0;
64 65
65 void __init setup_cmdline(char **cmdline_p) 66 void __init setup_cmdline(char **cmdline_p)
66 { 67 {
67 extern unsigned int boot_args[]; 68 extern unsigned int boot_args[];
68 69
69 /* Collect stuff passed in from the boot loader */ 70 /* Collect stuff passed in from the boot loader */
70 71
71 /* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */ 72 /* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */
72 if (boot_args[0] < 64) { 73 if (boot_args[0] < 64) {
73 /* called from hpux boot loader */ 74 /* called from hpux boot loader */
74 boot_command_line[0] = '\0'; 75 boot_command_line[0] = '\0';
75 } else { 76 } else {
76 strcpy(boot_command_line, (char *)__va(boot_args[1])); 77 strcpy(boot_command_line, (char *)__va(boot_args[1]));
77 78
78 #ifdef CONFIG_BLK_DEV_INITRD 79 #ifdef CONFIG_BLK_DEV_INITRD
79 if (boot_args[2] != 0) /* did palo pass us a ramdisk? */ 80 if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
80 { 81 {
81 initrd_start = (unsigned long)__va(boot_args[2]); 82 initrd_start = (unsigned long)__va(boot_args[2]);
82 initrd_end = (unsigned long)__va(boot_args[3]); 83 initrd_end = (unsigned long)__va(boot_args[3]);
83 } 84 }
84 #endif 85 #endif
85 } 86 }
86 87
87 strcpy(command_line, boot_command_line); 88 strcpy(command_line, boot_command_line);
88 *cmdline_p = command_line; 89 *cmdline_p = command_line;
89 } 90 }
90 91
91 #ifdef CONFIG_PA11 92 #ifdef CONFIG_PA11
92 void __init dma_ops_init(void) 93 void __init dma_ops_init(void)
93 { 94 {
94 switch (boot_cpu_data.cpu_type) { 95 switch (boot_cpu_data.cpu_type) {
95 case pcx: 96 case pcx:
96 /* 97 /*
97 * We've got way too many dependencies on 1.1 semantics 98 * We've got way too many dependencies on 1.1 semantics
98 * to support 1.0 boxes at this point. 99 * to support 1.0 boxes at this point.
99 */ 100 */
100 panic( "PA-RISC Linux currently only supports machines that conform to\n" 101 panic( "PA-RISC Linux currently only supports machines that conform to\n"
101 "the PA-RISC 1.1 or 2.0 architecture specification.\n"); 102 "the PA-RISC 1.1 or 2.0 architecture specification.\n");
102 103
103 case pcxs: 104 case pcxs:
104 case pcxt: 105 case pcxt:
105 hppa_dma_ops = &pcx_dma_ops; 106 hppa_dma_ops = &pcx_dma_ops;
106 break; 107 break;
107 case pcxl2: 108 case pcxl2:
108 pa7300lc_init(); 109 pa7300lc_init();
109 case pcxl: /* falls through */ 110 case pcxl: /* falls through */
110 hppa_dma_ops = &pcxl_dma_ops; 111 hppa_dma_ops = &pcxl_dma_ops;
111 break; 112 break;
112 default: 113 default:
113 break; 114 break;
114 } 115 }
115 } 116 }
116 #endif 117 #endif
117 118
118 extern int init_per_cpu(int cpuid); 119 extern int init_per_cpu(int cpuid);
119 extern void collect_boot_cpu_data(void); 120 extern void collect_boot_cpu_data(void);
120 121
121 void __init setup_arch(char **cmdline_p) 122 void __init setup_arch(char **cmdline_p)
122 { 123 {
123 #ifdef CONFIG_64BIT 124 #ifdef CONFIG_64BIT
124 extern int parisc_narrow_firmware; 125 extern int parisc_narrow_firmware;
125 #endif 126 #endif
127 unwind_init();
126 128
127 init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */ 129 init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */
128 130
129 #ifdef CONFIG_64BIT 131 #ifdef CONFIG_64BIT
130 printk(KERN_INFO "The 64-bit Kernel has started...\n"); 132 printk(KERN_INFO "The 64-bit Kernel has started...\n");
131 #else 133 #else
132 printk(KERN_INFO "The 32-bit Kernel has started...\n"); 134 printk(KERN_INFO "The 32-bit Kernel has started...\n");
133 #endif 135 #endif
134 136
135 pdc_console_init(); 137 pdc_console_init();
136 138
137 #ifdef CONFIG_64BIT 139 #ifdef CONFIG_64BIT
138 if(parisc_narrow_firmware) { 140 if(parisc_narrow_firmware) {
139 printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n"); 141 printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
140 } 142 }
141 #endif 143 #endif
142 setup_pdc(); 144 setup_pdc();
143 setup_cmdline(cmdline_p); 145 setup_cmdline(cmdline_p);
144 collect_boot_cpu_data(); 146 collect_boot_cpu_data();
145 do_memory_inventory(); /* probe for physical memory */ 147 do_memory_inventory(); /* probe for physical memory */
146 parisc_cache_init(); 148 parisc_cache_init();
147 paging_init(); 149 paging_init();
148 150
149 #ifdef CONFIG_CHASSIS_LCD_LED 151 #ifdef CONFIG_CHASSIS_LCD_LED
150 /* initialize the LCD/LED after boot_cpu_data is available ! */ 152 /* initialize the LCD/LED after boot_cpu_data is available ! */
151 led_init(); /* LCD/LED initialization */ 153 led_init(); /* LCD/LED initialization */
152 #endif 154 #endif
153 155
154 #ifdef CONFIG_PA11 156 #ifdef CONFIG_PA11
155 dma_ops_init(); 157 dma_ops_init();
156 #endif 158 #endif
157 159
158 #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) 160 #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
159 conswitchp = &dummy_con; /* we use take_over_console() later ! */ 161 conswitchp = &dummy_con; /* we use take_over_console() later ! */
160 #endif 162 #endif
161 163
162 } 164 }
163 165
164 /* 166 /*
165 * Display CPU info for all CPUs. 167 * Display CPU info for all CPUs.
166 * for parisc this is in processor.c 168 * for parisc this is in processor.c
167 */ 169 */
168 extern int show_cpuinfo (struct seq_file *m, void *v); 170 extern int show_cpuinfo (struct seq_file *m, void *v);
169 171
170 static void * 172 static void *
171 c_start (struct seq_file *m, loff_t *pos) 173 c_start (struct seq_file *m, loff_t *pos)
172 { 174 {
173 /* Looks like the caller will call repeatedly until we return 175 /* Looks like the caller will call repeatedly until we return
174 * 0, signaling EOF perhaps. This could be used to sequence 176 * 0, signaling EOF perhaps. This could be used to sequence
175 * through CPUs for example. Since we print all cpu info in our 177 * through CPUs for example. Since we print all cpu info in our
176 * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above) 178 * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above)
177 * we only allow for one "position". */ 179 * we only allow for one "position". */
178 return ((long)*pos < 1) ? (void *)1 : NULL; 180 return ((long)*pos < 1) ? (void *)1 : NULL;
179 } 181 }
180 182
181 static void * 183 static void *
182 c_next (struct seq_file *m, void *v, loff_t *pos) 184 c_next (struct seq_file *m, void *v, loff_t *pos)
183 { 185 {
184 ++*pos; 186 ++*pos;
185 return c_start(m, pos); 187 return c_start(m, pos);
186 } 188 }
187 189
188 static void 190 static void
189 c_stop (struct seq_file *m, void *v) 191 c_stop (struct seq_file *m, void *v)
190 { 192 {
191 } 193 }
192 194
193 const struct seq_operations cpuinfo_op = { 195 const struct seq_operations cpuinfo_op = {
194 .start = c_start, 196 .start = c_start,
195 .next = c_next, 197 .next = c_next,
196 .stop = c_stop, 198 .stop = c_stop,
197 .show = show_cpuinfo 199 .show = show_cpuinfo
198 }; 200 };
199 201
200 static void __init parisc_proc_mkdir(void) 202 static void __init parisc_proc_mkdir(void)
201 { 203 {
202 /* 204 /*
203 ** Can't call proc_mkdir() until after proc_root_init() has been 205 ** Can't call proc_mkdir() until after proc_root_init() has been
204 ** called by start_kernel(). In other words, this code can't 206 ** called by start_kernel(). In other words, this code can't
205 ** live in arch/.../setup.c because start_parisc() calls 207 ** live in arch/.../setup.c because start_parisc() calls
206 ** start_kernel(). 208 ** start_kernel().
207 */ 209 */
208 switch (boot_cpu_data.cpu_type) { 210 switch (boot_cpu_data.cpu_type) {
209 case pcxl: 211 case pcxl:
210 case pcxl2: 212 case pcxl2:
211 if (NULL == proc_gsc_root) 213 if (NULL == proc_gsc_root)
212 { 214 {
213 proc_gsc_root = proc_mkdir("bus/gsc", NULL); 215 proc_gsc_root = proc_mkdir("bus/gsc", NULL);
214 } 216 }
215 break; 217 break;
216 case pcxt_: 218 case pcxt_:
217 case pcxu: 219 case pcxu:
218 case pcxu_: 220 case pcxu_:
219 case pcxw: 221 case pcxw:
220 case pcxw_: 222 case pcxw_:
221 case pcxw2: 223 case pcxw2:
222 if (NULL == proc_runway_root) 224 if (NULL == proc_runway_root)
223 { 225 {
224 proc_runway_root = proc_mkdir("bus/runway", NULL); 226 proc_runway_root = proc_mkdir("bus/runway", NULL);
225 } 227 }
226 break; 228 break;
227 case mako: 229 case mako:
228 case mako2: 230 case mako2:
229 if (NULL == proc_mckinley_root) 231 if (NULL == proc_mckinley_root)
230 { 232 {
231 proc_mckinley_root = proc_mkdir("bus/mckinley", NULL); 233 proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
232 } 234 }
233 break; 235 break;
234 default: 236 default:
235 /* FIXME: this was added to prevent the compiler 237 /* FIXME: this was added to prevent the compiler
236 * complaining about missing pcx, pcxs and pcxt 238 * complaining about missing pcx, pcxs and pcxt
237 * I'm assuming they have neither gsc nor runway */ 239 * I'm assuming they have neither gsc nor runway */
238 break; 240 break;
239 } 241 }
240 } 242 }
241 243
242 static struct resource central_bus = { 244 static struct resource central_bus = {
243 .name = "Central Bus", 245 .name = "Central Bus",
244 .start = F_EXTEND(0xfff80000), 246 .start = F_EXTEND(0xfff80000),
245 .end = F_EXTEND(0xfffaffff), 247 .end = F_EXTEND(0xfffaffff),
246 .flags = IORESOURCE_MEM, 248 .flags = IORESOURCE_MEM,
247 }; 249 };
248 250
249 static struct resource local_broadcast = { 251 static struct resource local_broadcast = {
250 .name = "Local Broadcast", 252 .name = "Local Broadcast",
251 .start = F_EXTEND(0xfffb0000), 253 .start = F_EXTEND(0xfffb0000),
252 .end = F_EXTEND(0xfffdffff), 254 .end = F_EXTEND(0xfffdffff),
253 .flags = IORESOURCE_MEM, 255 .flags = IORESOURCE_MEM,
254 }; 256 };
255 257
256 static struct resource global_broadcast = { 258 static struct resource global_broadcast = {
257 .name = "Global Broadcast", 259 .name = "Global Broadcast",
258 .start = F_EXTEND(0xfffe0000), 260 .start = F_EXTEND(0xfffe0000),
259 .end = F_EXTEND(0xffffffff), 261 .end = F_EXTEND(0xffffffff),
260 .flags = IORESOURCE_MEM, 262 .flags = IORESOURCE_MEM,
261 }; 263 };
262 264
263 static int __init parisc_init_resources(void) 265 static int __init parisc_init_resources(void)
264 { 266 {
265 int result; 267 int result;
266 268
267 result = request_resource(&iomem_resource, &central_bus); 269 result = request_resource(&iomem_resource, &central_bus);
268 if (result < 0) { 270 if (result < 0) {
269 printk(KERN_ERR 271 printk(KERN_ERR
270 "%s: failed to claim %s address space!\n", 272 "%s: failed to claim %s address space!\n",
271 __FILE__, central_bus.name); 273 __FILE__, central_bus.name);
272 return result; 274 return result;
273 } 275 }
274 276
275 result = request_resource(&iomem_resource, &local_broadcast); 277 result = request_resource(&iomem_resource, &local_broadcast);
276 if (result < 0) { 278 if (result < 0) {
277 printk(KERN_ERR 279 printk(KERN_ERR
278 "%s: failed to claim %saddress space!\n", 280 "%s: failed to claim %saddress space!\n",
279 __FILE__, local_broadcast.name); 281 __FILE__, local_broadcast.name);
280 return result; 282 return result;
281 } 283 }
282 284
283 result = request_resource(&iomem_resource, &global_broadcast); 285 result = request_resource(&iomem_resource, &global_broadcast);
284 if (result < 0) { 286 if (result < 0) {
285 printk(KERN_ERR 287 printk(KERN_ERR
286 "%s: failed to claim %s address space!\n", 288 "%s: failed to claim %s address space!\n",
287 __FILE__, global_broadcast.name); 289 __FILE__, global_broadcast.name);
288 return result; 290 return result;
289 } 291 }
290 292
291 return 0; 293 return 0;
292 } 294 }
293 295
294 extern void gsc_init(void); 296 extern void gsc_init(void);
295 extern void processor_init(void); 297 extern void processor_init(void);
296 extern void ccio_init(void); 298 extern void ccio_init(void);
297 extern void hppb_init(void); 299 extern void hppb_init(void);
298 extern void dino_init(void); 300 extern void dino_init(void);
299 extern void iosapic_init(void); 301 extern void iosapic_init(void);
300 extern void lba_init(void); 302 extern void lba_init(void);
301 extern void sba_init(void); 303 extern void sba_init(void);
302 extern void eisa_init(void); 304 extern void eisa_init(void);
303 305
304 static int __init parisc_init(void) 306 static int __init parisc_init(void)
305 { 307 {
306 u32 osid = (OS_ID_LINUX << 16); 308 u32 osid = (OS_ID_LINUX << 16);
307 309
308 parisc_proc_mkdir(); 310 parisc_proc_mkdir();
309 parisc_init_resources(); 311 parisc_init_resources();
310 do_device_inventory(); /* probe for hardware */ 312 do_device_inventory(); /* probe for hardware */
311 313
312 parisc_pdc_chassis_init(); 314 parisc_pdc_chassis_init();
313 315
314 /* set up a new led state on systems shipped LED State panel */ 316 /* set up a new led state on systems shipped LED State panel */
315 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART); 317 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART);
316 318
317 /* tell PDC we're Linux. Nevermind failure. */ 319 /* tell PDC we're Linux. Nevermind failure. */
318 pdc_stable_write(0x40, &osid, sizeof(osid)); 320 pdc_stable_write(0x40, &osid, sizeof(osid));
319 321
320 processor_init(); 322 processor_init();
321 printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n", 323 printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
322 boot_cpu_data.cpu_count, 324 boot_cpu_data.cpu_count,
323 boot_cpu_data.cpu_name, 325 boot_cpu_data.cpu_name,
324 boot_cpu_data.cpu_hz / 1000000, 326 boot_cpu_data.cpu_hz / 1000000,
325 boot_cpu_data.cpu_hz % 1000000 ); 327 boot_cpu_data.cpu_hz % 1000000 );
326 328
327 parisc_setup_cache_timing(); 329 parisc_setup_cache_timing();
328 330
329 /* These are in a non-obvious order, will fix when we have an iotree */ 331 /* These are in a non-obvious order, will fix when we have an iotree */
330 #if defined(CONFIG_IOSAPIC) 332 #if defined(CONFIG_IOSAPIC)
331 iosapic_init(); 333 iosapic_init();
332 #endif 334 #endif
333 #if defined(CONFIG_IOMMU_SBA) 335 #if defined(CONFIG_IOMMU_SBA)
334 sba_init(); 336 sba_init();
335 #endif 337 #endif
336 #if defined(CONFIG_PCI_LBA) 338 #if defined(CONFIG_PCI_LBA)
337 lba_init(); 339 lba_init();
338 #endif 340 #endif
339 341
340 /* CCIO before any potential subdevices */ 342 /* CCIO before any potential subdevices */
341 #if defined(CONFIG_IOMMU_CCIO) 343 #if defined(CONFIG_IOMMU_CCIO)
342 ccio_init(); 344 ccio_init();
343 #endif 345 #endif
344 346
345 /* 347 /*
346 * Need to register Asp & Wax before the EISA adapters for the IRQ 348 * Need to register Asp & Wax before the EISA adapters for the IRQ
347 * regions. EISA must come before PCI to be sure it gets IRQ region 349 * regions. EISA must come before PCI to be sure it gets IRQ region
348 * 0. 350 * 0.
349 */ 351 */
350 #if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX) 352 #if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX)
351 gsc_init(); 353 gsc_init();
352 #endif 354 #endif
353 #ifdef CONFIG_EISA 355 #ifdef CONFIG_EISA
354 eisa_init(); 356 eisa_init();
355 #endif 357 #endif
356 358
357 #if defined(CONFIG_HPPB) 359 #if defined(CONFIG_HPPB)
358 hppb_init(); 360 hppb_init();
359 #endif 361 #endif
360 362
361 #if defined(CONFIG_GSC_DINO) 363 #if defined(CONFIG_GSC_DINO)
362 dino_init(); 364 dino_init();
363 #endif 365 #endif
364 366
365 #ifdef CONFIG_CHASSIS_LCD_LED 367 #ifdef CONFIG_CHASSIS_LCD_LED
366 register_led_regions(); /* register LED port info in procfs */ 368 register_led_regions(); /* register LED port info in procfs */
367 #endif 369 #endif
368 370
369 return 0; 371 return 0;
370 } 372 }
371 arch_initcall(parisc_init); 373 arch_initcall(parisc_init);
372 374
373 void start_parisc(void) 375 void start_parisc(void)
374 { 376 {
375 extern void start_kernel(void); 377 extern void start_kernel(void);
376 378
377 int ret, cpunum; 379 int ret, cpunum;
378 struct pdc_coproc_cfg coproc_cfg; 380 struct pdc_coproc_cfg coproc_cfg;
379 381
380 cpunum = smp_processor_id(); 382 cpunum = smp_processor_id();
381 383
382 set_firmware_width_unlocked(); 384 set_firmware_width_unlocked();
383 385
384 ret = pdc_coproc_cfg_unlocked(&coproc_cfg); 386 ret = pdc_coproc_cfg_unlocked(&coproc_cfg);
385 if (ret >= 0 && coproc_cfg.ccr_functional) { 387 if (ret >= 0 && coproc_cfg.ccr_functional) {
386 mtctl(coproc_cfg.ccr_functional, 10); 388 mtctl(coproc_cfg.ccr_functional, 10);
387 389
388 cpu_data[cpunum].fp_rev = coproc_cfg.revision; 390 cpu_data[cpunum].fp_rev = coproc_cfg.revision;
389 cpu_data[cpunum].fp_model = coproc_cfg.model; 391 cpu_data[cpunum].fp_model = coproc_cfg.model;
390 392
391 asm volatile ("fstd %fr0,8(%sp)"); 393 asm volatile ("fstd %fr0,8(%sp)");
392 } else { 394 } else {
393 panic("must have an fpu to boot linux"); 395 panic("must have an fpu to boot linux");
394 } 396 }
395 397
396 start_kernel(); 398 start_kernel();
397 // not reached 399 // not reached
398 } 400 }
399 401
arch/parisc/kernel/unwind.c
1 /* 1 /*
2 * Kernel unwinding support 2 * Kernel unwinding support
3 * 3 *
4 * (c) 2002-2004 Randolph Chung <tausq@debian.org> 4 * (c) 2002-2004 Randolph Chung <tausq@debian.org>
5 * 5 *
6 * Derived partially from the IA64 implementation. The PA-RISC 6 * Derived partially from the IA64 implementation. The PA-RISC
7 * Runtime Architecture Document is also a useful reference to 7 * Runtime Architecture Document is also a useful reference to
8 * understand what is happening here 8 * understand what is happening here
9 */ 9 */
10 10
11 #include <linux/kernel.h> 11 #include <linux/kernel.h>
12 #include <linux/init.h> 12 #include <linux/init.h>
13 #include <linux/sched.h> 13 #include <linux/sched.h>
14 #include <linux/slab.h> 14 #include <linux/slab.h>
15 #include <linux/kallsyms.h> 15 #include <linux/kallsyms.h>
16 16
17 #include <asm/uaccess.h> 17 #include <asm/uaccess.h>
18 #include <asm/assembly.h> 18 #include <asm/assembly.h>
19 #include <asm/asm-offsets.h> 19 #include <asm/asm-offsets.h>
20 #include <asm/ptrace.h> 20 #include <asm/ptrace.h>
21 21
22 #include <asm/unwind.h> 22 #include <asm/unwind.h>
23 23
24 /* #define DEBUG 1 */ 24 /* #define DEBUG 1 */
25 #ifdef DEBUG 25 #ifdef DEBUG
26 #define dbg(x...) printk(x) 26 #define dbg(x...) printk(x)
27 #else 27 #else
28 #define dbg(x...) 28 #define dbg(x...)
29 #endif 29 #endif
30 30
31 #define KERNEL_START (KERNEL_BINARY_TEXT_START - 0x1000) 31 #define KERNEL_START (KERNEL_BINARY_TEXT_START - 0x1000)
32 32
33 extern struct unwind_table_entry __start___unwind[]; 33 extern struct unwind_table_entry __start___unwind[];
34 extern struct unwind_table_entry __stop___unwind[]; 34 extern struct unwind_table_entry __stop___unwind[];
35 35
36 static spinlock_t unwind_lock; 36 static spinlock_t unwind_lock;
37 /* 37 /*
38 * the kernel unwind block is not dynamically allocated so that 38 * the kernel unwind block is not dynamically allocated so that
39 * we can call unwind_init as early in the bootup process as 39 * we can call unwind_init as early in the bootup process as
40 * possible (before the slab allocator is initialized) 40 * possible (before the slab allocator is initialized)
41 */ 41 */
42 static struct unwind_table kernel_unwind_table __read_mostly; 42 static struct unwind_table kernel_unwind_table __read_mostly;
43 static LIST_HEAD(unwind_tables); 43 static LIST_HEAD(unwind_tables);
44 44
45 static inline const struct unwind_table_entry * 45 static inline const struct unwind_table_entry *
46 find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr) 46 find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
47 { 47 {
48 const struct unwind_table_entry *e = NULL; 48 const struct unwind_table_entry *e = NULL;
49 unsigned long lo, hi, mid; 49 unsigned long lo, hi, mid;
50 50
51 lo = 0; 51 lo = 0;
52 hi = table->length - 1; 52 hi = table->length - 1;
53 53
54 while (lo <= hi) { 54 while (lo <= hi) {
55 mid = (hi - lo) / 2 + lo; 55 mid = (hi - lo) / 2 + lo;
56 e = &table->table[mid]; 56 e = &table->table[mid];
57 if (addr < e->region_start) 57 if (addr < e->region_start)
58 hi = mid - 1; 58 hi = mid - 1;
59 else if (addr > e->region_end) 59 else if (addr > e->region_end)
60 lo = mid + 1; 60 lo = mid + 1;
61 else 61 else
62 return e; 62 return e;
63 } 63 }
64 64
65 return NULL; 65 return NULL;
66 } 66 }
67 67
68 static const struct unwind_table_entry * 68 static const struct unwind_table_entry *
69 find_unwind_entry(unsigned long addr) 69 find_unwind_entry(unsigned long addr)
70 { 70 {
71 struct unwind_table *table; 71 struct unwind_table *table;
72 const struct unwind_table_entry *e = NULL; 72 const struct unwind_table_entry *e = NULL;
73 73
74 if (addr >= kernel_unwind_table.start && 74 if (addr >= kernel_unwind_table.start &&
75 addr <= kernel_unwind_table.end) 75 addr <= kernel_unwind_table.end)
76 e = find_unwind_entry_in_table(&kernel_unwind_table, addr); 76 e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
77 else 77 else
78 list_for_each_entry(table, &unwind_tables, list) { 78 list_for_each_entry(table, &unwind_tables, list) {
79 if (addr >= table->start && 79 if (addr >= table->start &&
80 addr <= table->end) 80 addr <= table->end)
81 e = find_unwind_entry_in_table(table, addr); 81 e = find_unwind_entry_in_table(table, addr);
82 if (e) 82 if (e)
83 break; 83 break;
84 } 84 }
85 85
86 return e; 86 return e;
87 } 87 }
88 88
89 static void 89 static void
90 unwind_table_init(struct unwind_table *table, const char *name, 90 unwind_table_init(struct unwind_table *table, const char *name,
91 unsigned long base_addr, unsigned long gp, 91 unsigned long base_addr, unsigned long gp,
92 void *table_start, void *table_end) 92 void *table_start, void *table_end)
93 { 93 {
94 struct unwind_table_entry *start = table_start; 94 struct unwind_table_entry *start = table_start;
95 struct unwind_table_entry *end = 95 struct unwind_table_entry *end =
96 (struct unwind_table_entry *)table_end - 1; 96 (struct unwind_table_entry *)table_end - 1;
97 97
98 table->name = name; 98 table->name = name;
99 table->base_addr = base_addr; 99 table->base_addr = base_addr;
100 table->gp = gp; 100 table->gp = gp;
101 table->start = base_addr + start->region_start; 101 table->start = base_addr + start->region_start;
102 table->end = base_addr + end->region_end; 102 table->end = base_addr + end->region_end;
103 table->table = (struct unwind_table_entry *)table_start; 103 table->table = (struct unwind_table_entry *)table_start;
104 table->length = end - start + 1; 104 table->length = end - start + 1;
105 INIT_LIST_HEAD(&table->list); 105 INIT_LIST_HEAD(&table->list);
106 106
107 for (; start <= end; start++) { 107 for (; start <= end; start++) {
108 if (start < end && 108 if (start < end &&
109 start->region_end > (start+1)->region_start) { 109 start->region_end > (start+1)->region_start) {
110 printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1); 110 printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1);
111 } 111 }
112 112
113 start->region_start += base_addr; 113 start->region_start += base_addr;
114 start->region_end += base_addr; 114 start->region_end += base_addr;
115 } 115 }
116 } 116 }
117 117
118 static void 118 static void
119 unwind_table_sort(struct unwind_table_entry *start, 119 unwind_table_sort(struct unwind_table_entry *start,
120 struct unwind_table_entry *finish) 120 struct unwind_table_entry *finish)
121 { 121 {
122 struct unwind_table_entry el, *p, *q; 122 struct unwind_table_entry el, *p, *q;
123 123
124 for (p = start + 1; p < finish; ++p) { 124 for (p = start + 1; p < finish; ++p) {
125 if (p[0].region_start < p[-1].region_start) { 125 if (p[0].region_start < p[-1].region_start) {
126 el = *p; 126 el = *p;
127 q = p; 127 q = p;
128 do { 128 do {
129 q[0] = q[-1]; 129 q[0] = q[-1];
130 --q; 130 --q;
131 } while (q > start && 131 } while (q > start &&
132 el.region_start < q[-1].region_start); 132 el.region_start < q[-1].region_start);
133 *q = el; 133 *q = el;
134 } 134 }
135 } 135 }
136 } 136 }
137 137
138 struct unwind_table * 138 struct unwind_table *
139 unwind_table_add(const char *name, unsigned long base_addr, 139 unwind_table_add(const char *name, unsigned long base_addr,
140 unsigned long gp, 140 unsigned long gp,
141 void *start, void *end) 141 void *start, void *end)
142 { 142 {
143 struct unwind_table *table; 143 struct unwind_table *table;
144 unsigned long flags; 144 unsigned long flags;
145 struct unwind_table_entry *s = (struct unwind_table_entry *)start; 145 struct unwind_table_entry *s = (struct unwind_table_entry *)start;
146 struct unwind_table_entry *e = (struct unwind_table_entry *)end; 146 struct unwind_table_entry *e = (struct unwind_table_entry *)end;
147 147
148 unwind_table_sort(s, e); 148 unwind_table_sort(s, e);
149 149
150 table = kmalloc(sizeof(struct unwind_table), GFP_USER); 150 table = kmalloc(sizeof(struct unwind_table), GFP_USER);
151 if (table == NULL) 151 if (table == NULL)
152 return NULL; 152 return NULL;
153 unwind_table_init(table, name, base_addr, gp, start, end); 153 unwind_table_init(table, name, base_addr, gp, start, end);
154 spin_lock_irqsave(&unwind_lock, flags); 154 spin_lock_irqsave(&unwind_lock, flags);
155 list_add_tail(&table->list, &unwind_tables); 155 list_add_tail(&table->list, &unwind_tables);
156 spin_unlock_irqrestore(&unwind_lock, flags); 156 spin_unlock_irqrestore(&unwind_lock, flags);
157 157
158 return table; 158 return table;
159 } 159 }
160 160
161 void unwind_table_remove(struct unwind_table *table) 161 void unwind_table_remove(struct unwind_table *table)
162 { 162 {
163 unsigned long flags; 163 unsigned long flags;
164 164
165 spin_lock_irqsave(&unwind_lock, flags); 165 spin_lock_irqsave(&unwind_lock, flags);
166 list_del(&table->list); 166 list_del(&table->list);
167 spin_unlock_irqrestore(&unwind_lock, flags); 167 spin_unlock_irqrestore(&unwind_lock, flags);
168 168
169 kfree(table); 169 kfree(table);
170 } 170 }
171 171
172 /* Called from setup_arch to import the kernel unwind info */ 172 /* Called from setup_arch to import the kernel unwind info */
173 static int unwind_init(void) 173 int unwind_init(void)
174 { 174 {
175 long start, stop; 175 long start, stop;
176 register unsigned long gp __asm__ ("r27"); 176 register unsigned long gp __asm__ ("r27");
177 177
178 start = (long)&__start___unwind[0]; 178 start = (long)&__start___unwind[0];
179 stop = (long)&__stop___unwind[0]; 179 stop = (long)&__stop___unwind[0];
180 180
181 spin_lock_init(&unwind_lock); 181 spin_lock_init(&unwind_lock);
182 182
183 printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n", 183 printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
184 start, stop, 184 start, stop,
185 (stop - start) / sizeof(struct unwind_table_entry)); 185 (stop - start) / sizeof(struct unwind_table_entry));
186 186
187 unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START, 187 unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
188 gp, 188 gp,
189 &__start___unwind[0], &__stop___unwind[0]); 189 &__start___unwind[0], &__stop___unwind[0]);
190 #if 0 190 #if 0
191 { 191 {
192 int i; 192 int i;
193 for (i = 0; i < 10; i++) 193 for (i = 0; i < 10; i++)
194 { 194 {
195 printk("region 0x%x-0x%x\n", 195 printk("region 0x%x-0x%x\n",
196 __start___unwind[i].region_start, 196 __start___unwind[i].region_start,
197 __start___unwind[i].region_end); 197 __start___unwind[i].region_end);
198 } 198 }
199 } 199 }
200 #endif 200 #endif
201 return 0; 201 return 0;
202 } 202 }
203 203
204 #ifdef CONFIG_64BIT 204 #ifdef CONFIG_64BIT
205 #define get_func_addr(fptr) fptr[2] 205 #define get_func_addr(fptr) fptr[2]
206 #else 206 #else
207 #define get_func_addr(fptr) fptr[0] 207 #define get_func_addr(fptr) fptr[0]
208 #endif 208 #endif
209 209
210 static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size) 210 static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
211 { 211 {
212 extern void handle_interruption(int, struct pt_regs *); 212 extern void handle_interruption(int, struct pt_regs *);
213 static unsigned long *hi = (unsigned long *)&handle_interruption; 213 static unsigned long *hi = (unsigned long *)&handle_interruption;
214 214
215 if (pc == get_func_addr(hi)) { 215 if (pc == get_func_addr(hi)) {
216 struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); 216 struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
217 dbg("Unwinding through handle_interruption()\n"); 217 dbg("Unwinding through handle_interruption()\n");
218 info->prev_sp = regs->gr[30]; 218 info->prev_sp = regs->gr[30];
219 info->prev_ip = regs->iaoq[0]; 219 info->prev_ip = regs->iaoq[0];
220 220
221 return 1; 221 return 1;
222 } 222 }
223 223
224 return 0; 224 return 0;
225 } 225 }
226 226
227 static void unwind_frame_regs(struct unwind_frame_info *info) 227 static void unwind_frame_regs(struct unwind_frame_info *info)
228 { 228 {
229 const struct unwind_table_entry *e; 229 const struct unwind_table_entry *e;
230 unsigned long npc; 230 unsigned long npc;
231 unsigned int insn; 231 unsigned int insn;
232 long frame_size = 0; 232 long frame_size = 0;
233 int looking_for_rp, rpoffset = 0; 233 int looking_for_rp, rpoffset = 0;
234 234
235 e = find_unwind_entry(info->ip); 235 e = find_unwind_entry(info->ip);
236 if (e == NULL) { 236 if (e == NULL) {
237 unsigned long sp; 237 unsigned long sp;
238 extern char _stext[], _etext[]; 238 extern char _stext[], _etext[];
239 239
240 dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip); 240 dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
241 241
242 #ifdef CONFIG_KALLSYMS 242 #ifdef CONFIG_KALLSYMS
243 /* Handle some frequent special cases.... */ 243 /* Handle some frequent special cases.... */
244 { 244 {
245 char symname[KSYM_NAME_LEN]; 245 char symname[KSYM_NAME_LEN];
246 char *modname; 246 char *modname;
247 247
248 kallsyms_lookup(info->ip, NULL, NULL, &modname, 248 kallsyms_lookup(info->ip, NULL, NULL, &modname,
249 symname); 249 symname);
250 250
251 dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname); 251 dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname);
252 252
253 if (strcmp(symname, "_switch_to_ret") == 0) { 253 if (strcmp(symname, "_switch_to_ret") == 0) {
254 info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; 254 info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
255 info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); 255 info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
256 dbg("_switch_to_ret @ %lx - setting " 256 dbg("_switch_to_ret @ %lx - setting "
257 "prev_sp=%lx prev_ip=%lx\n", 257 "prev_sp=%lx prev_ip=%lx\n",
258 info->ip, info->prev_sp, 258 info->ip, info->prev_sp,
259 info->prev_ip); 259 info->prev_ip);
260 return; 260 return;
261 } else if (strcmp(symname, "ret_from_kernel_thread") == 0 || 261 } else if (strcmp(symname, "ret_from_kernel_thread") == 0 ||
262 strcmp(symname, "syscall_exit") == 0) { 262 strcmp(symname, "syscall_exit") == 0) {
263 info->prev_ip = info->prev_sp = 0; 263 info->prev_ip = info->prev_sp = 0;
264 return; 264 return;
265 } 265 }
266 } 266 }
267 #endif 267 #endif
268 268
269 /* Since we are doing the unwinding blind, we don't know if 269 /* Since we are doing the unwinding blind, we don't know if
270 we are adjusting the stack correctly or extracting the rp 270 we are adjusting the stack correctly or extracting the rp
271 correctly. The rp is checked to see if it belongs to the 271 correctly. The rp is checked to see if it belongs to the
272 kernel text section, if not we assume we don't have a 272 kernel text section, if not we assume we don't have a
273 correct stack frame and we continue to unwind the stack. 273 correct stack frame and we continue to unwind the stack.
274 This is not quite correct, and will fail for loadable 274 This is not quite correct, and will fail for loadable
275 modules. */ 275 modules. */
276 sp = info->sp & ~63; 276 sp = info->sp & ~63;
277 do { 277 do {
278 unsigned long tmp; 278 unsigned long tmp;
279 279
280 info->prev_sp = sp - 64; 280 info->prev_sp = sp - 64;
281 info->prev_ip = 0; 281 info->prev_ip = 0;
282 if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) 282 if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET)))
283 break; 283 break;
284 info->prev_ip = tmp; 284 info->prev_ip = tmp;
285 sp = info->prev_sp; 285 sp = info->prev_sp;
286 } while (info->prev_ip < (unsigned long)_stext || 286 } while (info->prev_ip < (unsigned long)_stext ||
287 info->prev_ip > (unsigned long)_etext); 287 info->prev_ip > (unsigned long)_etext);
288 288
289 info->rp = 0; 289 info->rp = 0;
290 290
291 dbg("analyzing func @ %lx with no unwind info, setting " 291 dbg("analyzing func @ %lx with no unwind info, setting "
292 "prev_sp=%lx prev_ip=%lx\n", info->ip, 292 "prev_sp=%lx prev_ip=%lx\n", info->ip,
293 info->prev_sp, info->prev_ip); 293 info->prev_sp, info->prev_ip);
294 } else { 294 } else {
295 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, " 295 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
296 "Save_RP = %d, Millicode = %d size = %u\n", 296 "Save_RP = %d, Millicode = %d size = %u\n",
297 e->region_start, e->region_end, e->Save_SP, e->Save_RP, 297 e->region_start, e->region_end, e->Save_SP, e->Save_RP,
298 e->Millicode, e->Total_frame_size); 298 e->Millicode, e->Total_frame_size);
299 299
300 looking_for_rp = e->Save_RP; 300 looking_for_rp = e->Save_RP;
301 301
302 for (npc = e->region_start; 302 for (npc = e->region_start;
303 (frame_size < (e->Total_frame_size << 3) || 303 (frame_size < (e->Total_frame_size << 3) ||
304 looking_for_rp) && 304 looking_for_rp) &&
305 npc < info->ip; 305 npc < info->ip;
306 npc += 4) { 306 npc += 4) {
307 307
308 insn = *(unsigned int *)npc; 308 insn = *(unsigned int *)npc;
309 309
310 if ((insn & 0xffffc000) == 0x37de0000 || 310 if ((insn & 0xffffc000) == 0x37de0000 ||
311 (insn & 0xffe00000) == 0x6fc00000) { 311 (insn & 0xffe00000) == 0x6fc00000) {
312 /* ldo X(sp), sp, or stwm X,D(sp) */ 312 /* ldo X(sp), sp, or stwm X,D(sp) */
313 frame_size += (insn & 0x1 ? -1 << 13 : 0) | 313 frame_size += (insn & 0x1 ? -1 << 13 : 0) |
314 ((insn & 0x3fff) >> 1); 314 ((insn & 0x3fff) >> 1);
315 dbg("analyzing func @ %lx, insn=%08x @ " 315 dbg("analyzing func @ %lx, insn=%08x @ "
316 "%lx, frame_size = %ld\n", info->ip, 316 "%lx, frame_size = %ld\n", info->ip,
317 insn, npc, frame_size); 317 insn, npc, frame_size);
318 } else if ((insn & 0xffe00008) == 0x73c00008) { 318 } else if ((insn & 0xffe00008) == 0x73c00008) {
319 /* std,ma X,D(sp) */ 319 /* std,ma X,D(sp) */
320 frame_size += (insn & 0x1 ? -1 << 13 : 0) | 320 frame_size += (insn & 0x1 ? -1 << 13 : 0) |
321 (((insn >> 4) & 0x3ff) << 3); 321 (((insn >> 4) & 0x3ff) << 3);
322 dbg("analyzing func @ %lx, insn=%08x @ " 322 dbg("analyzing func @ %lx, insn=%08x @ "
323 "%lx, frame_size = %ld\n", info->ip, 323 "%lx, frame_size = %ld\n", info->ip,
324 insn, npc, frame_size); 324 insn, npc, frame_size);
325 } else if (insn == 0x6bc23fd9) { 325 } else if (insn == 0x6bc23fd9) {
326 /* stw rp,-20(sp) */ 326 /* stw rp,-20(sp) */
327 rpoffset = 20; 327 rpoffset = 20;
328 looking_for_rp = 0; 328 looking_for_rp = 0;
329 dbg("analyzing func @ %lx, insn=stw rp," 329 dbg("analyzing func @ %lx, insn=stw rp,"
330 "-20(sp) @ %lx\n", info->ip, npc); 330 "-20(sp) @ %lx\n", info->ip, npc);
331 } else if (insn == 0x0fc212c1) { 331 } else if (insn == 0x0fc212c1) {
332 /* std rp,-16(sr0,sp) */ 332 /* std rp,-16(sr0,sp) */
333 rpoffset = 16; 333 rpoffset = 16;
334 looking_for_rp = 0; 334 looking_for_rp = 0;
335 dbg("analyzing func @ %lx, insn=std rp," 335 dbg("analyzing func @ %lx, insn=std rp,"
336 "-16(sp) @ %lx\n", info->ip, npc); 336 "-16(sp) @ %lx\n", info->ip, npc);
337 } 337 }
338 } 338 }
339 339
340 if (!unwind_special(info, e->region_start, frame_size)) { 340 if (!unwind_special(info, e->region_start, frame_size)) {
341 info->prev_sp = info->sp - frame_size; 341 info->prev_sp = info->sp - frame_size;
342 if (e->Millicode) 342 if (e->Millicode)
343 info->rp = info->r31; 343 info->rp = info->r31;
344 else if (rpoffset) 344 else if (rpoffset)
345 info->rp = *(unsigned long *)(info->prev_sp - rpoffset); 345 info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
346 info->prev_ip = info->rp; 346 info->prev_ip = info->rp;
347 info->rp = 0; 347 info->rp = 0;
348 } 348 }
349 349
350 dbg("analyzing func @ %lx, setting prev_sp=%lx " 350 dbg("analyzing func @ %lx, setting prev_sp=%lx "
351 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, 351 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
352 info->prev_ip, npc); 352 info->prev_ip, npc);
353 } 353 }
354 } 354 }
355 355
356 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 356 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
357 struct pt_regs *regs) 357 struct pt_regs *regs)
358 { 358 {
359 memset(info, 0, sizeof(struct unwind_frame_info)); 359 memset(info, 0, sizeof(struct unwind_frame_info));
360 info->t = t; 360 info->t = t;
361 info->sp = regs->gr[30]; 361 info->sp = regs->gr[30];
362 info->ip = regs->iaoq[0]; 362 info->ip = regs->iaoq[0];
363 info->rp = regs->gr[2]; 363 info->rp = regs->gr[2];
364 info->r31 = regs->gr[31]; 364 info->r31 = regs->gr[31];
365 365
366 dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", 366 dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
367 t ? (int)t->pid : -1, info->sp, info->ip); 367 t ? (int)t->pid : -1, info->sp, info->ip);
368 } 368 }
369 369
370 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t) 370 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
371 { 371 {
372 struct pt_regs *r = &t->thread.regs; 372 struct pt_regs *r = &t->thread.regs;
373 struct pt_regs *r2; 373 struct pt_regs *r2;
374 374
375 r2 = kmalloc(sizeof(struct pt_regs), GFP_KERNEL); 375 r2 = kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
376 if (!r2) 376 if (!r2)
377 return; 377 return;
378 *r2 = *r; 378 *r2 = *r;
379 r2->gr[30] = r->ksp; 379 r2->gr[30] = r->ksp;
380 r2->iaoq[0] = r->kpc; 380 r2->iaoq[0] = r->kpc;
381 unwind_frame_init(info, t, r2); 381 unwind_frame_init(info, t, r2);
382 kfree(r2); 382 kfree(r2);
383 } 383 }
384 384
385 void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs) 385 void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs)
386 { 386 {
387 unwind_frame_init(info, current, regs); 387 unwind_frame_init(info, current, regs);
388 } 388 }
389 389
390 int unwind_once(struct unwind_frame_info *next_frame) 390 int unwind_once(struct unwind_frame_info *next_frame)
391 { 391 {
392 unwind_frame_regs(next_frame); 392 unwind_frame_regs(next_frame);
393 393
394 if (next_frame->prev_sp == 0 || 394 if (next_frame->prev_sp == 0 ||
395 next_frame->prev_ip == 0) 395 next_frame->prev_ip == 0)
396 return -1; 396 return -1;
397 397
398 next_frame->sp = next_frame->prev_sp; 398 next_frame->sp = next_frame->prev_sp;
399 next_frame->ip = next_frame->prev_ip; 399 next_frame->ip = next_frame->prev_ip;
400 next_frame->prev_sp = 0; 400 next_frame->prev_sp = 0;
401 next_frame->prev_ip = 0; 401 next_frame->prev_ip = 0;
402 402
403 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", 403 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n",
404 next_frame->t ? (int)next_frame->t->pid : -1, 404 next_frame->t ? (int)next_frame->t->pid : -1,
405 next_frame->sp, next_frame->ip); 405 next_frame->sp, next_frame->ip);
406 406
407 return 0; 407 return 0;
408 } 408 }
409 409
410 int unwind_to_user(struct unwind_frame_info *info) 410 int unwind_to_user(struct unwind_frame_info *info)
411 { 411 {
412 int ret; 412 int ret;
413 413
414 do { 414 do {
415 ret = unwind_once(info); 415 ret = unwind_once(info);
416 } while (!ret && !(info->ip & 3)); 416 } while (!ret && !(info->ip & 3));
417 417
418 return ret; 418 return ret;
419 } 419 }
420
421 module_init(unwind_init);
422 420