diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 3 | ||||
-rw-r--r-- | kernel/audit_tree.c | 100 | ||||
-rw-r--r-- | kernel/auditsc.c | 7 | ||||
-rw-r--r-- | kernel/capability.c | 4 | ||||
-rw-r--r-- | kernel/early_res.c | 578 | ||||
-rw-r--r-- | kernel/irq/chip.c | 52 | ||||
-rw-r--r-- | kernel/irq/handle.c | 58 | ||||
-rw-r--r-- | kernel/irq/internals.h | 6 | ||||
-rw-r--r-- | kernel/irq/numa_migrate.c | 4 | ||||
-rw-r--r-- | kernel/kexec.c | 2 | ||||
-rw-r--r-- | kernel/module.c | 29 | ||||
-rw-r--r-- | kernel/printk.c | 52 | ||||
-rw-r--r-- | kernel/range.c | 163 | ||||
-rw-r--r-- | kernel/rcutorture.c | 8 | ||||
-rw-r--r-- | kernel/resource.c | 9 | ||||
-rw-r--r-- | kernel/sched.c | 4 | ||||
-rw-r--r-- | kernel/signal.c | 43 | ||||
-rw-r--r-- | kernel/stop_machine.c | 2 | ||||
-rw-r--r-- | kernel/sysctl.c | 2 | ||||
-rw-r--r-- | kernel/sysctl_binary.c | 7 | ||||
-rw-r--r-- | kernel/taskstats.c | 6 | ||||
-rw-r--r-- | kernel/trace/ring_buffer.c | 1 | ||||
-rw-r--r-- | kernel/trace/ring_buffer_benchmark.c | 1 | ||||
-rw-r--r-- | kernel/trace/trace.c | 6 | ||||
-rw-r--r-- | kernel/trace/trace_functions_graph.c | 4 |
25 files changed, 942 insertions, 209 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 6aebdeb2aa34..7b974699f8c2 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -10,7 +10,8 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ | |||
10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | 10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ |
11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ | 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ |
12 | notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \ | 12 | notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \ |
13 | async.o | 13 | async.o range.o |
14 | obj-$(CONFIG_HAVE_EARLY_RES) += early_res.o | ||
14 | obj-y += groups.o | 15 | obj-y += groups.o |
15 | 16 | ||
16 | ifdef CONFIG_FUNCTION_TRACER | 17 | ifdef CONFIG_FUNCTION_TRACER |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 4b05bd9479db..028e85663f27 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -548,6 +548,11 @@ int audit_remove_tree_rule(struct audit_krule *rule) | |||
548 | return 0; | 548 | return 0; |
549 | } | 549 | } |
550 | 550 | ||
551 | static int compare_root(struct vfsmount *mnt, void *arg) | ||
552 | { | ||
553 | return mnt->mnt_root->d_inode == arg; | ||
554 | } | ||
555 | |||
551 | void audit_trim_trees(void) | 556 | void audit_trim_trees(void) |
552 | { | 557 | { |
553 | struct list_head cursor; | 558 | struct list_head cursor; |
@@ -559,7 +564,6 @@ void audit_trim_trees(void) | |||
559 | struct path path; | 564 | struct path path; |
560 | struct vfsmount *root_mnt; | 565 | struct vfsmount *root_mnt; |
561 | struct node *node; | 566 | struct node *node; |
562 | struct list_head list; | ||
563 | int err; | 567 | int err; |
564 | 568 | ||
565 | tree = container_of(cursor.next, struct audit_tree, list); | 569 | tree = container_of(cursor.next, struct audit_tree, list); |
@@ -577,24 +581,16 @@ void audit_trim_trees(void) | |||
577 | if (!root_mnt) | 581 | if (!root_mnt) |
578 | goto skip_it; | 582 | goto skip_it; |
579 | 583 | ||
580 | list_add_tail(&list, &root_mnt->mnt_list); | ||
581 | spin_lock(&hash_lock); | 584 | spin_lock(&hash_lock); |
582 | list_for_each_entry(node, &tree->chunks, list) { | 585 | list_for_each_entry(node, &tree->chunks, list) { |
583 | struct audit_chunk *chunk = find_chunk(node); | 586 | struct inode *inode = find_chunk(node)->watch.inode; |
584 | struct inode *inode = chunk->watch.inode; | ||
585 | struct vfsmount *mnt; | ||
586 | node->index |= 1U<<31; | 587 | node->index |= 1U<<31; |
587 | list_for_each_entry(mnt, &list, mnt_list) { | 588 | if (iterate_mounts(compare_root, inode, root_mnt)) |
588 | if (mnt->mnt_root->d_inode == inode) { | 589 | node->index &= ~(1U<<31); |
589 | node->index &= ~(1U<<31); | ||
590 | break; | ||
591 | } | ||
592 | } | ||
593 | } | 590 | } |
594 | spin_unlock(&hash_lock); | 591 | spin_unlock(&hash_lock); |
595 | trim_marked(tree); | 592 | trim_marked(tree); |
596 | put_tree(tree); | 593 | put_tree(tree); |
597 | list_del_init(&list); | ||
598 | drop_collected_mounts(root_mnt); | 594 | drop_collected_mounts(root_mnt); |
599 | skip_it: | 595 | skip_it: |
600 | mutex_lock(&audit_filter_mutex); | 596 | mutex_lock(&audit_filter_mutex); |
@@ -603,22 +599,6 @@ skip_it: | |||
603 | mutex_unlock(&audit_filter_mutex); | 599 | mutex_unlock(&audit_filter_mutex); |
604 | } | 600 | } |
605 | 601 | ||
606 | static int is_under(struct vfsmount *mnt, struct dentry *dentry, | ||
607 | struct path *path) | ||
608 | { | ||
609 | if (mnt != path->mnt) { | ||
610 | for (;;) { | ||
611 | if (mnt->mnt_parent == mnt) | ||
612 | return 0; | ||
613 | if (mnt->mnt_parent == path->mnt) | ||
614 | break; | ||
615 | mnt = mnt->mnt_parent; | ||
616 | } | ||
617 | dentry = mnt->mnt_mountpoint; | ||
618 | } | ||
619 | return is_subdir(dentry, path->dentry); | ||
620 | } | ||
621 | |||
622 | int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) | 602 | int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) |
623 | { | 603 | { |
624 | 604 | ||
@@ -638,13 +618,17 @@ void audit_put_tree(struct audit_tree *tree) | |||
638 | put_tree(tree); | 618 | put_tree(tree); |
639 | } | 619 | } |
640 | 620 | ||
621 | static int tag_mount(struct vfsmount *mnt, void *arg) | ||
622 | { | ||
623 | return tag_chunk(mnt->mnt_root->d_inode, arg); | ||
624 | } | ||
625 | |||
641 | /* called with audit_filter_mutex */ | 626 | /* called with audit_filter_mutex */ |
642 | int audit_add_tree_rule(struct audit_krule *rule) | 627 | int audit_add_tree_rule(struct audit_krule *rule) |
643 | { | 628 | { |
644 | struct audit_tree *seed = rule->tree, *tree; | 629 | struct audit_tree *seed = rule->tree, *tree; |
645 | struct path path; | 630 | struct path path; |
646 | struct vfsmount *mnt, *p; | 631 | struct vfsmount *mnt; |
647 | struct list_head list; | ||
648 | int err; | 632 | int err; |
649 | 633 | ||
650 | list_for_each_entry(tree, &tree_list, list) { | 634 | list_for_each_entry(tree, &tree_list, list) { |
@@ -670,16 +654,9 @@ int audit_add_tree_rule(struct audit_krule *rule) | |||
670 | err = -ENOMEM; | 654 | err = -ENOMEM; |
671 | goto Err; | 655 | goto Err; |
672 | } | 656 | } |
673 | list_add_tail(&list, &mnt->mnt_list); | ||
674 | 657 | ||
675 | get_tree(tree); | 658 | get_tree(tree); |
676 | list_for_each_entry(p, &list, mnt_list) { | 659 | err = iterate_mounts(tag_mount, tree, mnt); |
677 | err = tag_chunk(p->mnt_root->d_inode, tree); | ||
678 | if (err) | ||
679 | break; | ||
680 | } | ||
681 | |||
682 | list_del(&list); | ||
683 | drop_collected_mounts(mnt); | 660 | drop_collected_mounts(mnt); |
684 | 661 | ||
685 | if (!err) { | 662 | if (!err) { |
@@ -714,31 +691,23 @@ int audit_tag_tree(char *old, char *new) | |||
714 | { | 691 | { |
715 | struct list_head cursor, barrier; | 692 | struct list_head cursor, barrier; |
716 | int failed = 0; | 693 | int failed = 0; |
717 | struct path path; | 694 | struct path path1, path2; |
718 | struct vfsmount *tagged; | 695 | struct vfsmount *tagged; |
719 | struct list_head list; | ||
720 | struct vfsmount *mnt; | ||
721 | struct dentry *dentry; | ||
722 | int err; | 696 | int err; |
723 | 697 | ||
724 | err = kern_path(new, 0, &path); | 698 | err = kern_path(new, 0, &path2); |
725 | if (err) | 699 | if (err) |
726 | return err; | 700 | return err; |
727 | tagged = collect_mounts(&path); | 701 | tagged = collect_mounts(&path2); |
728 | path_put(&path); | 702 | path_put(&path2); |
729 | if (!tagged) | 703 | if (!tagged) |
730 | return -ENOMEM; | 704 | return -ENOMEM; |
731 | 705 | ||
732 | err = kern_path(old, 0, &path); | 706 | err = kern_path(old, 0, &path1); |
733 | if (err) { | 707 | if (err) { |
734 | drop_collected_mounts(tagged); | 708 | drop_collected_mounts(tagged); |
735 | return err; | 709 | return err; |
736 | } | 710 | } |
737 | mnt = mntget(path.mnt); | ||
738 | dentry = dget(path.dentry); | ||
739 | path_put(&path); | ||
740 | |||
741 | list_add_tail(&list, &tagged->mnt_list); | ||
742 | 711 | ||
743 | mutex_lock(&audit_filter_mutex); | 712 | mutex_lock(&audit_filter_mutex); |
744 | list_add(&barrier, &tree_list); | 713 | list_add(&barrier, &tree_list); |
@@ -746,7 +715,7 @@ int audit_tag_tree(char *old, char *new) | |||
746 | 715 | ||
747 | while (cursor.next != &tree_list) { | 716 | while (cursor.next != &tree_list) { |
748 | struct audit_tree *tree; | 717 | struct audit_tree *tree; |
749 | struct vfsmount *p; | 718 | int good_one = 0; |
750 | 719 | ||
751 | tree = container_of(cursor.next, struct audit_tree, list); | 720 | tree = container_of(cursor.next, struct audit_tree, list); |
752 | get_tree(tree); | 721 | get_tree(tree); |
@@ -754,30 +723,19 @@ int audit_tag_tree(char *old, char *new) | |||
754 | list_add(&cursor, &tree->list); | 723 | list_add(&cursor, &tree->list); |
755 | mutex_unlock(&audit_filter_mutex); | 724 | mutex_unlock(&audit_filter_mutex); |
756 | 725 | ||
757 | err = kern_path(tree->pathname, 0, &path); | 726 | err = kern_path(tree->pathname, 0, &path2); |
758 | if (err) { | 727 | if (!err) { |
759 | put_tree(tree); | 728 | good_one = path_is_under(&path1, &path2); |
760 | mutex_lock(&audit_filter_mutex); | 729 | path_put(&path2); |
761 | continue; | ||
762 | } | 730 | } |
763 | 731 | ||
764 | spin_lock(&vfsmount_lock); | 732 | if (!good_one) { |
765 | if (!is_under(mnt, dentry, &path)) { | ||
766 | spin_unlock(&vfsmount_lock); | ||
767 | path_put(&path); | ||
768 | put_tree(tree); | 733 | put_tree(tree); |
769 | mutex_lock(&audit_filter_mutex); | 734 | mutex_lock(&audit_filter_mutex); |
770 | continue; | 735 | continue; |
771 | } | 736 | } |
772 | spin_unlock(&vfsmount_lock); | ||
773 | path_put(&path); | ||
774 | |||
775 | list_for_each_entry(p, &list, mnt_list) { | ||
776 | failed = tag_chunk(p->mnt_root->d_inode, tree); | ||
777 | if (failed) | ||
778 | break; | ||
779 | } | ||
780 | 737 | ||
738 | failed = iterate_mounts(tag_mount, tree, tagged); | ||
781 | if (failed) { | 739 | if (failed) { |
782 | put_tree(tree); | 740 | put_tree(tree); |
783 | mutex_lock(&audit_filter_mutex); | 741 | mutex_lock(&audit_filter_mutex); |
@@ -818,10 +776,8 @@ int audit_tag_tree(char *old, char *new) | |||
818 | } | 776 | } |
819 | list_del(&barrier); | 777 | list_del(&barrier); |
820 | list_del(&cursor); | 778 | list_del(&cursor); |
821 | list_del(&list); | ||
822 | mutex_unlock(&audit_filter_mutex); | 779 | mutex_unlock(&audit_filter_mutex); |
823 | dput(dentry); | 780 | path_put(&path1); |
824 | mntput(mnt); | ||
825 | drop_collected_mounts(tagged); | 781 | drop_collected_mounts(tagged); |
826 | return failed; | 782 | return failed; |
827 | } | 783 | } |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index fc0f928167e7..f3a461c0970a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -1988,7 +1988,6 @@ void __audit_inode(const char *name, const struct dentry *dentry) | |||
1988 | 1988 | ||
1989 | /** | 1989 | /** |
1990 | * audit_inode_child - collect inode info for created/removed objects | 1990 | * audit_inode_child - collect inode info for created/removed objects |
1991 | * @dname: inode's dentry name | ||
1992 | * @dentry: dentry being audited | 1991 | * @dentry: dentry being audited |
1993 | * @parent: inode of dentry parent | 1992 | * @parent: inode of dentry parent |
1994 | * | 1993 | * |
@@ -2000,13 +1999,14 @@ void __audit_inode(const char *name, const struct dentry *dentry) | |||
2000 | * must be hooked prior, in order to capture the target inode during | 1999 | * must be hooked prior, in order to capture the target inode during |
2001 | * unsuccessful attempts. | 2000 | * unsuccessful attempts. |
2002 | */ | 2001 | */ |
2003 | void __audit_inode_child(const char *dname, const struct dentry *dentry, | 2002 | void __audit_inode_child(const struct dentry *dentry, |
2004 | const struct inode *parent) | 2003 | const struct inode *parent) |
2005 | { | 2004 | { |
2006 | int idx; | 2005 | int idx; |
2007 | struct audit_context *context = current->audit_context; | 2006 | struct audit_context *context = current->audit_context; |
2008 | const char *found_parent = NULL, *found_child = NULL; | 2007 | const char *found_parent = NULL, *found_child = NULL; |
2009 | const struct inode *inode = dentry->d_inode; | 2008 | const struct inode *inode = dentry->d_inode; |
2009 | const char *dname = dentry->d_name.name; | ||
2010 | int dirlen = 0; | 2010 | int dirlen = 0; |
2011 | 2011 | ||
2012 | if (!context->in_syscall) | 2012 | if (!context->in_syscall) |
@@ -2014,9 +2014,6 @@ void __audit_inode_child(const char *dname, const struct dentry *dentry, | |||
2014 | 2014 | ||
2015 | if (inode) | 2015 | if (inode) |
2016 | handle_one(inode); | 2016 | handle_one(inode); |
2017 | /* determine matching parent */ | ||
2018 | if (!dname) | ||
2019 | goto add_names; | ||
2020 | 2017 | ||
2021 | /* parent is more likely, look for it first */ | 2018 | /* parent is more likely, look for it first */ |
2022 | for (idx = 0; idx < context->name_count; idx++) { | 2019 | for (idx = 0; idx < context->name_count; idx++) { |
diff --git a/kernel/capability.c b/kernel/capability.c index 7f876e60521f..9e4697e9b276 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -135,7 +135,7 @@ static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, | |||
135 | if (pid && (pid != task_pid_vnr(current))) { | 135 | if (pid && (pid != task_pid_vnr(current))) { |
136 | struct task_struct *target; | 136 | struct task_struct *target; |
137 | 137 | ||
138 | read_lock(&tasklist_lock); | 138 | rcu_read_lock(); |
139 | 139 | ||
140 | target = find_task_by_vpid(pid); | 140 | target = find_task_by_vpid(pid); |
141 | if (!target) | 141 | if (!target) |
@@ -143,7 +143,7 @@ static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp, | |||
143 | else | 143 | else |
144 | ret = security_capget(target, pEp, pIp, pPp); | 144 | ret = security_capget(target, pEp, pIp, pPp); |
145 | 145 | ||
146 | read_unlock(&tasklist_lock); | 146 | rcu_read_unlock(); |
147 | } else | 147 | } else |
148 | ret = security_capget(current, pEp, pIp, pPp); | 148 | ret = security_capget(current, pEp, pIp, pPp); |
149 | 149 | ||
diff --git a/kernel/early_res.c b/kernel/early_res.c new file mode 100644 index 000000000000..3cb2c661bb78 --- /dev/null +++ b/kernel/early_res.c | |||
@@ -0,0 +1,578 @@ | |||
1 | /* | ||
2 | * early_res, could be used to replace bootmem | ||
3 | */ | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/bootmem.h> | ||
8 | #include <linux/mm.h> | ||
9 | #include <linux/early_res.h> | ||
10 | |||
11 | /* | ||
12 | * Early reserved memory areas. | ||
13 | */ | ||
14 | /* | ||
15 | * need to make sure this one is bigger enough before | ||
16 | * find_fw_memmap_area could be used | ||
17 | */ | ||
18 | #define MAX_EARLY_RES_X 32 | ||
19 | |||
20 | struct early_res { | ||
21 | u64 start, end; | ||
22 | char name[15]; | ||
23 | char overlap_ok; | ||
24 | }; | ||
25 | static struct early_res early_res_x[MAX_EARLY_RES_X] __initdata; | ||
26 | |||
27 | static int max_early_res __initdata = MAX_EARLY_RES_X; | ||
28 | static struct early_res *early_res __initdata = &early_res_x[0]; | ||
29 | static int early_res_count __initdata; | ||
30 | |||
31 | static int __init find_overlapped_early(u64 start, u64 end) | ||
32 | { | ||
33 | int i; | ||
34 | struct early_res *r; | ||
35 | |||
36 | for (i = 0; i < max_early_res && early_res[i].end; i++) { | ||
37 | r = &early_res[i]; | ||
38 | if (end > r->start && start < r->end) | ||
39 | break; | ||
40 | } | ||
41 | |||
42 | return i; | ||
43 | } | ||
44 | |||
45 | /* | ||
46 | * Drop the i-th range from the early reservation map, | ||
47 | * by copying any higher ranges down one over it, and | ||
48 | * clearing what had been the last slot. | ||
49 | */ | ||
50 | static void __init drop_range(int i) | ||
51 | { | ||
52 | int j; | ||
53 | |||
54 | for (j = i + 1; j < max_early_res && early_res[j].end; j++) | ||
55 | ; | ||
56 | |||
57 | memmove(&early_res[i], &early_res[i + 1], | ||
58 | (j - 1 - i) * sizeof(struct early_res)); | ||
59 | |||
60 | early_res[j - 1].end = 0; | ||
61 | early_res_count--; | ||
62 | } | ||
63 | |||
64 | static void __init drop_range_partial(int i, u64 start, u64 end) | ||
65 | { | ||
66 | u64 common_start, common_end; | ||
67 | u64 old_start, old_end; | ||
68 | |||
69 | old_start = early_res[i].start; | ||
70 | old_end = early_res[i].end; | ||
71 | common_start = max(old_start, start); | ||
72 | common_end = min(old_end, end); | ||
73 | |||
74 | /* no overlap ? */ | ||
75 | if (common_start >= common_end) | ||
76 | return; | ||
77 | |||
78 | if (old_start < common_start) { | ||
79 | /* make head segment */ | ||
80 | early_res[i].end = common_start; | ||
81 | if (old_end > common_end) { | ||
82 | char name[15]; | ||
83 | |||
84 | /* | ||
85 | * Save a local copy of the name, since the | ||
86 | * early_res array could get resized inside | ||
87 | * reserve_early_without_check() -> | ||
88 | * __check_and_double_early_res(), which would | ||
89 | * make the current name pointer invalid. | ||
90 | */ | ||
91 | strncpy(name, early_res[i].name, | ||
92 | sizeof(early_res[i].name) - 1); | ||
93 | /* add another for left over on tail */ | ||
94 | reserve_early_without_check(common_end, old_end, name); | ||
95 | } | ||
96 | return; | ||
97 | } else { | ||
98 | if (old_end > common_end) { | ||
99 | /* reuse the entry for tail left */ | ||
100 | early_res[i].start = common_end; | ||
101 | return; | ||
102 | } | ||
103 | /* all covered */ | ||
104 | drop_range(i); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Split any existing ranges that: | ||
110 | * 1) are marked 'overlap_ok', and | ||
111 | * 2) overlap with the stated range [start, end) | ||
112 | * into whatever portion (if any) of the existing range is entirely | ||
113 | * below or entirely above the stated range. Drop the portion | ||
114 | * of the existing range that overlaps with the stated range, | ||
115 | * which will allow the caller of this routine to then add that | ||
116 | * stated range without conflicting with any existing range. | ||
117 | */ | ||
118 | static void __init drop_overlaps_that_are_ok(u64 start, u64 end) | ||
119 | { | ||
120 | int i; | ||
121 | struct early_res *r; | ||
122 | u64 lower_start, lower_end; | ||
123 | u64 upper_start, upper_end; | ||
124 | char name[15]; | ||
125 | |||
126 | for (i = 0; i < max_early_res && early_res[i].end; i++) { | ||
127 | r = &early_res[i]; | ||
128 | |||
129 | /* Continue past non-overlapping ranges */ | ||
130 | if (end <= r->start || start >= r->end) | ||
131 | continue; | ||
132 | |||
133 | /* | ||
134 | * Leave non-ok overlaps as is; let caller | ||
135 | * panic "Overlapping early reservations" | ||
136 | * when it hits this overlap. | ||
137 | */ | ||
138 | if (!r->overlap_ok) | ||
139 | return; | ||
140 | |||
141 | /* | ||
142 | * We have an ok overlap. We will drop it from the early | ||
143 | * reservation map, and add back in any non-overlapping | ||
144 | * portions (lower or upper) as separate, overlap_ok, | ||
145 | * non-overlapping ranges. | ||
146 | */ | ||
147 | |||
148 | /* 1. Note any non-overlapping (lower or upper) ranges. */ | ||
149 | strncpy(name, r->name, sizeof(name) - 1); | ||
150 | |||
151 | lower_start = lower_end = 0; | ||
152 | upper_start = upper_end = 0; | ||
153 | if (r->start < start) { | ||
154 | lower_start = r->start; | ||
155 | lower_end = start; | ||
156 | } | ||
157 | if (r->end > end) { | ||
158 | upper_start = end; | ||
159 | upper_end = r->end; | ||
160 | } | ||
161 | |||
162 | /* 2. Drop the original ok overlapping range */ | ||
163 | drop_range(i); | ||
164 | |||
165 | i--; /* resume for-loop on copied down entry */ | ||
166 | |||
167 | /* 3. Add back in any non-overlapping ranges. */ | ||
168 | if (lower_end) | ||
169 | reserve_early_overlap_ok(lower_start, lower_end, name); | ||
170 | if (upper_end) | ||
171 | reserve_early_overlap_ok(upper_start, upper_end, name); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | static void __init __reserve_early(u64 start, u64 end, char *name, | ||
176 | int overlap_ok) | ||
177 | { | ||
178 | int i; | ||
179 | struct early_res *r; | ||
180 | |||
181 | i = find_overlapped_early(start, end); | ||
182 | if (i >= max_early_res) | ||
183 | panic("Too many early reservations"); | ||
184 | r = &early_res[i]; | ||
185 | if (r->end) | ||
186 | panic("Overlapping early reservations " | ||
187 | "%llx-%llx %s to %llx-%llx %s\n", | ||
188 | start, end - 1, name ? name : "", r->start, | ||
189 | r->end - 1, r->name); | ||
190 | r->start = start; | ||
191 | r->end = end; | ||
192 | r->overlap_ok = overlap_ok; | ||
193 | if (name) | ||
194 | strncpy(r->name, name, sizeof(r->name) - 1); | ||
195 | early_res_count++; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * A few early reservtations come here. | ||
200 | * | ||
201 | * The 'overlap_ok' in the name of this routine does -not- mean it | ||
202 | * is ok for these reservations to overlap an earlier reservation. | ||
203 | * Rather it means that it is ok for subsequent reservations to | ||
204 | * overlap this one. | ||
205 | * | ||
206 | * Use this entry point to reserve early ranges when you are doing | ||
207 | * so out of "Paranoia", reserving perhaps more memory than you need, | ||
208 | * just in case, and don't mind a subsequent overlapping reservation | ||
209 | * that is known to be needed. | ||
210 | * | ||
211 | * The drop_overlaps_that_are_ok() call here isn't really needed. | ||
212 | * It would be needed if we had two colliding 'overlap_ok' | ||
213 | * reservations, so that the second such would not panic on the | ||
214 | * overlap with the first. We don't have any such as of this | ||
215 | * writing, but might as well tolerate such if it happens in | ||
216 | * the future. | ||
217 | */ | ||
218 | void __init reserve_early_overlap_ok(u64 start, u64 end, char *name) | ||
219 | { | ||
220 | drop_overlaps_that_are_ok(start, end); | ||
221 | __reserve_early(start, end, name, 1); | ||
222 | } | ||
223 | |||
224 | static void __init __check_and_double_early_res(u64 ex_start, u64 ex_end) | ||
225 | { | ||
226 | u64 start, end, size, mem; | ||
227 | struct early_res *new; | ||
228 | |||
229 | /* do we have enough slots left ? */ | ||
230 | if ((max_early_res - early_res_count) > max(max_early_res/8, 2)) | ||
231 | return; | ||
232 | |||
233 | /* double it */ | ||
234 | mem = -1ULL; | ||
235 | size = sizeof(struct early_res) * max_early_res * 2; | ||
236 | if (early_res == early_res_x) | ||
237 | start = 0; | ||
238 | else | ||
239 | start = early_res[0].end; | ||
240 | end = ex_start; | ||
241 | if (start + size < end) | ||
242 | mem = find_fw_memmap_area(start, end, size, | ||
243 | sizeof(struct early_res)); | ||
244 | if (mem == -1ULL) { | ||
245 | start = ex_end; | ||
246 | end = get_max_mapped(); | ||
247 | if (start + size < end) | ||
248 | mem = find_fw_memmap_area(start, end, size, | ||
249 | sizeof(struct early_res)); | ||
250 | } | ||
251 | if (mem == -1ULL) | ||
252 | panic("can not find more space for early_res array"); | ||
253 | |||
254 | new = __va(mem); | ||
255 | /* save the first one for own */ | ||
256 | new[0].start = mem; | ||
257 | new[0].end = mem + size; | ||
258 | new[0].overlap_ok = 0; | ||
259 | /* copy old to new */ | ||
260 | if (early_res == early_res_x) { | ||
261 | memcpy(&new[1], &early_res[0], | ||
262 | sizeof(struct early_res) * max_early_res); | ||
263 | memset(&new[max_early_res+1], 0, | ||
264 | sizeof(struct early_res) * (max_early_res - 1)); | ||
265 | early_res_count++; | ||
266 | } else { | ||
267 | memcpy(&new[1], &early_res[1], | ||
268 | sizeof(struct early_res) * (max_early_res - 1)); | ||
269 | memset(&new[max_early_res], 0, | ||
270 | sizeof(struct early_res) * max_early_res); | ||
271 | } | ||
272 | memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res); | ||
273 | early_res = new; | ||
274 | max_early_res *= 2; | ||
275 | printk(KERN_DEBUG "early_res array is doubled to %d at [%llx - %llx]\n", | ||
276 | max_early_res, mem, mem + size - 1); | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * Most early reservations come here. | ||
281 | * | ||
282 | * We first have drop_overlaps_that_are_ok() drop any pre-existing | ||
283 | * 'overlap_ok' ranges, so that we can then reserve this memory | ||
284 | * range without risk of panic'ing on an overlapping overlap_ok | ||
285 | * early reservation. | ||
286 | */ | ||
287 | void __init reserve_early(u64 start, u64 end, char *name) | ||
288 | { | ||
289 | if (start >= end) | ||
290 | return; | ||
291 | |||
292 | __check_and_double_early_res(start, end); | ||
293 | |||
294 | drop_overlaps_that_are_ok(start, end); | ||
295 | __reserve_early(start, end, name, 0); | ||
296 | } | ||
297 | |||
298 | void __init reserve_early_without_check(u64 start, u64 end, char *name) | ||
299 | { | ||
300 | struct early_res *r; | ||
301 | |||
302 | if (start >= end) | ||
303 | return; | ||
304 | |||
305 | __check_and_double_early_res(start, end); | ||
306 | |||
307 | r = &early_res[early_res_count]; | ||
308 | |||
309 | r->start = start; | ||
310 | r->end = end; | ||
311 | r->overlap_ok = 0; | ||
312 | if (name) | ||
313 | strncpy(r->name, name, sizeof(r->name) - 1); | ||
314 | early_res_count++; | ||
315 | } | ||
316 | |||
317 | void __init free_early(u64 start, u64 end) | ||
318 | { | ||
319 | struct early_res *r; | ||
320 | int i; | ||
321 | |||
322 | i = find_overlapped_early(start, end); | ||
323 | r = &early_res[i]; | ||
324 | if (i >= max_early_res || r->end != end || r->start != start) | ||
325 | panic("free_early on not reserved area: %llx-%llx!", | ||
326 | start, end - 1); | ||
327 | |||
328 | drop_range(i); | ||
329 | } | ||
330 | |||
331 | void __init free_early_partial(u64 start, u64 end) | ||
332 | { | ||
333 | struct early_res *r; | ||
334 | int i; | ||
335 | |||
336 | try_next: | ||
337 | i = find_overlapped_early(start, end); | ||
338 | if (i >= max_early_res) | ||
339 | return; | ||
340 | |||
341 | r = &early_res[i]; | ||
342 | /* hole ? */ | ||
343 | if (r->end >= end && r->start <= start) { | ||
344 | drop_range_partial(i, start, end); | ||
345 | return; | ||
346 | } | ||
347 | |||
348 | drop_range_partial(i, start, end); | ||
349 | goto try_next; | ||
350 | } | ||
351 | |||
352 | #ifdef CONFIG_NO_BOOTMEM | ||
353 | static void __init subtract_early_res(struct range *range, int az) | ||
354 | { | ||
355 | int i, count; | ||
356 | u64 final_start, final_end; | ||
357 | int idx = 0; | ||
358 | |||
359 | count = 0; | ||
360 | for (i = 0; i < max_early_res && early_res[i].end; i++) | ||
361 | count++; | ||
362 | |||
363 | /* need to skip first one ?*/ | ||
364 | if (early_res != early_res_x) | ||
365 | idx = 1; | ||
366 | |||
367 | #define DEBUG_PRINT_EARLY_RES 1 | ||
368 | |||
369 | #if DEBUG_PRINT_EARLY_RES | ||
370 | printk(KERN_INFO "Subtract (%d early reservations)\n", count); | ||
371 | #endif | ||
372 | for (i = idx; i < count; i++) { | ||
373 | struct early_res *r = &early_res[i]; | ||
374 | #if DEBUG_PRINT_EARLY_RES | ||
375 | printk(KERN_INFO " #%d [%010llx - %010llx] %15s\n", i, | ||
376 | r->start, r->end, r->name); | ||
377 | #endif | ||
378 | final_start = PFN_DOWN(r->start); | ||
379 | final_end = PFN_UP(r->end); | ||
380 | if (final_start >= final_end) | ||
381 | continue; | ||
382 | subtract_range(range, az, final_start, final_end); | ||
383 | } | ||
384 | |||
385 | } | ||
386 | |||
387 | int __init get_free_all_memory_range(struct range **rangep, int nodeid) | ||
388 | { | ||
389 | int i, count; | ||
390 | u64 start = 0, end; | ||
391 | u64 size; | ||
392 | u64 mem; | ||
393 | struct range *range; | ||
394 | int nr_range; | ||
395 | |||
396 | count = 0; | ||
397 | for (i = 0; i < max_early_res && early_res[i].end; i++) | ||
398 | count++; | ||
399 | |||
400 | count *= 2; | ||
401 | |||
402 | size = sizeof(struct range) * count; | ||
403 | end = get_max_mapped(); | ||
404 | #ifdef MAX_DMA32_PFN | ||
405 | if (end > (MAX_DMA32_PFN << PAGE_SHIFT)) | ||
406 | start = MAX_DMA32_PFN << PAGE_SHIFT; | ||
407 | #endif | ||
408 | mem = find_fw_memmap_area(start, end, size, sizeof(struct range)); | ||
409 | if (mem == -1ULL) | ||
410 | panic("can not find more space for range free"); | ||
411 | |||
412 | range = __va(mem); | ||
413 | /* use early_node_map[] and early_res to get range array at first */ | ||
414 | memset(range, 0, size); | ||
415 | nr_range = 0; | ||
416 | |||
417 | /* need to go over early_node_map to find out good range for node */ | ||
418 | nr_range = add_from_early_node_map(range, count, nr_range, nodeid); | ||
419 | #ifdef CONFIG_X86_32 | ||
420 | subtract_range(range, count, max_low_pfn, -1ULL); | ||
421 | #endif | ||
422 | subtract_early_res(range, count); | ||
423 | nr_range = clean_sort_range(range, count); | ||
424 | |||
425 | /* need to clear it ? */ | ||
426 | if (nodeid == MAX_NUMNODES) { | ||
427 | memset(&early_res[0], 0, | ||
428 | sizeof(struct early_res) * max_early_res); | ||
429 | early_res = NULL; | ||
430 | max_early_res = 0; | ||
431 | } | ||
432 | |||
433 | *rangep = range; | ||
434 | return nr_range; | ||
435 | } | ||
436 | #else | ||
437 | void __init early_res_to_bootmem(u64 start, u64 end) | ||
438 | { | ||
439 | int i, count; | ||
440 | u64 final_start, final_end; | ||
441 | int idx = 0; | ||
442 | |||
443 | count = 0; | ||
444 | for (i = 0; i < max_early_res && early_res[i].end; i++) | ||
445 | count++; | ||
446 | |||
447 | /* need to skip first one ?*/ | ||
448 | if (early_res != early_res_x) | ||
449 | idx = 1; | ||
450 | |||
451 | printk(KERN_INFO "(%d/%d early reservations) ==> bootmem [%010llx - %010llx]\n", | ||
452 | count - idx, max_early_res, start, end); | ||
453 | for (i = idx; i < count; i++) { | ||
454 | struct early_res *r = &early_res[i]; | ||
455 | printk(KERN_INFO " #%d [%010llx - %010llx] %16s", i, | ||
456 | r->start, r->end, r->name); | ||
457 | final_start = max(start, r->start); | ||
458 | final_end = min(end, r->end); | ||
459 | if (final_start >= final_end) { | ||
460 | printk(KERN_CONT "\n"); | ||
461 | continue; | ||
462 | } | ||
463 | printk(KERN_CONT " ==> [%010llx - %010llx]\n", | ||
464 | final_start, final_end); | ||
465 | reserve_bootmem_generic(final_start, final_end - final_start, | ||
466 | BOOTMEM_DEFAULT); | ||
467 | } | ||
468 | /* clear them */ | ||
469 | memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res); | ||
470 | early_res = NULL; | ||
471 | max_early_res = 0; | ||
472 | early_res_count = 0; | ||
473 | } | ||
474 | #endif | ||
475 | |||
476 | /* Check for already reserved areas */ | ||
477 | static inline int __init bad_addr(u64 *addrp, u64 size, u64 align) | ||
478 | { | ||
479 | int i; | ||
480 | u64 addr = *addrp; | ||
481 | int changed = 0; | ||
482 | struct early_res *r; | ||
483 | again: | ||
484 | i = find_overlapped_early(addr, addr + size); | ||
485 | r = &early_res[i]; | ||
486 | if (i < max_early_res && r->end) { | ||
487 | *addrp = addr = round_up(r->end, align); | ||
488 | changed = 1; | ||
489 | goto again; | ||
490 | } | ||
491 | return changed; | ||
492 | } | ||
493 | |||
494 | /* Check for already reserved areas */ | ||
495 | static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align) | ||
496 | { | ||
497 | int i; | ||
498 | u64 addr = *addrp, last; | ||
499 | u64 size = *sizep; | ||
500 | int changed = 0; | ||
501 | again: | ||
502 | last = addr + size; | ||
503 | for (i = 0; i < max_early_res && early_res[i].end; i++) { | ||
504 | struct early_res *r = &early_res[i]; | ||
505 | if (last > r->start && addr < r->start) { | ||
506 | size = r->start - addr; | ||
507 | changed = 1; | ||
508 | goto again; | ||
509 | } | ||
510 | if (last > r->end && addr < r->end) { | ||
511 | addr = round_up(r->end, align); | ||
512 | size = last - addr; | ||
513 | changed = 1; | ||
514 | goto again; | ||
515 | } | ||
516 | if (last <= r->end && addr >= r->start) { | ||
517 | (*sizep)++; | ||
518 | return 0; | ||
519 | } | ||
520 | } | ||
521 | if (changed) { | ||
522 | *addrp = addr; | ||
523 | *sizep = size; | ||
524 | } | ||
525 | return changed; | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * Find a free area with specified alignment in a specific range. | ||
530 | * only with the area.between start to end is active range from early_node_map | ||
531 | * so they are good as RAM | ||
532 | */ | ||
533 | u64 __init find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end, | ||
534 | u64 size, u64 align) | ||
535 | { | ||
536 | u64 addr, last; | ||
537 | |||
538 | addr = round_up(ei_start, align); | ||
539 | if (addr < start) | ||
540 | addr = round_up(start, align); | ||
541 | if (addr >= ei_last) | ||
542 | goto out; | ||
543 | while (bad_addr(&addr, size, align) && addr+size <= ei_last) | ||
544 | ; | ||
545 | last = addr + size; | ||
546 | if (last > ei_last) | ||
547 | goto out; | ||
548 | if (last > end) | ||
549 | goto out; | ||
550 | |||
551 | return addr; | ||
552 | |||
553 | out: | ||
554 | return -1ULL; | ||
555 | } | ||
556 | |||
557 | u64 __init find_early_area_size(u64 ei_start, u64 ei_last, u64 start, | ||
558 | u64 *sizep, u64 align) | ||
559 | { | ||
560 | u64 addr, last; | ||
561 | |||
562 | addr = round_up(ei_start, align); | ||
563 | if (addr < start) | ||
564 | addr = round_up(start, align); | ||
565 | if (addr >= ei_last) | ||
566 | goto out; | ||
567 | *sizep = ei_last - addr; | ||
568 | while (bad_addr_size(&addr, sizep, align) && addr + *sizep <= ei_last) | ||
569 | ; | ||
570 | last = addr + *sizep; | ||
571 | if (last > ei_last) | ||
572 | goto out; | ||
573 | |||
574 | return addr; | ||
575 | |||
576 | out: | ||
577 | return -1ULL; | ||
578 | } | ||
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index ecc3fa28f666..d70394f12ee9 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -18,11 +18,7 @@ | |||
18 | 18 | ||
19 | #include "internals.h" | 19 | #include "internals.h" |
20 | 20 | ||
21 | /** | 21 | static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data) |
22 | * dynamic_irq_init - initialize a dynamically allocated irq | ||
23 | * @irq: irq number to initialize | ||
24 | */ | ||
25 | void dynamic_irq_init(unsigned int irq) | ||
26 | { | 22 | { |
27 | struct irq_desc *desc; | 23 | struct irq_desc *desc; |
28 | unsigned long flags; | 24 | unsigned long flags; |
@@ -41,7 +37,8 @@ void dynamic_irq_init(unsigned int irq) | |||
41 | desc->depth = 1; | 37 | desc->depth = 1; |
42 | desc->msi_desc = NULL; | 38 | desc->msi_desc = NULL; |
43 | desc->handler_data = NULL; | 39 | desc->handler_data = NULL; |
44 | desc->chip_data = NULL; | 40 | if (!keep_chip_data) |
41 | desc->chip_data = NULL; | ||
45 | desc->action = NULL; | 42 | desc->action = NULL; |
46 | desc->irq_count = 0; | 43 | desc->irq_count = 0; |
47 | desc->irqs_unhandled = 0; | 44 | desc->irqs_unhandled = 0; |
@@ -55,10 +52,26 @@ void dynamic_irq_init(unsigned int irq) | |||
55 | } | 52 | } |
56 | 53 | ||
57 | /** | 54 | /** |
58 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | 55 | * dynamic_irq_init - initialize a dynamically allocated irq |
59 | * @irq: irq number to initialize | 56 | * @irq: irq number to initialize |
60 | */ | 57 | */ |
61 | void dynamic_irq_cleanup(unsigned int irq) | 58 | void dynamic_irq_init(unsigned int irq) |
59 | { | ||
60 | dynamic_irq_init_x(irq, false); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * dynamic_irq_init_keep_chip_data - initialize a dynamically allocated irq | ||
65 | * @irq: irq number to initialize | ||
66 | * | ||
67 | * does not set irq_to_desc(irq)->chip_data to NULL | ||
68 | */ | ||
69 | void dynamic_irq_init_keep_chip_data(unsigned int irq) | ||
70 | { | ||
71 | dynamic_irq_init_x(irq, true); | ||
72 | } | ||
73 | |||
74 | static void dynamic_irq_cleanup_x(unsigned int irq, bool keep_chip_data) | ||
62 | { | 75 | { |
63 | struct irq_desc *desc = irq_to_desc(irq); | 76 | struct irq_desc *desc = irq_to_desc(irq); |
64 | unsigned long flags; | 77 | unsigned long flags; |
@@ -77,7 +90,8 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
77 | } | 90 | } |
78 | desc->msi_desc = NULL; | 91 | desc->msi_desc = NULL; |
79 | desc->handler_data = NULL; | 92 | desc->handler_data = NULL; |
80 | desc->chip_data = NULL; | 93 | if (!keep_chip_data) |
94 | desc->chip_data = NULL; | ||
81 | desc->handle_irq = handle_bad_irq; | 95 | desc->handle_irq = handle_bad_irq; |
82 | desc->chip = &no_irq_chip; | 96 | desc->chip = &no_irq_chip; |
83 | desc->name = NULL; | 97 | desc->name = NULL; |
@@ -85,6 +99,26 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
85 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 99 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
86 | } | 100 | } |
87 | 101 | ||
102 | /** | ||
103 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | ||
104 | * @irq: irq number to initialize | ||
105 | */ | ||
106 | void dynamic_irq_cleanup(unsigned int irq) | ||
107 | { | ||
108 | dynamic_irq_cleanup_x(irq, false); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * dynamic_irq_cleanup_keep_chip_data - cleanup a dynamically allocated irq | ||
113 | * @irq: irq number to initialize | ||
114 | * | ||
115 | * does not set irq_to_desc(irq)->chip_data to NULL | ||
116 | */ | ||
117 | void dynamic_irq_cleanup_keep_chip_data(unsigned int irq) | ||
118 | { | ||
119 | dynamic_irq_cleanup_x(irq, true); | ||
120 | } | ||
121 | |||
88 | 122 | ||
89 | /** | 123 | /** |
90 | * set_irq_chip - set the irq chip for an irq | 124 | * set_irq_chip - set the irq chip for an irq |
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 814940e7f485..76d5a671bfe1 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/kernel_stat.h> | 19 | #include <linux/kernel_stat.h> |
20 | #include <linux/rculist.h> | 20 | #include <linux/rculist.h> |
21 | #include <linux/hash.h> | 21 | #include <linux/hash.h> |
22 | #include <linux/bootmem.h> | 22 | #include <linux/radix-tree.h> |
23 | #include <trace/events/irq.h> | 23 | #include <trace/events/irq.h> |
24 | 24 | ||
25 | #include "internals.h" | 25 | #include "internals.h" |
@@ -87,12 +87,8 @@ void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr) | |||
87 | { | 87 | { |
88 | void *ptr; | 88 | void *ptr; |
89 | 89 | ||
90 | if (slab_is_available()) | 90 | ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), |
91 | ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), | 91 | GFP_ATOMIC, node); |
92 | GFP_ATOMIC, node); | ||
93 | else | ||
94 | ptr = alloc_bootmem_node(NODE_DATA(node), | ||
95 | nr * sizeof(*desc->kstat_irqs)); | ||
96 | 92 | ||
97 | /* | 93 | /* |
98 | * don't overwite if can not get new one | 94 | * don't overwite if can not get new one |
@@ -132,7 +128,26 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int node) | |||
132 | */ | 128 | */ |
133 | DEFINE_RAW_SPINLOCK(sparse_irq_lock); | 129 | DEFINE_RAW_SPINLOCK(sparse_irq_lock); |
134 | 130 | ||
135 | struct irq_desc **irq_desc_ptrs __read_mostly; | 131 | static RADIX_TREE(irq_desc_tree, GFP_ATOMIC); |
132 | |||
133 | static void set_irq_desc(unsigned int irq, struct irq_desc *desc) | ||
134 | { | ||
135 | radix_tree_insert(&irq_desc_tree, irq, desc); | ||
136 | } | ||
137 | |||
138 | struct irq_desc *irq_to_desc(unsigned int irq) | ||
139 | { | ||
140 | return radix_tree_lookup(&irq_desc_tree, irq); | ||
141 | } | ||
142 | |||
143 | void replace_irq_desc(unsigned int irq, struct irq_desc *desc) | ||
144 | { | ||
145 | void **ptr; | ||
146 | |||
147 | ptr = radix_tree_lookup_slot(&irq_desc_tree, irq); | ||
148 | if (ptr) | ||
149 | radix_tree_replace_slot(ptr, desc); | ||
150 | } | ||
136 | 151 | ||
137 | static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { | 152 | static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { |
138 | [0 ... NR_IRQS_LEGACY-1] = { | 153 | [0 ... NR_IRQS_LEGACY-1] = { |
@@ -164,9 +179,6 @@ int __init early_irq_init(void) | |||
164 | legacy_count = ARRAY_SIZE(irq_desc_legacy); | 179 | legacy_count = ARRAY_SIZE(irq_desc_legacy); |
165 | node = first_online_node; | 180 | node = first_online_node; |
166 | 181 | ||
167 | /* allocate irq_desc_ptrs array based on nr_irqs */ | ||
168 | irq_desc_ptrs = kcalloc(nr_irqs, sizeof(void *), GFP_NOWAIT); | ||
169 | |||
170 | /* allocate based on nr_cpu_ids */ | 182 | /* allocate based on nr_cpu_ids */ |
171 | kstat_irqs_legacy = kzalloc_node(NR_IRQS_LEGACY * nr_cpu_ids * | 183 | kstat_irqs_legacy = kzalloc_node(NR_IRQS_LEGACY * nr_cpu_ids * |
172 | sizeof(int), GFP_NOWAIT, node); | 184 | sizeof(int), GFP_NOWAIT, node); |
@@ -180,23 +192,12 @@ int __init early_irq_init(void) | |||
180 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); | 192 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); |
181 | alloc_desc_masks(&desc[i], node, true); | 193 | alloc_desc_masks(&desc[i], node, true); |
182 | init_desc_masks(&desc[i]); | 194 | init_desc_masks(&desc[i]); |
183 | irq_desc_ptrs[i] = desc + i; | 195 | set_irq_desc(i, &desc[i]); |
184 | } | 196 | } |
185 | 197 | ||
186 | for (i = legacy_count; i < nr_irqs; i++) | ||
187 | irq_desc_ptrs[i] = NULL; | ||
188 | |||
189 | return arch_early_irq_init(); | 198 | return arch_early_irq_init(); |
190 | } | 199 | } |
191 | 200 | ||
192 | struct irq_desc *irq_to_desc(unsigned int irq) | ||
193 | { | ||
194 | if (irq_desc_ptrs && irq < nr_irqs) | ||
195 | return irq_desc_ptrs[irq]; | ||
196 | |||
197 | return NULL; | ||
198 | } | ||
199 | |||
200 | struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) | 201 | struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) |
201 | { | 202 | { |
202 | struct irq_desc *desc; | 203 | struct irq_desc *desc; |
@@ -208,21 +209,18 @@ struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) | |||
208 | return NULL; | 209 | return NULL; |
209 | } | 210 | } |
210 | 211 | ||
211 | desc = irq_desc_ptrs[irq]; | 212 | desc = irq_to_desc(irq); |
212 | if (desc) | 213 | if (desc) |
213 | return desc; | 214 | return desc; |
214 | 215 | ||
215 | raw_spin_lock_irqsave(&sparse_irq_lock, flags); | 216 | raw_spin_lock_irqsave(&sparse_irq_lock, flags); |
216 | 217 | ||
217 | /* We have to check it to avoid races with another CPU */ | 218 | /* We have to check it to avoid races with another CPU */ |
218 | desc = irq_desc_ptrs[irq]; | 219 | desc = irq_to_desc(irq); |
219 | if (desc) | 220 | if (desc) |
220 | goto out_unlock; | 221 | goto out_unlock; |
221 | 222 | ||
222 | if (slab_is_available()) | 223 | desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); |
223 | desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); | ||
224 | else | ||
225 | desc = alloc_bootmem_node(NODE_DATA(node), sizeof(*desc)); | ||
226 | 224 | ||
227 | printk(KERN_DEBUG " alloc irq_desc for %d on node %d\n", irq, node); | 225 | printk(KERN_DEBUG " alloc irq_desc for %d on node %d\n", irq, node); |
228 | if (!desc) { | 226 | if (!desc) { |
@@ -231,7 +229,7 @@ struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node) | |||
231 | } | 229 | } |
232 | init_one_irq_desc(irq, desc, node); | 230 | init_one_irq_desc(irq, desc, node); |
233 | 231 | ||
234 | irq_desc_ptrs[irq] = desc; | 232 | set_irq_desc(irq, desc); |
235 | 233 | ||
236 | out_unlock: | 234 | out_unlock: |
237 | raw_spin_unlock_irqrestore(&sparse_irq_lock, flags); | 235 | raw_spin_unlock_irqrestore(&sparse_irq_lock, flags); |
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index b2821f070a3d..c63f3bc88f0b 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -21,11 +21,7 @@ extern void clear_kstat_irqs(struct irq_desc *desc); | |||
21 | extern raw_spinlock_t sparse_irq_lock; | 21 | extern raw_spinlock_t sparse_irq_lock; |
22 | 22 | ||
23 | #ifdef CONFIG_SPARSE_IRQ | 23 | #ifdef CONFIG_SPARSE_IRQ |
24 | /* irq_desc_ptrs allocated at boot time */ | 24 | void replace_irq_desc(unsigned int irq, struct irq_desc *desc); |
25 | extern struct irq_desc **irq_desc_ptrs; | ||
26 | #else | ||
27 | /* irq_desc_ptrs is a fixed size array */ | ||
28 | extern struct irq_desc *irq_desc_ptrs[NR_IRQS]; | ||
29 | #endif | 25 | #endif |
30 | 26 | ||
31 | #ifdef CONFIG_PROC_FS | 27 | #ifdef CONFIG_PROC_FS |
diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c index 26bac9d8f860..963559dbd858 100644 --- a/kernel/irq/numa_migrate.c +++ b/kernel/irq/numa_migrate.c | |||
@@ -70,7 +70,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, | |||
70 | raw_spin_lock_irqsave(&sparse_irq_lock, flags); | 70 | raw_spin_lock_irqsave(&sparse_irq_lock, flags); |
71 | 71 | ||
72 | /* We have to check it to avoid races with another CPU */ | 72 | /* We have to check it to avoid races with another CPU */ |
73 | desc = irq_desc_ptrs[irq]; | 73 | desc = irq_to_desc(irq); |
74 | 74 | ||
75 | if (desc && old_desc != desc) | 75 | if (desc && old_desc != desc) |
76 | goto out_unlock; | 76 | goto out_unlock; |
@@ -90,7 +90,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, | |||
90 | goto out_unlock; | 90 | goto out_unlock; |
91 | } | 91 | } |
92 | 92 | ||
93 | irq_desc_ptrs[irq] = desc; | 93 | replace_irq_desc(irq, desc); |
94 | raw_spin_unlock_irqrestore(&sparse_irq_lock, flags); | 94 | raw_spin_unlock_irqrestore(&sparse_irq_lock, flags); |
95 | 95 | ||
96 | /* free the old one */ | 96 | /* free the old one */ |
diff --git a/kernel/kexec.c b/kernel/kexec.c index ef077fb73155..87ebe8adc474 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <asm/sections.h> | 41 | #include <asm/sections.h> |
42 | 42 | ||
43 | /* Per cpu memory for storing cpu states in case of system crash. */ | 43 | /* Per cpu memory for storing cpu states in case of system crash. */ |
44 | note_buf_t* crash_notes; | 44 | note_buf_t __percpu *crash_notes; |
45 | 45 | ||
46 | /* vmcoreinfo stuff */ | 46 | /* vmcoreinfo stuff */ |
47 | static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES]; | 47 | static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES]; |
diff --git a/kernel/module.c b/kernel/module.c index f82386bd9ee9..e5538d5f00ad 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -474,9 +474,10 @@ static void module_unload_init(struct module *mod) | |||
474 | 474 | ||
475 | INIT_LIST_HEAD(&mod->modules_which_use_me); | 475 | INIT_LIST_HEAD(&mod->modules_which_use_me); |
476 | for_each_possible_cpu(cpu) | 476 | for_each_possible_cpu(cpu) |
477 | local_set(__module_ref_addr(mod, cpu), 0); | 477 | per_cpu_ptr(mod->refptr, cpu)->count = 0; |
478 | |||
478 | /* Hold reference count during initialization. */ | 479 | /* Hold reference count during initialization. */ |
479 | local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1); | 480 | __this_cpu_write(mod->refptr->count, 1); |
480 | /* Backwards compatibility macros put refcount during init. */ | 481 | /* Backwards compatibility macros put refcount during init. */ |
481 | mod->waiter = current; | 482 | mod->waiter = current; |
482 | } | 483 | } |
@@ -619,7 +620,7 @@ unsigned int module_refcount(struct module *mod) | |||
619 | int cpu; | 620 | int cpu; |
620 | 621 | ||
621 | for_each_possible_cpu(cpu) | 622 | for_each_possible_cpu(cpu) |
622 | total += local_read(__module_ref_addr(mod, cpu)); | 623 | total += per_cpu_ptr(mod->refptr, cpu)->count; |
623 | return total; | 624 | return total; |
624 | } | 625 | } |
625 | EXPORT_SYMBOL(module_refcount); | 626 | EXPORT_SYMBOL(module_refcount); |
@@ -796,14 +797,15 @@ static struct module_attribute refcnt = { | |||
796 | void module_put(struct module *module) | 797 | void module_put(struct module *module) |
797 | { | 798 | { |
798 | if (module) { | 799 | if (module) { |
799 | unsigned int cpu = get_cpu(); | 800 | preempt_disable(); |
800 | local_dec(__module_ref_addr(module, cpu)); | 801 | __this_cpu_dec(module->refptr->count); |
802 | |||
801 | trace_module_put(module, _RET_IP_, | 803 | trace_module_put(module, _RET_IP_, |
802 | local_read(__module_ref_addr(module, cpu))); | 804 | __this_cpu_read(module->refptr->count)); |
803 | /* Maybe they're waiting for us to drop reference? */ | 805 | /* Maybe they're waiting for us to drop reference? */ |
804 | if (unlikely(!module_is_live(module))) | 806 | if (unlikely(!module_is_live(module))) |
805 | wake_up_process(module->waiter); | 807 | wake_up_process(module->waiter); |
806 | put_cpu(); | 808 | preempt_enable(); |
807 | } | 809 | } |
808 | } | 810 | } |
809 | EXPORT_SYMBOL(module_put); | 811 | EXPORT_SYMBOL(module_put); |
@@ -1397,9 +1399,9 @@ static void free_module(struct module *mod) | |||
1397 | kfree(mod->args); | 1399 | kfree(mod->args); |
1398 | if (mod->percpu) | 1400 | if (mod->percpu) |
1399 | percpu_modfree(mod->percpu); | 1401 | percpu_modfree(mod->percpu); |
1400 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 1402 | #if defined(CONFIG_MODULE_UNLOAD) |
1401 | if (mod->refptr) | 1403 | if (mod->refptr) |
1402 | percpu_modfree(mod->refptr); | 1404 | free_percpu(mod->refptr); |
1403 | #endif | 1405 | #endif |
1404 | /* Free lock-classes: */ | 1406 | /* Free lock-classes: */ |
1405 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1407 | lockdep_free_key_range(mod->module_core, mod->core_size); |
@@ -2162,9 +2164,8 @@ static noinline struct module *load_module(void __user *umod, | |||
2162 | mod = (void *)sechdrs[modindex].sh_addr; | 2164 | mod = (void *)sechdrs[modindex].sh_addr; |
2163 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); | 2165 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); |
2164 | 2166 | ||
2165 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2167 | #if defined(CONFIG_MODULE_UNLOAD) |
2166 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | 2168 | mod->refptr = alloc_percpu(struct module_ref); |
2167 | mod->name); | ||
2168 | if (!mod->refptr) { | 2169 | if (!mod->refptr) { |
2169 | err = -ENOMEM; | 2170 | err = -ENOMEM; |
2170 | goto free_init; | 2171 | goto free_init; |
@@ -2396,8 +2397,8 @@ static noinline struct module *load_module(void __user *umod, | |||
2396 | kobject_put(&mod->mkobj.kobj); | 2397 | kobject_put(&mod->mkobj.kobj); |
2397 | free_unload: | 2398 | free_unload: |
2398 | module_unload_free(mod); | 2399 | module_unload_free(mod); |
2399 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2400 | #if defined(CONFIG_MODULE_UNLOAD) |
2400 | percpu_modfree(mod->refptr); | 2401 | free_percpu(mod->refptr); |
2401 | free_init: | 2402 | free_init: |
2402 | #endif | 2403 | #endif |
2403 | module_free(mod, mod->module_init); | 2404 | module_free(mod, mod->module_init); |
diff --git a/kernel/printk.c b/kernel/printk.c index 1751c456b71f..40674122ecf2 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/kexec.h> | 35 | #include <linux/kexec.h> |
36 | #include <linux/ratelimit.h> | 36 | #include <linux/ratelimit.h> |
37 | #include <linux/kmsg_dump.h> | 37 | #include <linux/kmsg_dump.h> |
38 | #include <linux/syslog.h> | ||
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | 41 | ||
@@ -258,38 +259,23 @@ static inline void boot_delay_msec(void) | |||
258 | } | 259 | } |
259 | #endif | 260 | #endif |
260 | 261 | ||
261 | /* | 262 | int do_syslog(int type, char __user *buf, int len, bool from_file) |
262 | * Commands to do_syslog: | ||
263 | * | ||
264 | * 0 -- Close the log. Currently a NOP. | ||
265 | * 1 -- Open the log. Currently a NOP. | ||
266 | * 2 -- Read from the log. | ||
267 | * 3 -- Read all messages remaining in the ring buffer. | ||
268 | * 4 -- Read and clear all messages remaining in the ring buffer | ||
269 | * 5 -- Clear ring buffer. | ||
270 | * 6 -- Disable printk's to console | ||
271 | * 7 -- Enable printk's to console | ||
272 | * 8 -- Set level of messages printed to console | ||
273 | * 9 -- Return number of unread characters in the log buffer | ||
274 | * 10 -- Return size of the log buffer | ||
275 | */ | ||
276 | int do_syslog(int type, char __user *buf, int len) | ||
277 | { | 263 | { |
278 | unsigned i, j, limit, count; | 264 | unsigned i, j, limit, count; |
279 | int do_clear = 0; | 265 | int do_clear = 0; |
280 | char c; | 266 | char c; |
281 | int error = 0; | 267 | int error = 0; |
282 | 268 | ||
283 | error = security_syslog(type); | 269 | error = security_syslog(type, from_file); |
284 | if (error) | 270 | if (error) |
285 | return error; | 271 | return error; |
286 | 272 | ||
287 | switch (type) { | 273 | switch (type) { |
288 | case 0: /* Close log */ | 274 | case SYSLOG_ACTION_CLOSE: /* Close log */ |
289 | break; | 275 | break; |
290 | case 1: /* Open log */ | 276 | case SYSLOG_ACTION_OPEN: /* Open log */ |
291 | break; | 277 | break; |
292 | case 2: /* Read from log */ | 278 | case SYSLOG_ACTION_READ: /* Read from log */ |
293 | error = -EINVAL; | 279 | error = -EINVAL; |
294 | if (!buf || len < 0) | 280 | if (!buf || len < 0) |
295 | goto out; | 281 | goto out; |
@@ -320,10 +306,12 @@ int do_syslog(int type, char __user *buf, int len) | |||
320 | if (!error) | 306 | if (!error) |
321 | error = i; | 307 | error = i; |
322 | break; | 308 | break; |
323 | case 4: /* Read/clear last kernel messages */ | 309 | /* Read/clear last kernel messages */ |
310 | case SYSLOG_ACTION_READ_CLEAR: | ||
324 | do_clear = 1; | 311 | do_clear = 1; |
325 | /* FALL THRU */ | 312 | /* FALL THRU */ |
326 | case 3: /* Read last kernel messages */ | 313 | /* Read last kernel messages */ |
314 | case SYSLOG_ACTION_READ_ALL: | ||
327 | error = -EINVAL; | 315 | error = -EINVAL; |
328 | if (!buf || len < 0) | 316 | if (!buf || len < 0) |
329 | goto out; | 317 | goto out; |
@@ -376,21 +364,25 @@ int do_syslog(int type, char __user *buf, int len) | |||
376 | } | 364 | } |
377 | } | 365 | } |
378 | break; | 366 | break; |
379 | case 5: /* Clear ring buffer */ | 367 | /* Clear ring buffer */ |
368 | case SYSLOG_ACTION_CLEAR: | ||
380 | logged_chars = 0; | 369 | logged_chars = 0; |
381 | break; | 370 | break; |
382 | case 6: /* Disable logging to console */ | 371 | /* Disable logging to console */ |
372 | case SYSLOG_ACTION_CONSOLE_OFF: | ||
383 | if (saved_console_loglevel == -1) | 373 | if (saved_console_loglevel == -1) |
384 | saved_console_loglevel = console_loglevel; | 374 | saved_console_loglevel = console_loglevel; |
385 | console_loglevel = minimum_console_loglevel; | 375 | console_loglevel = minimum_console_loglevel; |
386 | break; | 376 | break; |
387 | case 7: /* Enable logging to console */ | 377 | /* Enable logging to console */ |
378 | case SYSLOG_ACTION_CONSOLE_ON: | ||
388 | if (saved_console_loglevel != -1) { | 379 | if (saved_console_loglevel != -1) { |
389 | console_loglevel = saved_console_loglevel; | 380 | console_loglevel = saved_console_loglevel; |
390 | saved_console_loglevel = -1; | 381 | saved_console_loglevel = -1; |
391 | } | 382 | } |
392 | break; | 383 | break; |
393 | case 8: /* Set level of messages printed to console */ | 384 | /* Set level of messages printed to console */ |
385 | case SYSLOG_ACTION_CONSOLE_LEVEL: | ||
394 | error = -EINVAL; | 386 | error = -EINVAL; |
395 | if (len < 1 || len > 8) | 387 | if (len < 1 || len > 8) |
396 | goto out; | 388 | goto out; |
@@ -401,10 +393,12 @@ int do_syslog(int type, char __user *buf, int len) | |||
401 | saved_console_loglevel = -1; | 393 | saved_console_loglevel = -1; |
402 | error = 0; | 394 | error = 0; |
403 | break; | 395 | break; |
404 | case 9: /* Number of chars in the log buffer */ | 396 | /* Number of chars in the log buffer */ |
397 | case SYSLOG_ACTION_SIZE_UNREAD: | ||
405 | error = log_end - log_start; | 398 | error = log_end - log_start; |
406 | break; | 399 | break; |
407 | case 10: /* Size of the log buffer */ | 400 | /* Size of the log buffer */ |
401 | case SYSLOG_ACTION_SIZE_BUFFER: | ||
408 | error = log_buf_len; | 402 | error = log_buf_len; |
409 | break; | 403 | break; |
410 | default: | 404 | default: |
@@ -417,7 +411,7 @@ out: | |||
417 | 411 | ||
418 | SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) | 412 | SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) |
419 | { | 413 | { |
420 | return do_syslog(type, buf, len); | 414 | return do_syslog(type, buf, len, SYSLOG_FROM_CALL); |
421 | } | 415 | } |
422 | 416 | ||
423 | /* | 417 | /* |
diff --git a/kernel/range.c b/kernel/range.c new file mode 100644 index 000000000000..74e2e6114927 --- /dev/null +++ b/kernel/range.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * Range add and subtract | ||
3 | */ | ||
4 | #include <linux/module.h> | ||
5 | #include <linux/init.h> | ||
6 | #include <linux/sort.h> | ||
7 | |||
8 | #include <linux/range.h> | ||
9 | |||
10 | #ifndef ARRAY_SIZE | ||
11 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
12 | #endif | ||
13 | |||
14 | int add_range(struct range *range, int az, int nr_range, u64 start, u64 end) | ||
15 | { | ||
16 | if (start >= end) | ||
17 | return nr_range; | ||
18 | |||
19 | /* Out of slots: */ | ||
20 | if (nr_range >= az) | ||
21 | return nr_range; | ||
22 | |||
23 | range[nr_range].start = start; | ||
24 | range[nr_range].end = end; | ||
25 | |||
26 | nr_range++; | ||
27 | |||
28 | return nr_range; | ||
29 | } | ||
30 | |||
31 | int add_range_with_merge(struct range *range, int az, int nr_range, | ||
32 | u64 start, u64 end) | ||
33 | { | ||
34 | int i; | ||
35 | |||
36 | if (start >= end) | ||
37 | return nr_range; | ||
38 | |||
39 | /* Try to merge it with old one: */ | ||
40 | for (i = 0; i < nr_range; i++) { | ||
41 | u64 final_start, final_end; | ||
42 | u64 common_start, common_end; | ||
43 | |||
44 | if (!range[i].end) | ||
45 | continue; | ||
46 | |||
47 | common_start = max(range[i].start, start); | ||
48 | common_end = min(range[i].end, end); | ||
49 | if (common_start > common_end) | ||
50 | continue; | ||
51 | |||
52 | final_start = min(range[i].start, start); | ||
53 | final_end = max(range[i].end, end); | ||
54 | |||
55 | range[i].start = final_start; | ||
56 | range[i].end = final_end; | ||
57 | return nr_range; | ||
58 | } | ||
59 | |||
60 | /* Need to add it: */ | ||
61 | return add_range(range, az, nr_range, start, end); | ||
62 | } | ||
63 | |||
64 | void subtract_range(struct range *range, int az, u64 start, u64 end) | ||
65 | { | ||
66 | int i, j; | ||
67 | |||
68 | if (start >= end) | ||
69 | return; | ||
70 | |||
71 | for (j = 0; j < az; j++) { | ||
72 | if (!range[j].end) | ||
73 | continue; | ||
74 | |||
75 | if (start <= range[j].start && end >= range[j].end) { | ||
76 | range[j].start = 0; | ||
77 | range[j].end = 0; | ||
78 | continue; | ||
79 | } | ||
80 | |||
81 | if (start <= range[j].start && end < range[j].end && | ||
82 | range[j].start < end) { | ||
83 | range[j].start = end; | ||
84 | continue; | ||
85 | } | ||
86 | |||
87 | |||
88 | if (start > range[j].start && end >= range[j].end && | ||
89 | range[j].end > start) { | ||
90 | range[j].end = start; | ||
91 | continue; | ||
92 | } | ||
93 | |||
94 | if (start > range[j].start && end < range[j].end) { | ||
95 | /* Find the new spare: */ | ||
96 | for (i = 0; i < az; i++) { | ||
97 | if (range[i].end == 0) | ||
98 | break; | ||
99 | } | ||
100 | if (i < az) { | ||
101 | range[i].end = range[j].end; | ||
102 | range[i].start = end; | ||
103 | } else { | ||
104 | printk(KERN_ERR "run of slot in ranges\n"); | ||
105 | } | ||
106 | range[j].end = start; | ||
107 | continue; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | static int cmp_range(const void *x1, const void *x2) | ||
113 | { | ||
114 | const struct range *r1 = x1; | ||
115 | const struct range *r2 = x2; | ||
116 | s64 start1, start2; | ||
117 | |||
118 | start1 = r1->start; | ||
119 | start2 = r2->start; | ||
120 | |||
121 | return start1 - start2; | ||
122 | } | ||
123 | |||
124 | int clean_sort_range(struct range *range, int az) | ||
125 | { | ||
126 | int i, j, k = az - 1, nr_range = 0; | ||
127 | |||
128 | for (i = 0; i < k; i++) { | ||
129 | if (range[i].end) | ||
130 | continue; | ||
131 | for (j = k; j > i; j--) { | ||
132 | if (range[j].end) { | ||
133 | k = j; | ||
134 | break; | ||
135 | } | ||
136 | } | ||
137 | if (j == i) | ||
138 | break; | ||
139 | range[i].start = range[k].start; | ||
140 | range[i].end = range[k].end; | ||
141 | range[k].start = 0; | ||
142 | range[k].end = 0; | ||
143 | k--; | ||
144 | } | ||
145 | /* count it */ | ||
146 | for (i = 0; i < az; i++) { | ||
147 | if (!range[i].end) { | ||
148 | nr_range = i; | ||
149 | break; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /* sort them */ | ||
154 | sort(range, nr_range, sizeof(struct range), cmp_range, NULL); | ||
155 | |||
156 | return nr_range; | ||
157 | } | ||
158 | |||
159 | void sort_range(struct range *range, int nr_range) | ||
160 | { | ||
161 | /* sort them */ | ||
162 | sort(range, nr_range, sizeof(struct range), cmp_range, NULL); | ||
163 | } | ||
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 258cdf0a91eb..58df55bf83ed 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
@@ -818,13 +818,13 @@ static void rcu_torture_timer(unsigned long unused) | |||
818 | /* Should not happen, but... */ | 818 | /* Should not happen, but... */ |
819 | pipe_count = RCU_TORTURE_PIPE_LEN; | 819 | pipe_count = RCU_TORTURE_PIPE_LEN; |
820 | } | 820 | } |
821 | __this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]); | 821 | __this_cpu_inc(rcu_torture_count[pipe_count]); |
822 | completed = cur_ops->completed() - completed; | 822 | completed = cur_ops->completed() - completed; |
823 | if (completed > RCU_TORTURE_PIPE_LEN) { | 823 | if (completed > RCU_TORTURE_PIPE_LEN) { |
824 | /* Should not happen, but... */ | 824 | /* Should not happen, but... */ |
825 | completed = RCU_TORTURE_PIPE_LEN; | 825 | completed = RCU_TORTURE_PIPE_LEN; |
826 | } | 826 | } |
827 | __this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]); | 827 | __this_cpu_inc(rcu_torture_batch[completed]); |
828 | preempt_enable(); | 828 | preempt_enable(); |
829 | cur_ops->readunlock(idx); | 829 | cur_ops->readunlock(idx); |
830 | } | 830 | } |
@@ -877,13 +877,13 @@ rcu_torture_reader(void *arg) | |||
877 | /* Should not happen, but... */ | 877 | /* Should not happen, but... */ |
878 | pipe_count = RCU_TORTURE_PIPE_LEN; | 878 | pipe_count = RCU_TORTURE_PIPE_LEN; |
879 | } | 879 | } |
880 | __this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]); | 880 | __this_cpu_inc(rcu_torture_count[pipe_count]); |
881 | completed = cur_ops->completed() - completed; | 881 | completed = cur_ops->completed() - completed; |
882 | if (completed > RCU_TORTURE_PIPE_LEN) { | 882 | if (completed > RCU_TORTURE_PIPE_LEN) { |
883 | /* Should not happen, but... */ | 883 | /* Should not happen, but... */ |
884 | completed = RCU_TORTURE_PIPE_LEN; | 884 | completed = RCU_TORTURE_PIPE_LEN; |
885 | } | 885 | } |
886 | __this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]); | 886 | __this_cpu_inc(rcu_torture_batch[completed]); |
887 | preempt_enable(); | 887 | preempt_enable(); |
888 | cur_ops->readunlock(idx); | 888 | cur_ops->readunlock(idx); |
889 | schedule(); | 889 | schedule(); |
diff --git a/kernel/resource.c b/kernel/resource.c index 4e9d87fd7bc5..2d5be5d9bf5f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -304,7 +304,7 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | |||
304 | void *arg, int (*func)(unsigned long, unsigned long, void *)) | 304 | void *arg, int (*func)(unsigned long, unsigned long, void *)) |
305 | { | 305 | { |
306 | struct resource res; | 306 | struct resource res; |
307 | unsigned long pfn, len; | 307 | unsigned long pfn, end_pfn; |
308 | u64 orig_end; | 308 | u64 orig_end; |
309 | int ret = -1; | 309 | int ret = -1; |
310 | 310 | ||
@@ -314,9 +314,10 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | |||
314 | orig_end = res.end; | 314 | orig_end = res.end; |
315 | while ((res.start < res.end) && | 315 | while ((res.start < res.end) && |
316 | (find_next_system_ram(&res, "System RAM") >= 0)) { | 316 | (find_next_system_ram(&res, "System RAM") >= 0)) { |
317 | pfn = (unsigned long)(res.start >> PAGE_SHIFT); | 317 | pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; |
318 | len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT); | 318 | end_pfn = (res.end + 1) >> PAGE_SHIFT; |
319 | ret = (*func)(pfn, len, arg); | 319 | if (end_pfn > pfn) |
320 | ret = (*func)(pfn, end_pfn - pfn, arg); | ||
320 | if (ret) | 321 | if (ret) |
321 | break; | 322 | break; |
322 | res.start = res.end + 1; | 323 | res.start = res.end + 1; |
diff --git a/kernel/sched.c b/kernel/sched.c index 6a212c97f523..abb36b16b93b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1521,7 +1521,7 @@ static unsigned long cpu_avg_load_per_task(int cpu) | |||
1521 | 1521 | ||
1522 | #ifdef CONFIG_FAIR_GROUP_SCHED | 1522 | #ifdef CONFIG_FAIR_GROUP_SCHED |
1523 | 1523 | ||
1524 | static __read_mostly unsigned long *update_shares_data; | 1524 | static __read_mostly unsigned long __percpu *update_shares_data; |
1525 | 1525 | ||
1526 | static void __set_se_shares(struct sched_entity *se, unsigned long shares); | 1526 | static void __set_se_shares(struct sched_entity *se, unsigned long shares); |
1527 | 1527 | ||
@@ -8813,7 +8813,7 @@ struct cgroup_subsys cpu_cgroup_subsys = { | |||
8813 | struct cpuacct { | 8813 | struct cpuacct { |
8814 | struct cgroup_subsys_state css; | 8814 | struct cgroup_subsys_state css; |
8815 | /* cpuusage holds pointer to a u64-type object on every cpu */ | 8815 | /* cpuusage holds pointer to a u64-type object on every cpu */ |
8816 | u64 *cpuusage; | 8816 | u64 __percpu *cpuusage; |
8817 | struct percpu_counter cpustat[CPUACCT_STAT_NSTATS]; | 8817 | struct percpu_counter cpustat[CPUACCT_STAT_NSTATS]; |
8818 | struct cpuacct *parent; | 8818 | struct cpuacct *parent; |
8819 | }; | 8819 | }; |
diff --git a/kernel/signal.c b/kernel/signal.c index 934ae5e687b9..5bb9baffa4f1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -159,6 +159,10 @@ void recalc_sigpending(void) | |||
159 | 159 | ||
160 | /* Given the mask, find the first available signal that should be serviced. */ | 160 | /* Given the mask, find the first available signal that should be serviced. */ |
161 | 161 | ||
162 | #define SYNCHRONOUS_MASK \ | ||
163 | (sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \ | ||
164 | sigmask(SIGTRAP) | sigmask(SIGFPE)) | ||
165 | |||
162 | int next_signal(struct sigpending *pending, sigset_t *mask) | 166 | int next_signal(struct sigpending *pending, sigset_t *mask) |
163 | { | 167 | { |
164 | unsigned long i, *s, *m, x; | 168 | unsigned long i, *s, *m, x; |
@@ -166,26 +170,39 @@ int next_signal(struct sigpending *pending, sigset_t *mask) | |||
166 | 170 | ||
167 | s = pending->signal.sig; | 171 | s = pending->signal.sig; |
168 | m = mask->sig; | 172 | m = mask->sig; |
173 | |||
174 | /* | ||
175 | * Handle the first word specially: it contains the | ||
176 | * synchronous signals that need to be dequeued first. | ||
177 | */ | ||
178 | x = *s &~ *m; | ||
179 | if (x) { | ||
180 | if (x & SYNCHRONOUS_MASK) | ||
181 | x &= SYNCHRONOUS_MASK; | ||
182 | sig = ffz(~x) + 1; | ||
183 | return sig; | ||
184 | } | ||
185 | |||
169 | switch (_NSIG_WORDS) { | 186 | switch (_NSIG_WORDS) { |
170 | default: | 187 | default: |
171 | for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m) | 188 | for (i = 1; i < _NSIG_WORDS; ++i) { |
172 | if ((x = *s &~ *m) != 0) { | 189 | x = *++s &~ *++m; |
173 | sig = ffz(~x) + i*_NSIG_BPW + 1; | 190 | if (!x) |
174 | break; | 191 | continue; |
175 | } | 192 | sig = ffz(~x) + i*_NSIG_BPW + 1; |
193 | break; | ||
194 | } | ||
176 | break; | 195 | break; |
177 | 196 | ||
178 | case 2: if ((x = s[0] &~ m[0]) != 0) | 197 | case 2: |
179 | sig = 1; | 198 | x = s[1] &~ m[1]; |
180 | else if ((x = s[1] &~ m[1]) != 0) | 199 | if (!x) |
181 | sig = _NSIG_BPW + 1; | ||
182 | else | ||
183 | break; | 200 | break; |
184 | sig += ffz(~x); | 201 | sig = ffz(~x) + _NSIG_BPW + 1; |
185 | break; | 202 | break; |
186 | 203 | ||
187 | case 1: if ((x = *s &~ *m) != 0) | 204 | case 1: |
188 | sig = ffz(~x) + 1; | 205 | /* Nothing to do */ |
189 | break; | 206 | break; |
190 | } | 207 | } |
191 | 208 | ||
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 912823e2a11b..9bb9fb1bd79c 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
@@ -45,7 +45,7 @@ static int refcount; | |||
45 | static struct workqueue_struct *stop_machine_wq; | 45 | static struct workqueue_struct *stop_machine_wq; |
46 | static struct stop_machine_data active, idle; | 46 | static struct stop_machine_data active, idle; |
47 | static const struct cpumask *active_cpus; | 47 | static const struct cpumask *active_cpus; |
48 | static void *stop_machine_work; | 48 | static void __percpu *stop_machine_work; |
49 | 49 | ||
50 | static void set_state(enum stopmachine_state newstate) | 50 | static void set_state(enum stopmachine_state newstate) |
51 | { | 51 | { |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8a68b2448468..33e7a38b6eb9 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -1441,7 +1441,7 @@ static struct ctl_table fs_table[] = { | |||
1441 | }; | 1441 | }; |
1442 | 1442 | ||
1443 | static struct ctl_table debug_table[] = { | 1443 | static struct ctl_table debug_table[] = { |
1444 | #if defined(CONFIG_X86) || defined(CONFIG_PPC) | 1444 | #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) |
1445 | { | 1445 | { |
1446 | .procname = "exception-trace", | 1446 | .procname = "exception-trace", |
1447 | .data = &show_unhandled_signals, | 1447 | .data = &show_unhandled_signals, |
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index 8f5d16e0707a..8cd50d8f9bde 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c | |||
@@ -1331,7 +1331,7 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
1331 | ssize_t result; | 1331 | ssize_t result; |
1332 | char *pathname; | 1332 | char *pathname; |
1333 | int flags; | 1333 | int flags; |
1334 | int acc_mode, fmode; | 1334 | int acc_mode; |
1335 | 1335 | ||
1336 | pathname = sysctl_getname(name, nlen, &table); | 1336 | pathname = sysctl_getname(name, nlen, &table); |
1337 | result = PTR_ERR(pathname); | 1337 | result = PTR_ERR(pathname); |
@@ -1342,15 +1342,12 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
1342 | if (oldval && oldlen && newval && newlen) { | 1342 | if (oldval && oldlen && newval && newlen) { |
1343 | flags = O_RDWR; | 1343 | flags = O_RDWR; |
1344 | acc_mode = MAY_READ | MAY_WRITE; | 1344 | acc_mode = MAY_READ | MAY_WRITE; |
1345 | fmode = FMODE_READ | FMODE_WRITE; | ||
1346 | } else if (newval && newlen) { | 1345 | } else if (newval && newlen) { |
1347 | flags = O_WRONLY; | 1346 | flags = O_WRONLY; |
1348 | acc_mode = MAY_WRITE; | 1347 | acc_mode = MAY_WRITE; |
1349 | fmode = FMODE_WRITE; | ||
1350 | } else if (oldval && oldlen) { | 1348 | } else if (oldval && oldlen) { |
1351 | flags = O_RDONLY; | 1349 | flags = O_RDONLY; |
1352 | acc_mode = MAY_READ; | 1350 | acc_mode = MAY_READ; |
1353 | fmode = FMODE_READ; | ||
1354 | } else { | 1351 | } else { |
1355 | result = 0; | 1352 | result = 0; |
1356 | goto out_putname; | 1353 | goto out_putname; |
@@ -1361,7 +1358,7 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
1361 | if (result) | 1358 | if (result) |
1362 | goto out_putname; | 1359 | goto out_putname; |
1363 | 1360 | ||
1364 | result = may_open(&nd.path, acc_mode, fmode); | 1361 | result = may_open(&nd.path, acc_mode, flags); |
1365 | if (result) | 1362 | if (result) |
1366 | goto out_putpath; | 1363 | goto out_putpath; |
1367 | 1364 | ||
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index ea8384d3caa7..899ca51be5e8 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -46,15 +46,13 @@ static struct genl_family family = { | |||
46 | .maxattr = TASKSTATS_CMD_ATTR_MAX, | 46 | .maxattr = TASKSTATS_CMD_ATTR_MAX, |
47 | }; | 47 | }; |
48 | 48 | ||
49 | static struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] | 49 | static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = { |
50 | __read_mostly = { | ||
51 | [TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 }, | 50 | [TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 }, |
52 | [TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 }, | 51 | [TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 }, |
53 | [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING }, | 52 | [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING }, |
54 | [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },}; | 53 | [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },}; |
55 | 54 | ||
56 | static struct nla_policy | 55 | static const struct nla_policy cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_MAX+1] = { |
57 | cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_MAX+1] __read_mostly = { | ||
58 | [CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 }, | 56 | [CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 }, |
59 | }; | 57 | }; |
60 | 58 | ||
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 8c1b2d290718..0287f9f52f5a 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | 22 | ||
23 | #include <asm/local.h> | ||
23 | #include "trace.h" | 24 | #include "trace.h" |
24 | 25 | ||
25 | /* | 26 | /* |
diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index b2477caf09c2..df74c7982255 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/kthread.h> | 8 | #include <linux/kthread.h> |
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/time.h> | 10 | #include <linux/time.h> |
11 | #include <asm/local.h> | ||
11 | 12 | ||
12 | struct rb_page { | 13 | struct rb_page { |
13 | u64 ts; | 14 | u64 ts; |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 032c57ca6502..ed01fdba4a55 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -92,12 +92,12 @@ DEFINE_PER_CPU(int, ftrace_cpu_disabled); | |||
92 | static inline void ftrace_disable_cpu(void) | 92 | static inline void ftrace_disable_cpu(void) |
93 | { | 93 | { |
94 | preempt_disable(); | 94 | preempt_disable(); |
95 | __this_cpu_inc(per_cpu_var(ftrace_cpu_disabled)); | 95 | __this_cpu_inc(ftrace_cpu_disabled); |
96 | } | 96 | } |
97 | 97 | ||
98 | static inline void ftrace_enable_cpu(void) | 98 | static inline void ftrace_enable_cpu(void) |
99 | { | 99 | { |
100 | __this_cpu_dec(per_cpu_var(ftrace_cpu_disabled)); | 100 | __this_cpu_dec(ftrace_cpu_disabled); |
101 | preempt_enable(); | 101 | preempt_enable(); |
102 | } | 102 | } |
103 | 103 | ||
@@ -1166,7 +1166,7 @@ trace_function(struct trace_array *tr, | |||
1166 | struct ftrace_entry *entry; | 1166 | struct ftrace_entry *entry; |
1167 | 1167 | ||
1168 | /* If we are reading the ring buffer, don't trace */ | 1168 | /* If we are reading the ring buffer, don't trace */ |
1169 | if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled)))) | 1169 | if (unlikely(__this_cpu_read(ftrace_cpu_disabled))) |
1170 | return; | 1170 | return; |
1171 | 1171 | ||
1172 | event = trace_buffer_lock_reserve(buffer, TRACE_FN, sizeof(*entry), | 1172 | event = trace_buffer_lock_reserve(buffer, TRACE_FN, sizeof(*entry), |
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index e998a824e9db..3fc2a575664f 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
@@ -188,7 +188,7 @@ static int __trace_graph_entry(struct trace_array *tr, | |||
188 | struct ring_buffer *buffer = tr->buffer; | 188 | struct ring_buffer *buffer = tr->buffer; |
189 | struct ftrace_graph_ent_entry *entry; | 189 | struct ftrace_graph_ent_entry *entry; |
190 | 190 | ||
191 | if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled)))) | 191 | if (unlikely(__this_cpu_read(ftrace_cpu_disabled))) |
192 | return 0; | 192 | return 0; |
193 | 193 | ||
194 | event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT, | 194 | event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT, |
@@ -247,7 +247,7 @@ static void __trace_graph_return(struct trace_array *tr, | |||
247 | struct ring_buffer *buffer = tr->buffer; | 247 | struct ring_buffer *buffer = tr->buffer; |
248 | struct ftrace_graph_ret_entry *entry; | 248 | struct ftrace_graph_ret_entry *entry; |
249 | 249 | ||
250 | if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled)))) | 250 | if (unlikely(__this_cpu_read(ftrace_cpu_disabled))) |
251 | return; | 251 | return; |
252 | 252 | ||
253 | event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RET, | 253 | event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RET, |