aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-11 22:34:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-11 22:34:09 -0400
commit01b0c014eeb0bb857a5dc572cd108be7becddfe7 (patch)
treed6f1a089081aadb09e66add27f7c5137d076ac80
parent3ebb0540c20d6670396ccee9ff6794c095fa9311 (diff)
parente527b22c3f63c02832ac4cb8ed0ec3a9b638bbdf (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--MAINTAINERS8
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl1
-rw-r--r--arch/x86/entry/syscalls/syscall_64.tbl1
-rw-r--r--drivers/iommu/omap-iommu-debug.c3
-rw-r--r--fs/nsfs.c3
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c6
-rw-r--r--fs/seq_file.c70
-rw-r--r--include/linux/seq_file.h19
-rw-r--r--include/linux/syscalls.h2
-rw-r--r--include/uapi/asm-generic/unistd.h4
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/membarrier.h53
-rw-r--r--init/Kconfig12
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/membarrier.c66
-rw-r--r--kernel/sys_ni.c3
-rw-r--r--mm/early_ioremap.c1
-rw-r--r--scripts/extract-cert.c2
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/membarrier/.gitignore1
-rw-r--r--tools/testing/selftests/membarrier/Makefile11
-rw-r--r--tools/testing/selftests/membarrier/membarrier_test.c121
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
6789Q: http://patchwork.ozlabs.org/project/netdev/list/ 6789Q: http://patchwork.ozlabs.org/project/netdev/list/
6790F: drivers/net/ethernet/mellanox/mlxsw/ 6790F: drivers/net/ethernet/mellanox/mlxsw/
6791 6791
6792MEMBARRIER SUPPORT
6793M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6794M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
6795L: linux-kernel@vger.kernel.org
6796S: Supported
6797F: kernel/membarrier.c
6798F: include/uapi/linux/membarrier.h
6799
6792MEMORY MANAGEMENT 6800MEMORY MANAGEMENT
6793L: linux-mm@kvack.org 6801L: linux-mm@kvack.org
6794W: http://www.linux-mm.org 6802W: 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 @@
381372 i386 recvmsg sys_recvmsg compat_sys_recvmsg 381372 i386 recvmsg sys_recvmsg compat_sys_recvmsg
382373 i386 shutdown sys_shutdown 382373 i386 shutdown sys_shutdown
383374 i386 userfaultfd sys_userfaultfd 383374 i386 userfaultfd sys_userfaultfd
384375 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 @@
330321 common bpf sys_bpf 330321 common bpf sys_bpf
331322 64 execveat stub_execveat 331322 64 execveat stub_execveat
332323 common userfaultfd sys_userfaultfd 332323 common userfaultfd sys_userfaultfd
333324 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)
135static ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, 135static 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
142static size_t omap_dump_tlb_entries(struct omap_iommu *obj, struct seq_file *s) 143static size_t omap_dump_tlb_entries(struct omap_iommu *obj, struct seq_file *s)
diff --git a/fs/nsfs.c b/fs/nsfs.c
index e4905fbf3396..8f20d6016e20 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -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
148static const struct super_operations nsfs_ops = { 149static 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 */
378int seq_escape(struct seq_file *m, const char *s, const char *esc) 378void 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}
402EXPORT_SYMBOL(seq_escape); 401EXPORT_SYMBOL(seq_escape);
403 402
404int seq_vprintf(struct seq_file *m, const char *f, va_list args) 403void 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}
418EXPORT_SYMBOL(seq_vprintf); 416EXPORT_SYMBOL(seq_vprintf);
419 417
420int seq_printf(struct seq_file *m, const char *f, ...) 418void 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}
431EXPORT_SYMBOL(seq_printf); 426EXPORT_SYMBOL(seq_printf);
432 427
@@ -664,26 +659,25 @@ int seq_open_private(struct file *filp, const struct seq_operations *ops,
664} 659}
665EXPORT_SYMBOL(seq_open_private); 660EXPORT_SYMBOL(seq_open_private);
666 661
667int seq_putc(struct seq_file *m, char c) 662void 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}
675EXPORT_SYMBOL(seq_putc); 669EXPORT_SYMBOL(seq_putc);
676 670
677int seq_puts(struct seq_file *m, const char *s) 671void 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}
688EXPORT_SYMBOL(seq_puts); 682EXPORT_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 */
697int seq_put_decimal_ull(struct seq_file *m, char delimiter, 691void 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
718overflow: 713overflow:
719 seq_set_overflow(m); 714 seq_set_overflow(m);
720 return -1;
721} 715}
722EXPORT_SYMBOL(seq_put_decimal_ull); 716EXPORT_SYMBOL(seq_put_decimal_ull);
723 717
724int seq_put_decimal_ll(struct seq_file *m, char delimiter, 718void 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}
740EXPORT_SYMBOL(seq_put_decimal_ll); 732EXPORT_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 *);
114ssize_t seq_read(struct file *, char __user *, size_t, loff_t *); 114ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
115loff_t seq_lseek(struct file *, loff_t, int); 115loff_t seq_lseek(struct file *, loff_t, int);
116int seq_release(struct inode *, struct file *); 116int seq_release(struct inode *, struct file *);
117int seq_escape(struct seq_file *, const char *, const char *);
118int seq_putc(struct seq_file *m, char c);
119int seq_puts(struct seq_file *m, const char *s);
120int seq_write(struct seq_file *seq, const void *data, size_t len); 117int 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); 120void seq_vprintf(struct seq_file *m, const char *fmt, va_list args);
121__printf(2, 3)
122void seq_printf(struct seq_file *m, const char *fmt, ...);
123void seq_putc(struct seq_file *m, char c);
124void seq_puts(struct seq_file *m, const char *s);
125void seq_put_decimal_ull(struct seq_file *m, char delimiter,
126 unsigned long long num);
127void seq_put_decimal_ll(struct seq_file *m, char delimiter, long long num);
128void seq_escape(struct seq_file *m, const char *s, const char *esc);
124 129
125void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type, 130void 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 *);
138void *__seq_open_private(struct file *, const struct seq_operations *, int); 143void *__seq_open_private(struct file *, const struct seq_operations *, int);
139int seq_open_private(struct file *, const struct seq_operations *, int); 144int seq_open_private(struct file *, const struct seq_operations *, int);
140int seq_release_private(struct inode *, struct file *); 145int seq_release_private(struct inode *, struct file *);
141int seq_put_decimal_ull(struct seq_file *m, char delimiter,
142 unsigned long long num);
143int seq_put_decimal_ll(struct seq_file *m, char delimiter,
144 long long num);
145 146
146static inline struct user_namespace *seq_user_ns(struct seq_file *seq) 147static 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
888asmlinkage 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
252header-y += media.h 252header-y += media.h
253header-y += media-bus-format.h 253header-y += media-bus-format.h
254header-y += mei.h 254header-y += mei.h
255header-y += membarrier.h
255header-y += memfd.h 256header-y += memfd.h
256header-y += mempolicy.h 257header-y += mempolicy.h
257header-y += meye.h 258header-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 */
48enum 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
1605config 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
1605config EMBEDDED 1617config 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
100obj-$(CONFIG_JUMP_LABEL) += jump_label.o 100obj-$(CONFIG_JUMP_LABEL) += jump_label.o
101obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o 101obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
102obj-$(CONFIG_TORTURE_TEST) += torture.o 102obj-$(CONFIG_TORTURE_TEST) += torture.o
103obj-$(CONFIG_MEMBARRIER) += membarrier.o
103 104
104obj-$(CONFIG_HAS_IOMEM) += memremap.o 105obj-$(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 */
52SYSCALL_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 */
247cond_syscall(sys_execveat); 247cond_syscall(sys_execveat);
248
249/* membarrier */
250cond_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
20static int early_ioremap_debug __initdata; 21static 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
6TARGETS += ftrace 6TARGETS += ftrace
7TARGETS += futex 7TARGETS += futex
8TARGETS += kcmp 8TARGETS += kcmp
9TARGETS += membarrier
9TARGETS += memfd 10TARGETS += memfd
10TARGETS += memory-hotplug 11TARGETS += memory-hotplug
11TARGETS += mount 12TARGETS += 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 @@
1CFLAGS += -g -I../../../../usr/include/
2
3all:
4 $(CC) $(CFLAGS) membarrier_test.c -o membarrier_test
5
6TEST_PROGS := membarrier_test
7
8include ../lib.mk
9
10clean:
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
13enum test_membarrier_status {
14 TEST_MEMBARRIER_PASS = 0,
15 TEST_MEMBARRIER_FAIL,
16 TEST_MEMBARRIER_SKIP,
17};
18
19static int sys_membarrier(int cmd, int flags)
20{
21 return syscall(__NR_membarrier, cmd, flags);
22}
23
24static 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
35static 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
46static 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
60static 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
76static 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
104int 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}