]>
Commit | Line | Data |
---|---|---|
51533b61 MS |
1 | /* |
2 | * Copyright (C) 2000-2003 Axis Communications AB | |
3 | * | |
4 | * Authors: Bjorn Wesen (bjornw@axis.com) | |
5 | * Mikael Starvik (starvik@axis.com) | |
6 | * Tobias Anderberg (tobiasa@axis.com), CRISv32 port. | |
7 | * | |
8 | * This file handles the architecture-dependent parts of process handling.. | |
9 | */ | |
10 | ||
51533b61 | 11 | #include <linux/sched.h> |
b17b0153 | 12 | #include <linux/sched/debug.h> |
29930025 | 13 | #include <linux/sched/task.h> |
68db0cf1 | 14 | #include <linux/sched/task_stack.h> |
5a0e3ad6 | 15 | #include <linux/slab.h> |
51533b61 MS |
16 | #include <linux/err.h> |
17 | #include <linux/fs.h> | |
8cca29b7 JN |
18 | #include <hwregs/reg_rdwr.h> |
19 | #include <hwregs/reg_map.h> | |
20 | #include <hwregs/timer_defs.h> | |
21 | #include <hwregs/intr_vect_defs.h> | |
27d892fb | 22 | #include <linux/ptrace.h> |
51533b61 MS |
23 | |
24 | extern void stop_watchdog(void); | |
25 | ||
51533b61 MS |
26 | /* We use this if we don't have any better idle routine. */ |
27 | void default_idle(void) | |
28 | { | |
3fffa23e | 29 | local_irq_enable(); |
8dc7c5ec | 30 | /* Halt until exception. */ |
3fffa23e | 31 | __asm__ volatile("halt"); |
51533b61 MS |
32 | } |
33 | ||
34 | /* | |
35 | * Free current thread data structures etc.. | |
36 | */ | |
37 | ||
38 | extern void deconfigure_bp(long pid); | |
e6464694 | 39 | void exit_thread(struct task_struct *tsk) |
51533b61 | 40 | { |
e6464694 | 41 | deconfigure_bp(tsk->pid); |
51533b61 MS |
42 | } |
43 | ||
44 | /* | |
45 | * If the watchdog is enabled, disable interrupts and enter an infinite loop. | |
46 | * The watchdog will reset the CPU after 0.1s. If the watchdog isn't enabled | |
47 | * then enable it and wait. | |
48 | */ | |
49 | extern void arch_enable_nmi(void); | |
50 | ||
51 | void | |
52 | hard_reset_now(void) | |
53 | { | |
54 | /* | |
55 | * Don't declare this variable elsewhere. We don't want any other | |
56 | * code to know about it than the watchdog handler in entry.S and | |
57 | * this code, implementing hard reset through the watchdog. | |
58 | */ | |
59 | #if defined(CONFIG_ETRAX_WATCHDOG) | |
60 | extern int cause_of_death; | |
61 | #endif | |
62 | ||
63 | printk("*** HARD RESET ***\n"); | |
64 | local_irq_disable(); | |
65 | ||
66 | #if defined(CONFIG_ETRAX_WATCHDOG) | |
67 | cause_of_death = 0xbedead; | |
68 | #else | |
69 | { | |
70 | reg_timer_rw_wd_ctrl wd_ctrl = {0}; | |
71 | ||
72 | stop_watchdog(); | |
73 | ||
74 | wd_ctrl.key = 16; /* Arbitrary key. */ | |
75 | wd_ctrl.cnt = 1; /* Minimum time. */ | |
76 | wd_ctrl.cmd = regk_timer_start; | |
77 | ||
78 | arch_enable_nmi(); | |
8cca29b7 | 79 | REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl); |
51533b61 MS |
80 | } |
81 | #endif | |
82 | ||
83 | while (1) | |
84 | ; /* Wait for reset. */ | |
85 | } | |
86 | ||
87 | /* | |
88 | * Return saved PC of a blocked thread. | |
89 | */ | |
90 | unsigned long thread_saved_pc(struct task_struct *t) | |
91 | { | |
95ca0dc6 | 92 | return task_pt_regs(t)->erp; |
51533b61 MS |
93 | } |
94 | ||
51533b61 MS |
95 | /* |
96 | * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. | |
97 | * It will be unnested during _resume and _ret_from_sys_call when the new thread | |
98 | * is scheduled. | |
99 | * | |
100 | * Also setup the thread switching structure which is used to keep | |
101 | * thread-specific data during _resumes. | |
102 | */ | |
103 | ||
104 | extern asmlinkage void ret_from_fork(void); | |
69b58a67 | 105 | extern asmlinkage void ret_from_kernel_thread(void); |
51533b61 MS |
106 | |
107 | int | |
6f2c55b8 | 108 | copy_thread(unsigned long clone_flags, unsigned long usp, |
afa86fc4 | 109 | unsigned long arg, struct task_struct *p) |
51533b61 | 110 | { |
69b58a67 AV |
111 | struct pt_regs *childregs = task_pt_regs(p); |
112 | struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; | |
51533b61 MS |
113 | |
114 | /* | |
115 | * Put the pt_regs structure at the end of the new kernel stack page and | |
116 | * fix it up. Note: the task_struct doubles as the kernel stack for the | |
117 | * task. | |
118 | */ | |
69b58a67 AV |
119 | if (unlikely(p->flags & PF_KTHREAD)) { |
120 | memset(swstack, 0, | |
121 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); | |
122 | swstack->r1 = usp; | |
123 | swstack->r2 = arg; | |
124 | childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); | |
125 | swstack->return_ip = (unsigned long) ret_from_kernel_thread; | |
126 | p->thread.ksp = (unsigned long) swstack; | |
127 | p->thread.usp = 0; | |
128 | return 0; | |
129 | } | |
27d892fb | 130 | *childregs = *current_pt_regs(); /* Struct copy of pt_regs. */ |
51533b61 MS |
131 | childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ |
132 | ||
133 | /* Set a new TLS ? | |
25985edc | 134 | * The TLS is in $mof because it is the 5th argument to sys_clone. |
51533b61 MS |
135 | */ |
136 | if (p->mm && (clone_flags & CLONE_SETTLS)) { | |
27d892fb | 137 | task_thread_info(p)->tls = childregs->mof; |
51533b61 MS |
138 | } |
139 | ||
140 | /* Put the switch stack right below the pt_regs. */ | |
51533b61 | 141 | |
49b4ff33 | 142 | /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ |
51533b61 MS |
143 | swstack->r9 = 0; |
144 | ||
145 | /* | |
146 | * We want to return into ret_from_sys_call after the _resume. | |
147 | * ret_from_fork will call ret_from_sys_call. | |
148 | */ | |
149 | swstack->return_ip = (unsigned long) ret_from_fork; | |
150 | ||
151 | /* Fix the user-mode and kernel-mode stackpointer. */ | |
27d892fb | 152 | p->thread.usp = usp ?: rdusp(); |
51533b61 MS |
153 | p->thread.ksp = (unsigned long) swstack; |
154 | ||
155 | return 0; | |
156 | } | |
157 | ||
51533b61 MS |
158 | unsigned long |
159 | get_wchan(struct task_struct *p) | |
160 | { | |
161 | /* TODO */ | |
162 | return 0; | |
163 | } | |
164 | #undef last_sched | |
165 | #undef first_sched | |
166 | ||
167 | void show_regs(struct pt_regs * regs) | |
168 | { | |
169 | unsigned long usp = rdusp(); | |
a43cb95d TH |
170 | |
171 | show_regs_print_info(KERN_DEFAULT); | |
172 | ||
51533b61 MS |
173 | printk("ERP: %08lx SRP: %08lx CCS: %08lx USP: %08lx MOF: %08lx\n", |
174 | regs->erp, regs->srp, regs->ccs, usp, regs->mof); | |
175 | ||
176 | printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", | |
177 | regs->r0, regs->r1, regs->r2, regs->r3); | |
178 | ||
179 | printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", | |
180 | regs->r4, regs->r5, regs->r6, regs->r7); | |
181 | ||
182 | printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", | |
183 | regs->r8, regs->r9, regs->r10, regs->r11); | |
184 | ||
185 | printk("r12: %08lx r13: %08lx oR10: %08lx\n", | |
186 | regs->r12, regs->r13, regs->orig_r10); | |
187 | } |