| .. | .. |
|---|
| 154 | 154 | static void microblaze_unwind_inner(struct task_struct *task, |
|---|
| 155 | 155 | unsigned long pc, unsigned long fp, |
|---|
| 156 | 156 | unsigned long leaf_return, |
|---|
| 157 | | - struct stack_trace *trace); |
|---|
| 157 | + struct stack_trace *trace, |
|---|
| 158 | + const char *loglvl); |
|---|
| 158 | 159 | |
|---|
| 159 | 160 | /** |
|---|
| 160 | 161 | * unwind_trap - Unwind through a system trap, that stored previous state |
|---|
| .. | .. |
|---|
| 162 | 163 | */ |
|---|
| 163 | 164 | #ifdef CONFIG_MMU |
|---|
| 164 | 165 | static inline void unwind_trap(struct task_struct *task, unsigned long pc, |
|---|
| 165 | | - unsigned long fp, struct stack_trace *trace) |
|---|
| 166 | + unsigned long fp, struct stack_trace *trace, |
|---|
| 167 | + const char *loglvl) |
|---|
| 166 | 168 | { |
|---|
| 167 | 169 | /* To be implemented */ |
|---|
| 168 | 170 | } |
|---|
| 169 | 171 | #else |
|---|
| 170 | 172 | static inline void unwind_trap(struct task_struct *task, unsigned long pc, |
|---|
| 171 | | - unsigned long fp, struct stack_trace *trace) |
|---|
| 173 | + unsigned long fp, struct stack_trace *trace, |
|---|
| 174 | + const char *loglvl) |
|---|
| 172 | 175 | { |
|---|
| 173 | 176 | const struct pt_regs *regs = (const struct pt_regs *) fp; |
|---|
| 174 | | - microblaze_unwind_inner(task, regs->pc, regs->r1, regs->r15, trace); |
|---|
| 177 | + microblaze_unwind_inner(task, regs->pc, regs->r1, regs->r15, trace, loglvl); |
|---|
| 175 | 178 | } |
|---|
| 176 | 179 | #endif |
|---|
| 177 | 180 | |
|---|
| .. | .. |
|---|
| 184 | 187 | * the caller's return address. |
|---|
| 185 | 188 | * @trace : Where to store stack backtrace (PC values). |
|---|
| 186 | 189 | * NULL == print backtrace to kernel log |
|---|
| 190 | + * @loglvl : Used for printk log level if (trace == NULL). |
|---|
| 187 | 191 | */ |
|---|
| 188 | 192 | static void microblaze_unwind_inner(struct task_struct *task, |
|---|
| 189 | 193 | unsigned long pc, unsigned long fp, |
|---|
| 190 | 194 | unsigned long leaf_return, |
|---|
| 191 | | - struct stack_trace *trace) |
|---|
| 195 | + struct stack_trace *trace, |
|---|
| 196 | + const char *loglvl) |
|---|
| 192 | 197 | { |
|---|
| 193 | 198 | int ofs = 0; |
|---|
| 194 | 199 | |
|---|
| .. | .. |
|---|
| 214 | 219 | const struct pt_regs *regs = |
|---|
| 215 | 220 | (const struct pt_regs *) fp; |
|---|
| 216 | 221 | #endif |
|---|
| 217 | | - pr_info("HW EXCEPTION\n"); |
|---|
| 222 | + printk("%sHW EXCEPTION\n", loglvl); |
|---|
| 218 | 223 | #ifndef CONFIG_MMU |
|---|
| 219 | 224 | microblaze_unwind_inner(task, regs->r17 - 4, |
|---|
| 220 | 225 | fp + EX_HANDLER_STACK_SIZ, |
|---|
| 221 | | - regs->r15, trace); |
|---|
| 226 | + regs->r15, trace, loglvl); |
|---|
| 222 | 227 | #endif |
|---|
| 223 | 228 | return; |
|---|
| 224 | 229 | } |
|---|
| .. | .. |
|---|
| 228 | 233 | if ((return_to >= handler->start_addr) |
|---|
| 229 | 234 | && (return_to <= handler->end_addr)) { |
|---|
| 230 | 235 | if (!trace) |
|---|
| 231 | | - pr_info("%s\n", handler->trap_name); |
|---|
| 232 | | - unwind_trap(task, pc, fp, trace); |
|---|
| 236 | + printk("%s%s\n", loglvl, handler->trap_name); |
|---|
| 237 | + unwind_trap(task, pc, fp, trace, loglvl); |
|---|
| 233 | 238 | return; |
|---|
| 234 | 239 | } |
|---|
| 235 | 240 | } |
|---|
| .. | .. |
|---|
| 248 | 253 | } else { |
|---|
| 249 | 254 | /* Have we reached userland? */ |
|---|
| 250 | 255 | if (unlikely(pc == task_pt_regs(task)->pc)) { |
|---|
| 251 | | - pr_info("[<%p>] PID %lu [%s]\n", |
|---|
| 252 | | - (void *) pc, |
|---|
| 256 | + printk("%s[<%p>] PID %lu [%s]\n", |
|---|
| 257 | + loglvl, (void *) pc, |
|---|
| 253 | 258 | (unsigned long) task->pid, |
|---|
| 254 | 259 | task->comm); |
|---|
| 255 | 260 | break; |
|---|
| 256 | 261 | } else |
|---|
| 257 | | - print_ip_sym(pc); |
|---|
| 262 | + print_ip_sym(loglvl, pc); |
|---|
| 258 | 263 | } |
|---|
| 259 | 264 | |
|---|
| 260 | 265 | /* Stop when we reach anything not part of the kernel */ |
|---|
| .. | .. |
|---|
| 282 | 287 | * @task : Task whose stack we are to unwind (NULL == current) |
|---|
| 283 | 288 | * @trace : Where to store stack backtrace (PC values). |
|---|
| 284 | 289 | * NULL == print backtrace to kernel log |
|---|
| 290 | + * @loglvl : Used for printk log level if (trace == NULL). |
|---|
| 285 | 291 | */ |
|---|
| 286 | | -void microblaze_unwind(struct task_struct *task, struct stack_trace *trace) |
|---|
| 292 | +void microblaze_unwind(struct task_struct *task, struct stack_trace *trace, |
|---|
| 293 | + const char *loglvl) |
|---|
| 287 | 294 | { |
|---|
| 288 | 295 | if (task) { |
|---|
| 289 | 296 | if (task == current) { |
|---|
| 290 | 297 | const struct pt_regs *regs = task_pt_regs(task); |
|---|
| 291 | 298 | microblaze_unwind_inner(task, regs->pc, regs->r1, |
|---|
| 292 | | - regs->r15, trace); |
|---|
| 299 | + regs->r15, trace, loglvl); |
|---|
| 293 | 300 | } else { |
|---|
| 294 | 301 | struct thread_info *thread_info = |
|---|
| 295 | 302 | (struct thread_info *)(task->stack); |
|---|
| .. | .. |
|---|
| 299 | 306 | microblaze_unwind_inner(task, |
|---|
| 300 | 307 | (unsigned long) &_switch_to, |
|---|
| 301 | 308 | cpu_context->r1, |
|---|
| 302 | | - cpu_context->r15, trace); |
|---|
| 309 | + cpu_context->r15, |
|---|
| 310 | + trace, loglvl); |
|---|
| 303 | 311 | } |
|---|
| 304 | 312 | } else { |
|---|
| 305 | 313 | unsigned long pc, fp; |
|---|
| .. | .. |
|---|
| 314 | 322 | ); |
|---|
| 315 | 323 | |
|---|
| 316 | 324 | /* Since we are not a leaf function, use leaf_return = 0 */ |
|---|
| 317 | | - microblaze_unwind_inner(current, pc, fp, 0, trace); |
|---|
| 325 | + microblaze_unwind_inner(current, pc, fp, 0, trace, loglvl); |
|---|
| 318 | 326 | } |
|---|
| 319 | 327 | } |
|---|
| 320 | 328 | |
|---|