Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/alpha/kernel/process.c
26444 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* linux/arch/alpha/kernel/process.c
4
*
5
* Copyright (C) 1995 Linus Torvalds
6
*/
7
8
/*
9
* This file handles the architecture-dependent parts of process handling.
10
*/
11
12
#include <linux/cpu.h>
13
#include <linux/errno.h>
14
#include <linux/module.h>
15
#include <linux/sched.h>
16
#include <linux/sched/debug.h>
17
#include <linux/sched/task.h>
18
#include <linux/sched/task_stack.h>
19
#include <linux/kernel.h>
20
#include <linux/mm.h>
21
#include <linux/smp.h>
22
#include <linux/stddef.h>
23
#include <linux/unistd.h>
24
#include <linux/ptrace.h>
25
#include <linux/user.h>
26
#include <linux/time.h>
27
#include <linux/major.h>
28
#include <linux/stat.h>
29
#include <linux/vt.h>
30
#include <linux/mman.h>
31
#include <linux/elfcore.h>
32
#include <linux/reboot.h>
33
#include <linux/tty.h>
34
#include <linux/console.h>
35
#include <linux/slab.h>
36
#include <linux/rcupdate.h>
37
38
#include <asm/reg.h>
39
#include <linux/uaccess.h>
40
#include <asm/io.h>
41
#include <asm/hwrpb.h>
42
#include <asm/fpu.h>
43
44
#include "proto.h"
45
#include "pci_impl.h"
46
47
/*
48
* Power off function, if any
49
*/
50
void (*pm_power_off)(void) = machine_power_off;
51
EXPORT_SYMBOL(pm_power_off);
52
53
#ifdef CONFIG_ALPHA_WTINT
54
/*
55
* Sleep the CPU.
56
* EV6, LCA45 and QEMU know how to power down, skipping N timer interrupts.
57
*/
58
void arch_cpu_idle(void)
59
{
60
wtint(0);
61
}
62
63
void __noreturn arch_cpu_idle_dead(void)
64
{
65
wtint(INT_MAX);
66
BUG();
67
}
68
#endif /* ALPHA_WTINT */
69
70
struct halt_info {
71
int mode;
72
char *restart_cmd;
73
};
74
75
static void
76
common_shutdown_1(void *generic_ptr)
77
{
78
struct halt_info *how = generic_ptr;
79
struct percpu_struct *cpup;
80
unsigned long *pflags, flags;
81
int cpuid = smp_processor_id();
82
83
/* No point in taking interrupts anymore. */
84
local_irq_disable();
85
86
cpup = (struct percpu_struct *)
87
((unsigned long)hwrpb + hwrpb->processor_offset
88
+ hwrpb->processor_size * cpuid);
89
pflags = &cpup->flags;
90
flags = *pflags;
91
92
/* Clear reason to "default"; clear "bootstrap in progress". */
93
flags &= ~0x00ff0001UL;
94
95
#ifdef CONFIG_SMP
96
/* Secondaries halt here. */
97
if (cpuid != boot_cpuid) {
98
flags |= 0x00040000UL; /* "remain halted" */
99
*pflags = flags;
100
set_cpu_present(cpuid, false);
101
set_cpu_possible(cpuid, false);
102
halt();
103
}
104
#endif
105
106
if (how->mode == LINUX_REBOOT_CMD_RESTART) {
107
if (!how->restart_cmd) {
108
flags |= 0x00020000UL; /* "cold bootstrap" */
109
} else {
110
/* For SRM, we could probably set environment
111
variables to get this to work. We'd have to
112
delay this until after srm_paging_stop unless
113
we ever got srm_fixup working.
114
115
At the moment, SRM will use the last boot device,
116
but the file and flags will be the defaults, when
117
doing a "warm" bootstrap. */
118
flags |= 0x00030000UL; /* "warm bootstrap" */
119
}
120
} else {
121
flags |= 0x00040000UL; /* "remain halted" */
122
}
123
*pflags = flags;
124
125
#ifdef CONFIG_SMP
126
/* Wait for the secondaries to halt. */
127
set_cpu_present(boot_cpuid, false);
128
set_cpu_possible(boot_cpuid, false);
129
while (!cpumask_empty(cpu_present_mask))
130
barrier();
131
#endif
132
133
/* If booted from SRM, reset some of the original environment. */
134
if (alpha_using_srm) {
135
#ifdef CONFIG_DUMMY_CONSOLE
136
/* If we've gotten here after SysRq-b, leave interrupt
137
context before taking over the console. */
138
if (in_hardirq())
139
irq_exit();
140
/* This has the effect of resetting the VGA video origin. */
141
console_lock();
142
do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1);
143
console_unlock();
144
#endif
145
pci_restore_srm_config();
146
set_hae(srm_hae);
147
}
148
149
if (alpha_mv.kill_arch)
150
alpha_mv.kill_arch(how->mode);
151
152
if (! alpha_using_srm && how->mode != LINUX_REBOOT_CMD_RESTART) {
153
/* Unfortunately, since MILO doesn't currently understand
154
the hwrpb bits above, we can't reliably halt the
155
processor and keep it halted. So just loop. */
156
return;
157
}
158
159
if (alpha_using_srm)
160
srm_paging_stop();
161
162
halt();
163
}
164
165
static void
166
common_shutdown(int mode, char *restart_cmd)
167
{
168
struct halt_info args;
169
args.mode = mode;
170
args.restart_cmd = restart_cmd;
171
on_each_cpu(common_shutdown_1, &args, 0);
172
}
173
174
void
175
machine_restart(char *restart_cmd)
176
{
177
common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd);
178
}
179
180
181
void
182
machine_halt(void)
183
{
184
common_shutdown(LINUX_REBOOT_CMD_HALT, NULL);
185
}
186
187
188
void
189
machine_power_off(void)
190
{
191
common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
192
}
193
194
195
/* Used by sysrq-p, among others. I don't believe r9-r15 are ever
196
saved in the context it's used. */
197
198
void
199
show_regs(struct pt_regs *regs)
200
{
201
show_regs_print_info(KERN_DEFAULT);
202
dik_show_regs(regs, NULL);
203
}
204
205
/*
206
* Re-start a thread when doing execve()
207
*/
208
void
209
start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
210
{
211
regs->pc = pc;
212
regs->ps = 8;
213
wrusp(sp);
214
}
215
EXPORT_SYMBOL(start_thread);
216
217
void
218
flush_thread(void)
219
{
220
/* Arrange for each exec'ed process to start off with a clean slate
221
with respect to the FPU. This is all exceptions disabled. */
222
current_thread_info()->ieee_state = 0;
223
wrfpcr(FPCR_DYN_NORMAL | ieee_swcr_to_fpcr(0));
224
225
/* Clean slate for TLS. */
226
current_thread_info()->pcb.unique = 0;
227
}
228
229
/*
230
* Copy architecture-specific thread state
231
*/
232
int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
233
{
234
unsigned long clone_flags = args->flags;
235
unsigned long usp = args->stack;
236
unsigned long tls = args->tls;
237
extern void ret_from_fork(void);
238
extern void ret_from_kernel_thread(void);
239
240
struct thread_info *childti = task_thread_info(p);
241
struct pt_regs *childregs = task_pt_regs(p);
242
struct pt_regs *regs = current_pt_regs();
243
struct switch_stack *childstack, *stack;
244
245
childstack = ((struct switch_stack *) childregs) - 1;
246
childti->pcb.ksp = (unsigned long) childstack;
247
childti->pcb.flags = 1; /* set FEN, clear everything else */
248
childti->status |= TS_SAVED_FP | TS_RESTORE_FP;
249
250
if (unlikely(args->fn)) {
251
/* kernel thread */
252
memset(childstack, 0,
253
sizeof(struct switch_stack) + sizeof(struct pt_regs));
254
childstack->r26 = (unsigned long) ret_from_kernel_thread;
255
childstack->r9 = (unsigned long) args->fn;
256
childstack->r10 = (unsigned long) args->fn_arg;
257
childregs->hae = alpha_mv.hae_cache;
258
memset(childti->fp, '\0', sizeof(childti->fp));
259
childti->pcb.usp = 0;
260
return 0;
261
}
262
/* Note: if CLONE_SETTLS is not set, then we must inherit the
263
value from the parent, which will have been set by the block
264
copy in dup_task_struct. This is non-intuitive, but is
265
required for proper operation in the case of a threaded
266
application calling fork. */
267
if (clone_flags & CLONE_SETTLS)
268
childti->pcb.unique = tls;
269
else
270
regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */
271
childti->pcb.usp = usp ?: rdusp();
272
*childregs = *regs;
273
childregs->r0 = 0;
274
childregs->r19 = 0;
275
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
276
stack = ((struct switch_stack *) regs) - 1;
277
*childstack = *stack;
278
childstack->r26 = (unsigned long) ret_from_fork;
279
return 0;
280
}
281
282
/*
283
* Fill in the user structure for a ELF core dump.
284
*/
285
void
286
dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
287
{
288
/* switch stack follows right below pt_regs: */
289
struct switch_stack * sw = ((struct switch_stack *) pt) - 1;
290
291
dest[ 0] = pt->r0;
292
dest[ 1] = pt->r1;
293
dest[ 2] = pt->r2;
294
dest[ 3] = pt->r3;
295
dest[ 4] = pt->r4;
296
dest[ 5] = pt->r5;
297
dest[ 6] = pt->r6;
298
dest[ 7] = pt->r7;
299
dest[ 8] = pt->r8;
300
dest[ 9] = sw->r9;
301
dest[10] = sw->r10;
302
dest[11] = sw->r11;
303
dest[12] = sw->r12;
304
dest[13] = sw->r13;
305
dest[14] = sw->r14;
306
dest[15] = sw->r15;
307
dest[16] = pt->r16;
308
dest[17] = pt->r17;
309
dest[18] = pt->r18;
310
dest[19] = pt->r19;
311
dest[20] = pt->r20;
312
dest[21] = pt->r21;
313
dest[22] = pt->r22;
314
dest[23] = pt->r23;
315
dest[24] = pt->r24;
316
dest[25] = pt->r25;
317
dest[26] = pt->r26;
318
dest[27] = pt->r27;
319
dest[28] = pt->r28;
320
dest[29] = pt->gp;
321
dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp;
322
dest[31] = pt->pc;
323
324
/* Once upon a time this was the PS value. Which is stupid
325
since that is always 8 for usermode. Usurped for the more
326
useful value of the thread's UNIQUE field. */
327
dest[32] = ti->pcb.unique;
328
}
329
EXPORT_SYMBOL(dump_elf_thread);
330
331
int
332
dump_elf_task(elf_greg_t *dest, struct task_struct *task)
333
{
334
dump_elf_thread(dest, task_pt_regs(task), task_thread_info(task));
335
return 1;
336
}
337
EXPORT_SYMBOL(dump_elf_task);
338
339
int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
340
{
341
memcpy(fpu, task_thread_info(t)->fp, 32 * 8);
342
return 1;
343
}
344
345
/*
346
* Return saved PC of a blocked thread. This assumes the frame
347
* pointer is the 6th saved long on the kernel stack and that the
348
* saved return address is the first long in the frame. This all
349
* holds provided the thread blocked through a call to schedule() ($15
350
* is the frame pointer in schedule() and $15 is saved at offset 48 by
351
* entry.S:do_switch_stack).
352
*
353
* Under heavy swap load I've seen this lose in an ugly way. So do
354
* some extra sanity checking on the ranges we expect these pointers
355
* to be in so that we can fail gracefully. This is just for ps after
356
* all. -- r~
357
*/
358
359
static unsigned long
360
thread_saved_pc(struct task_struct *t)
361
{
362
unsigned long base = (unsigned long)task_stack_page(t);
363
unsigned long fp, sp = task_thread_info(t)->pcb.ksp;
364
365
if (sp > base && sp+6*8 < base + 16*1024) {
366
fp = ((unsigned long*)sp)[6];
367
if (fp > sp && fp < base + 16*1024)
368
return *(unsigned long *)fp;
369
}
370
371
return 0;
372
}
373
374
unsigned long
375
__get_wchan(struct task_struct *p)
376
{
377
unsigned long schedule_frame;
378
unsigned long pc;
379
380
/*
381
* This one depends on the frame size of schedule(). Do a
382
* "disass schedule" in gdb to find the frame size. Also, the
383
* code assumes that sleep_on() follows immediately after
384
* interruptible_sleep_on() and that add_timer() follows
385
* immediately after interruptible_sleep(). Ugly, isn't it?
386
* Maybe adding a wchan field to task_struct would be better,
387
* after all...
388
*/
389
390
pc = thread_saved_pc(p);
391
if (in_sched_functions(pc)) {
392
schedule_frame = ((unsigned long *)task_thread_info(p)->pcb.ksp)[6];
393
return ((unsigned long *)schedule_frame)[12];
394
}
395
return pc;
396
}
397
398