diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-11 22:34:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-11 22:34:09 -0400 |
commit | 01b0c014eeb0bb857a5dc572cd108be7becddfe7 (patch) | |
tree | d6f1a089081aadb09e66add27f7c5137d076ac80 | |
parent | 3ebb0540c20d6670396ccee9ff6794c095fa9311 (diff) | |
parent | e527b22c3f63c02832ac4cb8ed0ec3a9b638bbdf (diff) |
Merge branch 'akpm' (patches from Andrew)
Merge fourth patch-bomb from Andrew Morton:
- sys_membarier syscall
- seq_file interface changes
- a few misc fixups
* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
revert "ocfs2/dlm: use list_for_each_entry instead of list_for_each"
mm/early_ioremap: add explicit #include of asm/early_ioremap.h
fs/seq_file: convert int seq_vprint/seq_printf/etc... returns to void
selftests: enhance membarrier syscall test
selftests: add membarrier syscall test
sys_membarrier(): system-wide memory barrier (generic, x86)
MODSIGN: fix a compilation warning in extract-cert
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | arch/x86/entry/syscalls/syscall_32.tbl | 1 | ||||
-rw-r--r-- | arch/x86/entry/syscalls/syscall_64.tbl | 1 | ||||
-rw-r--r-- | drivers/iommu/omap-iommu-debug.c | 3 | ||||
-rw-r--r-- | fs/nsfs.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmrecovery.c | 6 | ||||
-rw-r--r-- | fs/seq_file.c | 70 | ||||
-rw-r--r-- | include/linux/seq_file.h | 19 | ||||
-rw-r--r-- | include/linux/syscalls.h | 2 | ||||
-rw-r--r-- | include/uapi/asm-generic/unistd.h | 4 | ||||
-rw-r--r-- | include/uapi/linux/Kbuild | 1 | ||||
-rw-r--r-- | include/uapi/linux/membarrier.h | 53 | ||||
-rw-r--r-- | init/Kconfig | 12 | ||||
-rw-r--r-- | kernel/Makefile | 1 | ||||
-rw-r--r-- | kernel/membarrier.c | 66 | ||||
-rw-r--r-- | kernel/sys_ni.c | 3 | ||||
-rw-r--r-- | mm/early_ioremap.c | 1 | ||||
-rw-r--r-- | scripts/extract-cert.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/Makefile | 1 | ||||
-rw-r--r-- | tools/testing/selftests/membarrier/.gitignore | 1 | ||||
-rw-r--r-- | tools/testing/selftests/membarrier/Makefile | 11 | ||||
-rw-r--r-- | tools/testing/selftests/membarrier/membarrier_test.c | 121 |
22 files changed, 336 insertions, 54 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 030d8724b476..7ba7ab749c85 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6789,6 +6789,14 @@ W: http://www.mellanox.com | |||
6789 | Q: http://patchwork.ozlabs.org/project/netdev/list/ | 6789 | Q: http://patchwork.ozlabs.org/project/netdev/list/ |
6790 | F: drivers/net/ethernet/mellanox/mlxsw/ | 6790 | F: drivers/net/ethernet/mellanox/mlxsw/ |
6791 | 6791 | ||
6792 | MEMBARRIER SUPPORT | ||
6793 | M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
6794 | M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> | ||
6795 | L: linux-kernel@vger.kernel.org | ||
6796 | S: Supported | ||
6797 | F: kernel/membarrier.c | ||
6798 | F: include/uapi/linux/membarrier.h | ||
6799 | |||
6792 | MEMORY MANAGEMENT | 6800 | MEMORY MANAGEMENT |
6793 | L: linux-mm@kvack.org | 6801 | L: linux-mm@kvack.org |
6794 | W: http://www.linux-mm.org | 6802 | W: http://www.linux-mm.org |
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 477bfa6db370..7663c455b9f6 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl | |||
@@ -381,3 +381,4 @@ | |||
381 | 372 i386 recvmsg sys_recvmsg compat_sys_recvmsg | 381 | 372 i386 recvmsg sys_recvmsg compat_sys_recvmsg |
382 | 373 i386 shutdown sys_shutdown | 382 | 373 i386 shutdown sys_shutdown |
383 | 374 i386 userfaultfd sys_userfaultfd | 383 | 374 i386 userfaultfd sys_userfaultfd |
384 | 375 i386 membarrier sys_membarrier | ||
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 81c490634db9..278842fdf1f6 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl | |||
@@ -330,6 +330,7 @@ | |||
330 | 321 common bpf sys_bpf | 330 | 321 common bpf sys_bpf |
331 | 322 64 execveat stub_execveat | 331 | 322 64 execveat stub_execveat |
332 | 323 common userfaultfd sys_userfaultfd | 332 | 323 common userfaultfd sys_userfaultfd |
333 | 324 common membarrier sys_membarrier | ||
333 | 334 | ||
334 | # | 335 | # |
335 | # x32-specific system call numbers start at 512 to avoid cache impact | 336 | # x32-specific system call numbers start at 512 to avoid cache impact |
diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index 0717aa96ce39..9bc20e2119a3 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c | |||
@@ -135,8 +135,9 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num) | |||
135 | static ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, | 135 | static ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, |
136 | struct seq_file *s) | 136 | struct seq_file *s) |
137 | { | 137 | { |
138 | return seq_printf(s, "%08x %08x %01x\n", cr->cam, cr->ram, | 138 | seq_printf(s, "%08x %08x %01x\n", cr->cam, cr->ram, |
139 | (cr->cam & MMU_CAM_P) ? 1 : 0); | 139 | (cr->cam & MMU_CAM_P) ? 1 : 0); |
140 | return 0; | ||
140 | } | 141 | } |
141 | 142 | ||
142 | static size_t omap_dump_tlb_entries(struct omap_iommu *obj, struct seq_file *s) | 143 | static size_t omap_dump_tlb_entries(struct omap_iommu *obj, struct seq_file *s) |
@@ -142,7 +142,8 @@ static int nsfs_show_path(struct seq_file *seq, struct dentry *dentry) | |||
142 | struct inode *inode = d_inode(dentry); | 142 | struct inode *inode = d_inode(dentry); |
143 | const struct proc_ns_operations *ns_ops = dentry->d_fsdata; | 143 | const struct proc_ns_operations *ns_ops = dentry->d_fsdata; |
144 | 144 | ||
145 | return seq_printf(seq, "%s:[%lu]", ns_ops->name, inode->i_ino); | 145 | seq_printf(seq, "%s:[%lu]", ns_ops->name, inode->i_ino); |
146 | return 0; | ||
146 | } | 147 | } |
147 | 148 | ||
148 | static const struct super_operations nsfs_ops = { | 149 | static const struct super_operations nsfs_ops = { |
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index d0e436dc6437..ce12e0b1a31f 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
@@ -1776,7 +1776,7 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, | |||
1776 | struct dlm_migratable_lockres *mres) | 1776 | struct dlm_migratable_lockres *mres) |
1777 | { | 1777 | { |
1778 | struct dlm_migratable_lock *ml; | 1778 | struct dlm_migratable_lock *ml; |
1779 | struct list_head *queue; | 1779 | struct list_head *queue, *iter; |
1780 | struct list_head *tmpq = NULL; | 1780 | struct list_head *tmpq = NULL; |
1781 | struct dlm_lock *newlock = NULL; | 1781 | struct dlm_lock *newlock = NULL; |
1782 | struct dlm_lockstatus *lksb = NULL; | 1782 | struct dlm_lockstatus *lksb = NULL; |
@@ -1821,7 +1821,9 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, | |||
1821 | spin_lock(&res->spinlock); | 1821 | spin_lock(&res->spinlock); |
1822 | for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) { | 1822 | for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) { |
1823 | tmpq = dlm_list_idx_to_ptr(res, j); | 1823 | tmpq = dlm_list_idx_to_ptr(res, j); |
1824 | list_for_each_entry(lock, tmpq, list) { | 1824 | list_for_each(iter, tmpq) { |
1825 | lock = list_entry(iter, | ||
1826 | struct dlm_lock, list); | ||
1825 | if (lock->ml.cookie == ml->cookie) | 1827 | if (lock->ml.cookie == ml->cookie) |
1826 | break; | 1828 | break; |
1827 | lock = NULL; | 1829 | lock = NULL; |
diff --git a/fs/seq_file.c b/fs/seq_file.c index 263b125dbcf4..225586e141ca 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -372,16 +372,16 @@ EXPORT_SYMBOL(seq_release); | |||
372 | * @esc: set of characters that need escaping | 372 | * @esc: set of characters that need escaping |
373 | * | 373 | * |
374 | * Puts string into buffer, replacing each occurrence of character from | 374 | * Puts string into buffer, replacing each occurrence of character from |
375 | * @esc with usual octal escape. Returns 0 in case of success, -1 - in | 375 | * @esc with usual octal escape. |
376 | * case of overflow. | 376 | * Use seq_has_overflowed() to check for errors. |
377 | */ | 377 | */ |
378 | int seq_escape(struct seq_file *m, const char *s, const char *esc) | 378 | void seq_escape(struct seq_file *m, const char *s, const char *esc) |
379 | { | 379 | { |
380 | char *end = m->buf + m->size; | 380 | char *end = m->buf + m->size; |
381 | char *p; | 381 | char *p; |
382 | char c; | 382 | char c; |
383 | 383 | ||
384 | for (p = m->buf + m->count; (c = *s) != '\0' && p < end; s++) { | 384 | for (p = m->buf + m->count; (c = *s) != '\0' && p < end; s++) { |
385 | if (!strchr(esc, c)) { | 385 | if (!strchr(esc, c)) { |
386 | *p++ = c; | 386 | *p++ = c; |
387 | continue; | 387 | continue; |
@@ -394,14 +394,13 @@ int seq_escape(struct seq_file *m, const char *s, const char *esc) | |||
394 | continue; | 394 | continue; |
395 | } | 395 | } |
396 | seq_set_overflow(m); | 396 | seq_set_overflow(m); |
397 | return -1; | 397 | return; |
398 | } | 398 | } |
399 | m->count = p - m->buf; | 399 | m->count = p - m->buf; |
400 | return 0; | ||
401 | } | 400 | } |
402 | EXPORT_SYMBOL(seq_escape); | 401 | EXPORT_SYMBOL(seq_escape); |
403 | 402 | ||
404 | int seq_vprintf(struct seq_file *m, const char *f, va_list args) | 403 | void seq_vprintf(struct seq_file *m, const char *f, va_list args) |
405 | { | 404 | { |
406 | int len; | 405 | int len; |
407 | 406 | ||
@@ -409,24 +408,20 @@ int seq_vprintf(struct seq_file *m, const char *f, va_list args) | |||
409 | len = vsnprintf(m->buf + m->count, m->size - m->count, f, args); | 408 | len = vsnprintf(m->buf + m->count, m->size - m->count, f, args); |
410 | if (m->count + len < m->size) { | 409 | if (m->count + len < m->size) { |
411 | m->count += len; | 410 | m->count += len; |
412 | return 0; | 411 | return; |
413 | } | 412 | } |
414 | } | 413 | } |
415 | seq_set_overflow(m); | 414 | seq_set_overflow(m); |
416 | return -1; | ||
417 | } | 415 | } |
418 | EXPORT_SYMBOL(seq_vprintf); | 416 | EXPORT_SYMBOL(seq_vprintf); |
419 | 417 | ||
420 | int seq_printf(struct seq_file *m, const char *f, ...) | 418 | void seq_printf(struct seq_file *m, const char *f, ...) |
421 | { | 419 | { |
422 | int ret; | ||
423 | va_list args; | 420 | va_list args; |
424 | 421 | ||
425 | va_start(args, f); | 422 | va_start(args, f); |
426 | ret = seq_vprintf(m, f, args); | 423 | seq_vprintf(m, f, args); |
427 | va_end(args); | 424 | va_end(args); |
428 | |||
429 | return ret; | ||
430 | } | 425 | } |
431 | EXPORT_SYMBOL(seq_printf); | 426 | EXPORT_SYMBOL(seq_printf); |
432 | 427 | ||
@@ -664,26 +659,25 @@ int seq_open_private(struct file *filp, const struct seq_operations *ops, | |||
664 | } | 659 | } |
665 | EXPORT_SYMBOL(seq_open_private); | 660 | EXPORT_SYMBOL(seq_open_private); |
666 | 661 | ||
667 | int seq_putc(struct seq_file *m, char c) | 662 | void seq_putc(struct seq_file *m, char c) |
668 | { | 663 | { |
669 | if (m->count < m->size) { | 664 | if (m->count >= m->size) |
670 | m->buf[m->count++] = c; | 665 | return; |
671 | return 0; | 666 | |
672 | } | 667 | m->buf[m->count++] = c; |
673 | return -1; | ||
674 | } | 668 | } |
675 | EXPORT_SYMBOL(seq_putc); | 669 | EXPORT_SYMBOL(seq_putc); |
676 | 670 | ||
677 | int seq_puts(struct seq_file *m, const char *s) | 671 | void seq_puts(struct seq_file *m, const char *s) |
678 | { | 672 | { |
679 | int len = strlen(s); | 673 | int len = strlen(s); |
680 | if (m->count + len < m->size) { | 674 | |
681 | memcpy(m->buf + m->count, s, len); | 675 | if (m->count + len >= m->size) { |
682 | m->count += len; | 676 | seq_set_overflow(m); |
683 | return 0; | 677 | return; |
684 | } | 678 | } |
685 | seq_set_overflow(m); | 679 | memcpy(m->buf + m->count, s, len); |
686 | return -1; | 680 | m->count += len; |
687 | } | 681 | } |
688 | EXPORT_SYMBOL(seq_puts); | 682 | EXPORT_SYMBOL(seq_puts); |
689 | 683 | ||
@@ -694,8 +688,8 @@ EXPORT_SYMBOL(seq_puts); | |||
694 | * This routine is very quick when you show lots of numbers. | 688 | * This routine is very quick when you show lots of numbers. |
695 | * In usual cases, it will be better to use seq_printf(). It's easier to read. | 689 | * In usual cases, it will be better to use seq_printf(). It's easier to read. |
696 | */ | 690 | */ |
697 | int seq_put_decimal_ull(struct seq_file *m, char delimiter, | 691 | void seq_put_decimal_ull(struct seq_file *m, char delimiter, |
698 | unsigned long long num) | 692 | unsigned long long num) |
699 | { | 693 | { |
700 | int len; | 694 | int len; |
701 | 695 | ||
@@ -707,35 +701,33 @@ int seq_put_decimal_ull(struct seq_file *m, char delimiter, | |||
707 | 701 | ||
708 | if (num < 10) { | 702 | if (num < 10) { |
709 | m->buf[m->count++] = num + '0'; | 703 | m->buf[m->count++] = num + '0'; |
710 | return 0; | 704 | return; |
711 | } | 705 | } |
712 | 706 | ||
713 | len = num_to_str(m->buf + m->count, m->size - m->count, num); | 707 | len = num_to_str(m->buf + m->count, m->size - m->count, num); |
714 | if (!len) | 708 | if (!len) |
715 | goto overflow; | 709 | goto overflow; |
716 | m->count += len; | 710 | m->count += len; |
717 | return 0; | 711 | return; |
712 | |||
718 | overflow: | 713 | overflow: |
719 | seq_set_overflow(m); | 714 | seq_set_overflow(m); |
720 | return -1; | ||
721 | } | 715 | } |
722 | EXPORT_SYMBOL(seq_put_decimal_ull); | 716 | EXPORT_SYMBOL(seq_put_decimal_ull); |
723 | 717 | ||
724 | int seq_put_decimal_ll(struct seq_file *m, char delimiter, | 718 | void seq_put_decimal_ll(struct seq_file *m, char delimiter, long long num) |
725 | long long num) | ||
726 | { | 719 | { |
727 | if (num < 0) { | 720 | if (num < 0) { |
728 | if (m->count + 3 >= m->size) { | 721 | if (m->count + 3 >= m->size) { |
729 | seq_set_overflow(m); | 722 | seq_set_overflow(m); |
730 | return -1; | 723 | return; |
731 | } | 724 | } |
732 | if (delimiter) | 725 | if (delimiter) |
733 | m->buf[m->count++] = delimiter; | 726 | m->buf[m->count++] = delimiter; |
734 | num = -num; | 727 | num = -num; |
735 | delimiter = '-'; | 728 | delimiter = '-'; |
736 | } | 729 | } |
737 | return seq_put_decimal_ull(m, delimiter, num); | 730 | seq_put_decimal_ull(m, delimiter, num); |
738 | |||
739 | } | 731 | } |
740 | EXPORT_SYMBOL(seq_put_decimal_ll); | 732 | EXPORT_SYMBOL(seq_put_decimal_ll); |
741 | 733 | ||
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index adeadbd6d7bf..dde00defbaa5 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h | |||
@@ -114,13 +114,18 @@ int seq_open(struct file *, const struct seq_operations *); | |||
114 | ssize_t seq_read(struct file *, char __user *, size_t, loff_t *); | 114 | ssize_t seq_read(struct file *, char __user *, size_t, loff_t *); |
115 | loff_t seq_lseek(struct file *, loff_t, int); | 115 | loff_t seq_lseek(struct file *, loff_t, int); |
116 | int seq_release(struct inode *, struct file *); | 116 | int seq_release(struct inode *, struct file *); |
117 | int seq_escape(struct seq_file *, const char *, const char *); | ||
118 | int seq_putc(struct seq_file *m, char c); | ||
119 | int seq_puts(struct seq_file *m, const char *s); | ||
120 | int seq_write(struct seq_file *seq, const void *data, size_t len); | 117 | int seq_write(struct seq_file *seq, const void *data, size_t len); |
121 | 118 | ||
122 | __printf(2, 3) int seq_printf(struct seq_file *, const char *, ...); | 119 | __printf(2, 0) |
123 | __printf(2, 0) int seq_vprintf(struct seq_file *, const char *, va_list args); | 120 | void seq_vprintf(struct seq_file *m, const char *fmt, va_list args); |
121 | __printf(2, 3) | ||
122 | void seq_printf(struct seq_file *m, const char *fmt, ...); | ||
123 | void seq_putc(struct seq_file *m, char c); | ||
124 | void seq_puts(struct seq_file *m, const char *s); | ||
125 | void seq_put_decimal_ull(struct seq_file *m, char delimiter, | ||
126 | unsigned long long num); | ||
127 | void seq_put_decimal_ll(struct seq_file *m, char delimiter, long long num); | ||
128 | void seq_escape(struct seq_file *m, const char *s, const char *esc); | ||
124 | 129 | ||
125 | void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type, | 130 | void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type, |
126 | int rowsize, int groupsize, const void *buf, size_t len, | 131 | int rowsize, int groupsize, const void *buf, size_t len, |
@@ -138,10 +143,6 @@ int single_release(struct inode *, struct file *); | |||
138 | void *__seq_open_private(struct file *, const struct seq_operations *, int); | 143 | void *__seq_open_private(struct file *, const struct seq_operations *, int); |
139 | int seq_open_private(struct file *, const struct seq_operations *, int); | 144 | int seq_open_private(struct file *, const struct seq_operations *, int); |
140 | int seq_release_private(struct inode *, struct file *); | 145 | int seq_release_private(struct inode *, struct file *); |
141 | int seq_put_decimal_ull(struct seq_file *m, char delimiter, | ||
142 | unsigned long long num); | ||
143 | int seq_put_decimal_ll(struct seq_file *m, char delimiter, | ||
144 | long long num); | ||
145 | 146 | ||
146 | static inline struct user_namespace *seq_user_ns(struct seq_file *seq) | 147 | static inline struct user_namespace *seq_user_ns(struct seq_file *seq) |
147 | { | 148 | { |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 08001317aee7..a460e2ef2843 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -885,4 +885,6 @@ asmlinkage long sys_execveat(int dfd, const char __user *filename, | |||
885 | const char __user *const __user *argv, | 885 | const char __user *const __user *argv, |
886 | const char __user *const __user *envp, int flags); | 886 | const char __user *const __user *envp, int flags); |
887 | 887 | ||
888 | asmlinkage long sys_membarrier(int cmd, int flags); | ||
889 | |||
888 | #endif | 890 | #endif |
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index e016bd9b1a04..8da542a2874d 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h | |||
@@ -709,9 +709,11 @@ __SYSCALL(__NR_memfd_create, sys_memfd_create) | |||
709 | __SYSCALL(__NR_bpf, sys_bpf) | 709 | __SYSCALL(__NR_bpf, sys_bpf) |
710 | #define __NR_execveat 281 | 710 | #define __NR_execveat 281 |
711 | __SC_COMP(__NR_execveat, sys_execveat, compat_sys_execveat) | 711 | __SC_COMP(__NR_execveat, sys_execveat, compat_sys_execveat) |
712 | #define __NR_membarrier 282 | ||
713 | __SYSCALL(__NR_membarrier, sys_membarrier) | ||
712 | 714 | ||
713 | #undef __NR_syscalls | 715 | #undef __NR_syscalls |
714 | #define __NR_syscalls 282 | 716 | #define __NR_syscalls 283 |
715 | 717 | ||
716 | /* | 718 | /* |
717 | * All syscalls below here should go away really, | 719 | * All syscalls below here should go away really, |
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 70ff1d9abf0d..f7b2db44eb4b 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild | |||
@@ -252,6 +252,7 @@ header-y += mdio.h | |||
252 | header-y += media.h | 252 | header-y += media.h |
253 | header-y += media-bus-format.h | 253 | header-y += media-bus-format.h |
254 | header-y += mei.h | 254 | header-y += mei.h |
255 | header-y += membarrier.h | ||
255 | header-y += memfd.h | 256 | header-y += memfd.h |
256 | header-y += mempolicy.h | 257 | header-y += mempolicy.h |
257 | header-y += meye.h | 258 | header-y += meye.h |
diff --git a/include/uapi/linux/membarrier.h b/include/uapi/linux/membarrier.h new file mode 100644 index 000000000000..e0b108bd2624 --- /dev/null +++ b/include/uapi/linux/membarrier.h | |||
@@ -0,0 +1,53 @@ | |||
1 | #ifndef _UAPI_LINUX_MEMBARRIER_H | ||
2 | #define _UAPI_LINUX_MEMBARRIER_H | ||
3 | |||
4 | /* | ||
5 | * linux/membarrier.h | ||
6 | * | ||
7 | * membarrier system call API | ||
8 | * | ||
9 | * Copyright (c) 2010, 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
10 | * | ||
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
12 | * of this software and associated documentation files (the "Software"), to deal | ||
13 | * in the Software without restriction, including without limitation the rights | ||
14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
15 | * copies of the Software, and to permit persons to whom the Software is | ||
16 | * furnished to do so, subject to the following conditions: | ||
17 | * | ||
18 | * The above copyright notice and this permission notice shall be included in | ||
19 | * all copies or substantial portions of the Software. | ||
20 | * | ||
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
27 | * SOFTWARE. | ||
28 | */ | ||
29 | |||
30 | /** | ||
31 | * enum membarrier_cmd - membarrier system call command | ||
32 | * @MEMBARRIER_CMD_QUERY: Query the set of supported commands. It returns | ||
33 | * a bitmask of valid commands. | ||
34 | * @MEMBARRIER_CMD_SHARED: Execute a memory barrier on all running threads. | ||
35 | * Upon return from system call, the caller thread | ||
36 | * is ensured that all running threads have passed | ||
37 | * through a state where all memory accesses to | ||
38 | * user-space addresses match program order between | ||
39 | * entry to and return from the system call | ||
40 | * (non-running threads are de facto in such a | ||
41 | * state). This covers threads from all processes | ||
42 | * running on the system. This command returns 0. | ||
43 | * | ||
44 | * Command to be passed to the membarrier system call. The commands need to | ||
45 | * be a single bit each, except for MEMBARRIER_CMD_QUERY which is assigned to | ||
46 | * the value 0. | ||
47 | */ | ||
48 | enum membarrier_cmd { | ||
49 | MEMBARRIER_CMD_QUERY = 0, | ||
50 | MEMBARRIER_CMD_SHARED = (1 << 0), | ||
51 | }; | ||
52 | |||
53 | #endif /* _UAPI_LINUX_MEMBARRIER_H */ | ||
diff --git a/init/Kconfig b/init/Kconfig index 02da9f1fd9df..c24b6f767bf0 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -1602,6 +1602,18 @@ config PCI_QUIRKS | |||
1602 | bugs/quirks. Disable this only if your target machine is | 1602 | bugs/quirks. Disable this only if your target machine is |
1603 | unaffected by PCI quirks. | 1603 | unaffected by PCI quirks. |
1604 | 1604 | ||
1605 | config MEMBARRIER | ||
1606 | bool "Enable membarrier() system call" if EXPERT | ||
1607 | default y | ||
1608 | help | ||
1609 | Enable the membarrier() system call that allows issuing memory | ||
1610 | barriers across all running threads, which can be used to distribute | ||
1611 | the cost of user-space memory barriers asymmetrically by transforming | ||
1612 | pairs of memory barriers into pairs consisting of membarrier() and a | ||
1613 | compiler barrier. | ||
1614 | |||
1615 | If unsure, say Y. | ||
1616 | |||
1605 | config EMBEDDED | 1617 | config EMBEDDED |
1606 | bool "Embedded system" | 1618 | bool "Embedded system" |
1607 | option allnoconfig_y | 1619 | option allnoconfig_y |
diff --git a/kernel/Makefile b/kernel/Makefile index d4988410b410..53abf008ecb3 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -100,6 +100,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | |||
100 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o | 100 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o |
101 | obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o | 101 | obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o |
102 | obj-$(CONFIG_TORTURE_TEST) += torture.o | 102 | obj-$(CONFIG_TORTURE_TEST) += torture.o |
103 | obj-$(CONFIG_MEMBARRIER) += membarrier.o | ||
103 | 104 | ||
104 | obj-$(CONFIG_HAS_IOMEM) += memremap.o | 105 | obj-$(CONFIG_HAS_IOMEM) += memremap.o |
105 | 106 | ||
diff --git a/kernel/membarrier.c b/kernel/membarrier.c new file mode 100644 index 000000000000..536c727a56e9 --- /dev/null +++ b/kernel/membarrier.c | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010, 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
3 | * | ||
4 | * membarrier system call | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/syscalls.h> | ||
18 | #include <linux/membarrier.h> | ||
19 | |||
20 | /* | ||
21 | * Bitmask made from a "or" of all commands within enum membarrier_cmd, | ||
22 | * except MEMBARRIER_CMD_QUERY. | ||
23 | */ | ||
24 | #define MEMBARRIER_CMD_BITMASK (MEMBARRIER_CMD_SHARED) | ||
25 | |||
26 | /** | ||
27 | * sys_membarrier - issue memory barriers on a set of threads | ||
28 | * @cmd: Takes command values defined in enum membarrier_cmd. | ||
29 | * @flags: Currently needs to be 0. For future extensions. | ||
30 | * | ||
31 | * If this system call is not implemented, -ENOSYS is returned. If the | ||
32 | * command specified does not exist, or if the command argument is invalid, | ||
33 | * this system call returns -EINVAL. For a given command, with flags argument | ||
34 | * set to 0, this system call is guaranteed to always return the same value | ||
35 | * until reboot. | ||
36 | * | ||
37 | * All memory accesses performed in program order from each targeted thread | ||
38 | * is guaranteed to be ordered with respect to sys_membarrier(). If we use | ||
39 | * the semantic "barrier()" to represent a compiler barrier forcing memory | ||
40 | * accesses to be performed in program order across the barrier, and | ||
41 | * smp_mb() to represent explicit memory barriers forcing full memory | ||
42 | * ordering across the barrier, we have the following ordering table for | ||
43 | * each pair of barrier(), sys_membarrier() and smp_mb(): | ||
44 | * | ||
45 | * The pair ordering is detailed as (O: ordered, X: not ordered): | ||
46 | * | ||
47 | * barrier() smp_mb() sys_membarrier() | ||
48 | * barrier() X X O | ||
49 | * smp_mb() X O O | ||
50 | * sys_membarrier() O O O | ||
51 | */ | ||
52 | SYSCALL_DEFINE2(membarrier, int, cmd, int, flags) | ||
53 | { | ||
54 | if (unlikely(flags)) | ||
55 | return -EINVAL; | ||
56 | switch (cmd) { | ||
57 | case MEMBARRIER_CMD_QUERY: | ||
58 | return MEMBARRIER_CMD_BITMASK; | ||
59 | case MEMBARRIER_CMD_SHARED: | ||
60 | if (num_online_cpus() > 1) | ||
61 | synchronize_sched(); | ||
62 | return 0; | ||
63 | default: | ||
64 | return -EINVAL; | ||
65 | } | ||
66 | } | ||
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 03c3875d9958..a02decf15583 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
@@ -245,3 +245,6 @@ cond_syscall(sys_bpf); | |||
245 | 245 | ||
246 | /* execveat */ | 246 | /* execveat */ |
247 | cond_syscall(sys_execveat); | 247 | cond_syscall(sys_execveat); |
248 | |||
249 | /* membarrier */ | ||
250 | cond_syscall(sys_membarrier); | ||
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c index 23f744d77ce0..17ae14b5aefa 100644 --- a/mm/early_ioremap.c +++ b/mm/early_ioremap.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | #include <linux/vmalloc.h> | 16 | #include <linux/vmalloc.h> |
17 | #include <asm/fixmap.h> | 17 | #include <asm/fixmap.h> |
18 | #include <asm/early_ioremap.h> | ||
18 | 19 | ||
19 | #ifdef CONFIG_MMU | 20 | #ifdef CONFIG_MMU |
20 | static int early_ioremap_debug __initdata; | 21 | static int early_ioremap_debug __initdata; |
diff --git a/scripts/extract-cert.c b/scripts/extract-cert.c index fd0db015c65c..10d23ca9f617 100644 --- a/scripts/extract-cert.c +++ b/scripts/extract-cert.c | |||
@@ -86,7 +86,7 @@ static void write_cert(X509 *x509) | |||
86 | ERR(!wb, "%s", cert_dst); | 86 | ERR(!wb, "%s", cert_dst); |
87 | } | 87 | } |
88 | X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf)); | 88 | X509_NAME_oneline(X509_get_subject_name(x509), buf, sizeof(buf)); |
89 | ERR(!i2d_X509_bio(wb, x509), cert_dst); | 89 | ERR(!i2d_X509_bio(wb, x509), "%s", cert_dst); |
90 | if (kbuild_verbose) | 90 | if (kbuild_verbose) |
91 | fprintf(stderr, "Extracted cert: %s\n", buf); | 91 | fprintf(stderr, "Extracted cert: %s\n", buf); |
92 | } | 92 | } |
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 050151144596..89b05e2222c9 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile | |||
@@ -6,6 +6,7 @@ TARGETS += firmware | |||
6 | TARGETS += ftrace | 6 | TARGETS += ftrace |
7 | TARGETS += futex | 7 | TARGETS += futex |
8 | TARGETS += kcmp | 8 | TARGETS += kcmp |
9 | TARGETS += membarrier | ||
9 | TARGETS += memfd | 10 | TARGETS += memfd |
10 | TARGETS += memory-hotplug | 11 | TARGETS += memory-hotplug |
11 | TARGETS += mount | 12 | TARGETS += mount |
diff --git a/tools/testing/selftests/membarrier/.gitignore b/tools/testing/selftests/membarrier/.gitignore new file mode 100644 index 000000000000..020c44f49a9e --- /dev/null +++ b/tools/testing/selftests/membarrier/.gitignore | |||
@@ -0,0 +1 @@ | |||
membarrier_test | |||
diff --git a/tools/testing/selftests/membarrier/Makefile b/tools/testing/selftests/membarrier/Makefile new file mode 100644 index 000000000000..877a50355d7f --- /dev/null +++ b/tools/testing/selftests/membarrier/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | CFLAGS += -g -I../../../../usr/include/ | ||
2 | |||
3 | all: | ||
4 | $(CC) $(CFLAGS) membarrier_test.c -o membarrier_test | ||
5 | |||
6 | TEST_PROGS := membarrier_test | ||
7 | |||
8 | include ../lib.mk | ||
9 | |||
10 | clean: | ||
11 | $(RM) membarrier_test | ||
diff --git a/tools/testing/selftests/membarrier/membarrier_test.c b/tools/testing/selftests/membarrier/membarrier_test.c new file mode 100644 index 000000000000..dde312508007 --- /dev/null +++ b/tools/testing/selftests/membarrier/membarrier_test.c | |||
@@ -0,0 +1,121 @@ | |||
1 | #define _GNU_SOURCE | ||
2 | #define __EXPORTED_HEADERS__ | ||
3 | |||
4 | #include <linux/membarrier.h> | ||
5 | #include <asm-generic/unistd.h> | ||
6 | #include <sys/syscall.h> | ||
7 | #include <stdio.h> | ||
8 | #include <errno.h> | ||
9 | #include <string.h> | ||
10 | |||
11 | #include "../kselftest.h" | ||
12 | |||
13 | enum test_membarrier_status { | ||
14 | TEST_MEMBARRIER_PASS = 0, | ||
15 | TEST_MEMBARRIER_FAIL, | ||
16 | TEST_MEMBARRIER_SKIP, | ||
17 | }; | ||
18 | |||
19 | static int sys_membarrier(int cmd, int flags) | ||
20 | { | ||
21 | return syscall(__NR_membarrier, cmd, flags); | ||
22 | } | ||
23 | |||
24 | static enum test_membarrier_status test_membarrier_cmd_fail(void) | ||
25 | { | ||
26 | int cmd = -1, flags = 0; | ||
27 | |||
28 | if (sys_membarrier(cmd, flags) != -1) { | ||
29 | printf("membarrier: Wrong command should fail but passed.\n"); | ||
30 | return TEST_MEMBARRIER_FAIL; | ||
31 | } | ||
32 | return TEST_MEMBARRIER_PASS; | ||
33 | } | ||
34 | |||
35 | static enum test_membarrier_status test_membarrier_flags_fail(void) | ||
36 | { | ||
37 | int cmd = MEMBARRIER_CMD_QUERY, flags = 1; | ||
38 | |||
39 | if (sys_membarrier(cmd, flags) != -1) { | ||
40 | printf("membarrier: Wrong flags should fail but passed.\n"); | ||
41 | return TEST_MEMBARRIER_FAIL; | ||
42 | } | ||
43 | return TEST_MEMBARRIER_PASS; | ||
44 | } | ||
45 | |||
46 | static enum test_membarrier_status test_membarrier_success(void) | ||
47 | { | ||
48 | int cmd = MEMBARRIER_CMD_SHARED, flags = 0; | ||
49 | |||
50 | if (sys_membarrier(cmd, flags) != 0) { | ||
51 | printf("membarrier: Executing MEMBARRIER_CMD_SHARED failed. %s.\n", | ||
52 | strerror(errno)); | ||
53 | return TEST_MEMBARRIER_FAIL; | ||
54 | } | ||
55 | |||
56 | printf("membarrier: MEMBARRIER_CMD_SHARED success.\n"); | ||
57 | return TEST_MEMBARRIER_PASS; | ||
58 | } | ||
59 | |||
60 | static enum test_membarrier_status test_membarrier(void) | ||
61 | { | ||
62 | enum test_membarrier_status status; | ||
63 | |||
64 | status = test_membarrier_cmd_fail(); | ||
65 | if (status) | ||
66 | return status; | ||
67 | status = test_membarrier_flags_fail(); | ||
68 | if (status) | ||
69 | return status; | ||
70 | status = test_membarrier_success(); | ||
71 | if (status) | ||
72 | return status; | ||
73 | return TEST_MEMBARRIER_PASS; | ||
74 | } | ||
75 | |||
76 | static enum test_membarrier_status test_membarrier_query(void) | ||
77 | { | ||
78 | int flags = 0, ret; | ||
79 | |||
80 | printf("membarrier MEMBARRIER_CMD_QUERY "); | ||
81 | ret = sys_membarrier(MEMBARRIER_CMD_QUERY, flags); | ||
82 | if (ret < 0) { | ||
83 | printf("failed. %s.\n", strerror(errno)); | ||
84 | switch (errno) { | ||
85 | case ENOSYS: | ||
86 | /* | ||
87 | * It is valid to build a kernel with | ||
88 | * CONFIG_MEMBARRIER=n. However, this skips the tests. | ||
89 | */ | ||
90 | return TEST_MEMBARRIER_SKIP; | ||
91 | case EINVAL: | ||
92 | default: | ||
93 | return TEST_MEMBARRIER_FAIL; | ||
94 | } | ||
95 | } | ||
96 | if (!(ret & MEMBARRIER_CMD_SHARED)) { | ||
97 | printf("command MEMBARRIER_CMD_SHARED is not supported.\n"); | ||
98 | return TEST_MEMBARRIER_FAIL; | ||
99 | } | ||
100 | printf("syscall available.\n"); | ||
101 | return TEST_MEMBARRIER_PASS; | ||
102 | } | ||
103 | |||
104 | int main(int argc, char **argv) | ||
105 | { | ||
106 | switch (test_membarrier_query()) { | ||
107 | case TEST_MEMBARRIER_FAIL: | ||
108 | return ksft_exit_fail(); | ||
109 | case TEST_MEMBARRIER_SKIP: | ||
110 | return ksft_exit_skip(); | ||
111 | } | ||
112 | switch (test_membarrier()) { | ||
113 | case TEST_MEMBARRIER_FAIL: | ||
114 | return ksft_exit_fail(); | ||
115 | case TEST_MEMBARRIER_SKIP: | ||
116 | return ksft_exit_skip(); | ||
117 | } | ||
118 | |||
119 | printf("membarrier: tests done!\n"); | ||
120 | return ksft_exit_pass(); | ||
121 | } | ||