diff options
Diffstat (limited to 'arch/tile/kernel/process.c')
-rw-r--r-- | arch/tile/kernel/process.c | 110 |
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 | */ |
63 | void cpu_idle(void) | 68 | void 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) | |||
108 | struct thread_info *alloc_thread_info(struct task_struct *task) | 112 | struct 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 | ||
155 | static void save_arch_state(struct thread_struct *t); | 171 | static void save_arch_state(struct thread_struct *t); |
156 | 172 | ||
157 | extern void ret_from_fork(void); | ||
158 | |||
159 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 173 | int 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 | ||
450 | extern struct task_struct *__switch_to(struct task_struct *prev, | ||
451 | struct task_struct *next, | ||
452 | unsigned long new_system_save_1_0); | ||
453 | |||
454 | struct task_struct *__sched _switch_to(struct task_struct *prev, | 468 | struct 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 | ||
499 | int _sys_fork(struct pt_regs *regs) | 522 | long _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 | ||
504 | int _sys_clone(unsigned long clone_flags, unsigned long newsp, | 527 | long _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 | ||
514 | int _sys_vfork(struct pt_regs *regs) | 537 | long _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 | */ |
523 | int _sys_execve(char __user *path, char __user *__user *argv, | 546 | long _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 |
540 | int _compat_sys_execve(char __user *path, compat_uptr_t __user *argv, | 563 | long _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 | |||
627 | void show_regs(struct pt_regs *regs) | 642 | void 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); |