aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/kernel/process.c')
-rw-r--r--arch/tile/kernel/process.c110
1 files changed, 67 insertions, 43 deletions
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index c70ff14a48e4..ed590ad0acdc 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -24,9 +24,14 @@
24#include <linux/compat.h> 24#include <linux/compat.h>
25#include <linux/hardirq.h> 25#include <linux/hardirq.h>
26#include <linux/syscalls.h> 26#include <linux/syscalls.h>
27#include <linux/kernel.h>
27#include <asm/system.h> 28#include <asm/system.h>
28#include <asm/stack.h> 29#include <asm/stack.h>
29#include <asm/homecache.h> 30#include <asm/homecache.h>
31#include <asm/syscalls.h>
32#ifdef CONFIG_HARDWALL
33#include <asm/hardwall.h>
34#endif
30#include <arch/chip.h> 35#include <arch/chip.h>
31#include <arch/abi.h> 36#include <arch/abi.h>
32 37
@@ -43,7 +48,7 @@ static int __init idle_setup(char *str)
43 return -EINVAL; 48 return -EINVAL;
44 49
45 if (!strcmp(str, "poll")) { 50 if (!strcmp(str, "poll")) {
46 printk("using polling idle threads.\n"); 51 pr_info("using polling idle threads.\n");
47 no_idle_nap = 1; 52 no_idle_nap = 1;
48 } else if (!strcmp(str, "halt")) 53 } else if (!strcmp(str, "halt"))
49 no_idle_nap = 0; 54 no_idle_nap = 0;
@@ -62,7 +67,6 @@ early_param("idle", idle_setup);
62 */ 67 */
63void cpu_idle(void) 68void cpu_idle(void)
64{ 69{
65 extern void _cpu_idle(void);
66 int cpu = smp_processor_id(); 70 int cpu = smp_processor_id();
67 71
68 72
@@ -108,7 +112,7 @@ void cpu_idle(void)
108struct thread_info *alloc_thread_info(struct task_struct *task) 112struct thread_info *alloc_thread_info(struct task_struct *task)
109{ 113{
110 struct page *page; 114 struct page *page;
111 int flags = GFP_KERNEL; 115 gfp_t flags = GFP_KERNEL;
112 116
113#ifdef CONFIG_DEBUG_STACK_USAGE 117#ifdef CONFIG_DEBUG_STACK_USAGE
114 flags |= __GFP_ZERO; 118 flags |= __GFP_ZERO;
@@ -116,7 +120,7 @@ struct thread_info *alloc_thread_info(struct task_struct *task)
116 120
117 page = alloc_pages(flags, THREAD_SIZE_ORDER); 121 page = alloc_pages(flags, THREAD_SIZE_ORDER);
118 if (!page) 122 if (!page)
119 return 0; 123 return NULL;
120 124
121 return (struct thread_info *)page_address(page); 125 return (struct thread_info *)page_address(page);
122} 126}
@@ -129,6 +133,18 @@ void free_thread_info(struct thread_info *info)
129{ 133{
130 struct single_step_state *step_state = info->step_state; 134 struct single_step_state *step_state = info->step_state;
131 135
136#ifdef CONFIG_HARDWALL
137 /*
138 * We free a thread_info from the context of the task that has
139 * been scheduled next, so the original task is already dead.
140 * Calling deactivate here just frees up the data structures.
141 * If the task we're freeing held the last reference to a
142 * hardwall fd, it would have been released prior to this point
143 * anyway via exit_files(), and "hardwall" would be NULL by now.
144 */
145 if (info->task->thread.hardwall)
146 hardwall_deactivate(info->task);
147#endif
132 148
133 if (step_state) { 149 if (step_state) {
134 150
@@ -154,8 +170,6 @@ void free_thread_info(struct thread_info *info)
154 170
155static void save_arch_state(struct thread_struct *t); 171static void save_arch_state(struct thread_struct *t);
156 172
157extern void ret_from_fork(void);
158
159int copy_thread(unsigned long clone_flags, unsigned long sp, 173int copy_thread(unsigned long clone_flags, unsigned long sp,
160 unsigned long stack_size, 174 unsigned long stack_size,
161 struct task_struct *p, struct pt_regs *regs) 175 struct task_struct *p, struct pt_regs *regs)
@@ -235,6 +249,10 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
235 p->thread.proc_status = 0; 249 p->thread.proc_status = 0;
236#endif 250#endif
237 251
252#ifdef CONFIG_HARDWALL
253 /* New thread does not own any networks. */
254 p->thread.hardwall = NULL;
255#endif
238 256
239 257
240 /* 258 /*
@@ -257,7 +275,7 @@ struct task_struct *validate_current(void)
257 if (unlikely((unsigned long)tsk < PAGE_OFFSET || 275 if (unlikely((unsigned long)tsk < PAGE_OFFSET ||
258 (void *)tsk > high_memory || 276 (void *)tsk > high_memory ||
259 ((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) { 277 ((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) {
260 printk("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer); 278 pr_err("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer);
261 tsk = &corrupt; 279 tsk = &corrupt;
262 } 280 }
263 return tsk; 281 return tsk;
@@ -447,10 +465,6 @@ void _prepare_arch_switch(struct task_struct *next)
447} 465}
448 466
449 467
450extern struct task_struct *__switch_to(struct task_struct *prev,
451 struct task_struct *next,
452 unsigned long new_system_save_1_0);
453
454struct task_struct *__sched _switch_to(struct task_struct *prev, 468struct task_struct *__sched _switch_to(struct task_struct *prev,
455 struct task_struct *next) 469 struct task_struct *next)
456{ 470{
@@ -486,6 +500,15 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
486 } 500 }
487#endif 501#endif
488 502
503#ifdef CONFIG_HARDWALL
504 /* Enable or disable access to the network registers appropriately. */
505 if (prev->thread.hardwall != NULL) {
506 if (next->thread.hardwall == NULL)
507 restrict_network_mpls();
508 } else if (next->thread.hardwall != NULL) {
509 grant_network_mpls();
510 }
511#endif
489 512
490 /* 513 /*
491 * Switch kernel SP, PC, and callee-saved registers. 514 * Switch kernel SP, PC, and callee-saved registers.
@@ -496,14 +519,14 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
496 return __switch_to(prev, next, next_current_ksp0(next)); 519 return __switch_to(prev, next, next_current_ksp0(next));
497} 520}
498 521
499int _sys_fork(struct pt_regs *regs) 522long _sys_fork(struct pt_regs *regs)
500{ 523{
501 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); 524 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
502} 525}
503 526
504int _sys_clone(unsigned long clone_flags, unsigned long newsp, 527long _sys_clone(unsigned long clone_flags, unsigned long newsp,
505 void __user *parent_tidptr, void __user *child_tidptr, 528 void __user *parent_tidptr, void __user *child_tidptr,
506 struct pt_regs *regs) 529 struct pt_regs *regs)
507{ 530{
508 if (!newsp) 531 if (!newsp)
509 newsp = regs->sp; 532 newsp = regs->sp;
@@ -511,7 +534,7 @@ int _sys_clone(unsigned long clone_flags, unsigned long newsp,
511 parent_tidptr, child_tidptr); 534 parent_tidptr, child_tidptr);
512} 535}
513 536
514int _sys_vfork(struct pt_regs *regs) 537long _sys_vfork(struct pt_regs *regs)
515{ 538{
516 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, 539 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp,
517 regs, 0, NULL, NULL); 540 regs, 0, NULL, NULL);
@@ -520,10 +543,10 @@ int _sys_vfork(struct pt_regs *regs)
520/* 543/*
521 * sys_execve() executes a new program. 544 * sys_execve() executes a new program.
522 */ 545 */
523int _sys_execve(char __user *path, char __user *__user *argv, 546long _sys_execve(char __user *path, char __user *__user *argv,
524 char __user *__user *envp, struct pt_regs *regs) 547 char __user *__user *envp, struct pt_regs *regs)
525{ 548{
526 int error; 549 long error;
527 char *filename; 550 char *filename;
528 551
529 filename = getname(path); 552 filename = getname(path);
@@ -537,10 +560,10 @@ out:
537} 560}
538 561
539#ifdef CONFIG_COMPAT 562#ifdef CONFIG_COMPAT
540int _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, 563long _compat_sys_execve(char __user *path, compat_uptr_t __user *argv,
541 compat_uptr_t __user *envp, struct pt_regs *regs) 564 compat_uptr_t __user *envp, struct pt_regs *regs)
542{ 565{
543 int error; 566 long error;
544 char *filename; 567 char *filename;
545 568
546 filename = getname(path); 569 filename = getname(path);
@@ -616,31 +639,32 @@ void exit_thread(void)
616 /* Nothing */ 639 /* Nothing */
617} 640}
618 641
619#ifdef __tilegx__
620# define LINECOUNT 3
621# define EXTRA_NL "\n"
622#else
623# define LINECOUNT 4
624# define EXTRA_NL ""
625#endif
626
627void show_regs(struct pt_regs *regs) 642void show_regs(struct pt_regs *regs)
628{ 643{
629 struct task_struct *tsk = validate_current(); 644 struct task_struct *tsk = validate_current();
630 int i, linebreak; 645 int i;
631 printk("\n"); 646
632 printk(" Pid: %d, comm: %20s, CPU: %d\n", 647 pr_err("\n");
648 pr_err(" Pid: %d, comm: %20s, CPU: %d\n",
633 tsk->pid, tsk->comm, smp_processor_id()); 649 tsk->pid, tsk->comm, smp_processor_id());
634 for (i = linebreak = 0; i < 53; ++i) { 650#ifdef __tilegx__
635 printk(" r%-2d: "REGFMT, i, regs->regs[i]); 651 for (i = 0; i < 51; i += 3)
636 if (++linebreak == LINECOUNT) { 652 pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT" r%-2d: "REGFMT"\n",
637 linebreak = 0; 653 i, regs->regs[i], i+1, regs->regs[i+1],
638 printk("\n"); 654 i+2, regs->regs[i+2]);
639 } 655 pr_err(" r51: "REGFMT" r52: "REGFMT" tp : "REGFMT"\n",
640 } 656 regs->regs[51], regs->regs[52], regs->tp);
641 printk(" tp : "REGFMT EXTRA_NL " sp : "REGFMT" lr : "REGFMT"\n", 657 pr_err(" sp : "REGFMT" lr : "REGFMT"\n", regs->sp, regs->lr);
642 regs->tp, regs->sp, regs->lr); 658#else
643 printk(" pc : "REGFMT" ex1: %ld faultnum: %ld\n", 659 for (i = 0; i < 52; i += 3)
660 pr_err(" r%-2d: "REGFMT" r%-2d: "REGFMT
661 " r%-2d: "REGFMT" r%-2d: "REGFMT"\n",
662 i, regs->regs[i], i+1, regs->regs[i+1],
663 i+2, regs->regs[i+2], i+3, regs->regs[i+3]);
664 pr_err(" r52: "REGFMT" tp : "REGFMT" sp : "REGFMT" lr : "REGFMT"\n",
665 regs->regs[52], regs->tp, regs->sp, regs->lr);
666#endif
667 pr_err(" pc : "REGFMT" ex1: %ld faultnum: %ld\n",
644 regs->pc, regs->ex1, regs->faultnum); 668 regs->pc, regs->ex1, regs->faultnum);
645 669
646 dump_stack_regs(regs); 670 dump_stack_regs(regs);