Merge 03dc748bf1 ("Merge tag 'xfs-5.12-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux") into android-mainline

Steps on the way to 5.12-rc1

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: If2f608a4140e019c3d9fa7f28d57124a85a9d5f8
This commit is contained in:
Greg Kroah-Hartman 2021-03-06 20:22:19 +01:00
commit 2524797481
170 changed files with 3230 additions and 2473 deletions

View File

@ -29,7 +29,7 @@ Description:
option: [[appraise_type=]] [template=] [permit_directio]
[appraise_flag=] [keyrings=]
base:
func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK]MODULE_CHECK]
func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
[KEXEC_CMDLINE] [KEY_CHECK] [CRITICAL_DATA]

View File

@ -2098,7 +2098,7 @@ If the program returns 0, the attempt fails with -EPERM, otherwise
it succeeds.
An example of BPF_CGROUP_DEVICE program may be found in the kernel
source tree in the tools/testing/selftests/bpf/dev_cgroup.c file.
source tree in the tools/testing/selftests/bpf/progs/dev_cgroup.c file.
RDMA

View File

@ -5,10 +5,10 @@ Authors
Original Author
---------------
Steve French (sfrench@samba.org)
Steve French (smfrench@gmail.com, sfrench@samba.org)
The author wishes to express his appreciation and thanks to:
Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
Andrew Tridgell (Samba team) for his early suggestions about SMB/CIFS VFS
improvements. Thanks to IBM for allowing me time and test resources to pursue
this project, to Jim McDonough from IBM (and the Samba Team) for his help, to
the IBM Linux JFS team for explaining many esoteric Linux filesystem features.
@ -51,7 +51,7 @@ Patch Contributors
- Ronnie Sahlberg (for SMB3 xattr work, bug fixes, and lots of great work on compounding)
- Shirish Pargaonkar (for many ACL patches over the years)
- Sachin Prabhu (many bug fixes, including for reconnect, copy offload and security)
- Paulo Alcantara
- Paulo Alcantara (for some excellent work in DFS, and in booting from SMB3)
- Long Li (some great work on RDMA, SMB Direct)

View File

@ -3,6 +3,7 @@ Changes
=======
See https://wiki.samba.org/index.php/LinuxCIFSKernel for summary
information (that may be easier to read than parsing the output of
"git log fs/cifs") about fixes/improvements to CIFS/SMB2/SMB3 support (changes
information about fixes/improvements to CIFS/SMB2/SMB3 support (changes
to cifs.ko module) by kernel version (and cifs internal module version).
This may be easier to read than parsing the output of "git log fs/cifs"
by release.

View File

@ -7,19 +7,19 @@ Introduction
protocol which was the successor to the Server Message Block
(SMB) protocol, the native file sharing mechanism for most early
PC operating systems. New and improved versions of CIFS are now
called SMB2 and SMB3. Use of SMB3 (and later, including SMB3.1.1)
is strongly preferred over using older dialects like CIFS due to
security reasons. All modern dialects, including the most recent,
SMB3.1.1 are supported by the CIFS VFS module. The SMB3 protocol
is implemented and supported by all major file servers
such as all modern versions of Windows (including Windows 2016
Server), as well as by Samba (which provides excellent
CIFS/SMB2/SMB3 server support and tools for Linux and many other
operating systems). Apple systems also support SMB3 well, as
do most Network Attached Storage vendors, so this network
filesystem client can mount to a wide variety of systems.
It also supports mounting to the cloud (for example
Microsoft Azure), including the necessary security features.
called SMB2 and SMB3. Use of SMB3 (and later, including SMB3.1.1
the most current dialect) is strongly preferred over using older
dialects like CIFS due to security reasons. All modern dialects,
including the most recent, SMB3.1.1, are supported by the CIFS VFS
module. The SMB3 protocol is implemented and supported by all major
file servers such as Windows (including Windows 2019 Server), as
well as by Samba (which provides excellent CIFS/SMB2/SMB3 server
support and tools for Linux and many other operating systems).
Apple systems also support SMB3 well, as do most Network Attached
Storage vendors, so this network filesystem client can mount to a
wide variety of systems. It also supports mounting to the cloud
(for example Microsoft Azure), including the necessary security
features.
The intent of this module is to provide the most advanced network
file system function for SMB3 compliant servers, including advanced
@ -27,8 +27,8 @@ Introduction
POSIX compliance, secure per-user session establishment, encryption,
high performance safe distributed caching (leases/oplocks), optional packet
signing, large files, Unicode support and other internationalization
improvements. Since both Samba server and this filesystem client support
the CIFS Unix extensions (and in the future SMB3 POSIX extensions),
improvements. Since both Samba server and this filesystem client support the
CIFS Unix extensions, and the Linux client also suppors SMB3 POSIX extensions,
the combination can provide a reasonable alternative to other network and
cluster file systems for fileserving in some Linux to Linux environments,
not just in Linux to Windows (or Linux to Mac) environments.

View File

@ -13,24 +13,26 @@ is a partial list of the known problems and missing features:
a) SMB3 (and SMB3.1.1) missing optional features:
- multichannel (started), integration with RDMA
- directory leases (improved metadata caching), started (root dir only)
- multichannel (partially integrated), integration of multichannel with RDMA
- directory leases (improved metadata caching). Currently only implemented for root dir
- T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl
currently the only two server side copy mechanisms supported)
b) improved sparse file support (fiemap and SEEK_HOLE are implemented
but additional features would be supportable by the protocol).
but additional features would be supportable by the protocol such
as FALLOC_FL_COLLAPSE_RANGE and FALLOC_FL_INSERT_RANGE)
c) Directory entry caching relies on a 1 second timer, rather than
using Directory Leases, currently only the root file handle is cached longer
by leveraging Directory Leases
d) quota support (needs minor kernel change since quota calls
to make it to network filesystems or deviceless filesystems)
d) quota support (needs minor kernel change since quota calls otherwise
won't make it to network filesystems or deviceless filesystems).
e) Additional use cases can be optimized to use "compounding" (e.g.
open/query/close and open/setinfo/close) to reduce the number of
roundtrips to the server and improve performance. Various cases
(stat, statfs, create, unlink, mkdir) already have been improved by
(stat, statfs, create, unlink, mkdir, xattrs) already have been improved by
using compounding but more can be done. In addition we could
significantly reduce redundant opens by using deferred close (with
handle caching leases) and better using reference counters on file
@ -60,7 +62,9 @@ k) Add tools to take advantage of more smb3 specific ioctls and features
metadata attributes easier from tools (e.g. extending what was done
in smb-info tool).
l) encrypted file support
l) encrypted file support (currently the attribute showing the file is
encrypted on the server is reported, but changing the attribute is not
supported).
m) improved stats gathering tools (perhaps integration with nfsometer?)
to extend and make easier to use what is currently in /proc/fs/cifs/Stats
@ -69,14 +73,13 @@ n) Add support for claims based ACLs ("DAC")
o) mount helper GUI (to simplify the various configuration options on mount)
p) Add support for witness protocol (perhaps ioctl to cifs.ko from user space
tool listening on witness protocol RPC) to allow for notification of share
move, server failover, and server adapter changes. And also improve other
failover scenarios, e.g. when client knows multiple DFS entries point to
different servers, and the server we are connected to has gone down.
p) Expand support for witness protocol to allow for notification of share
move, and server network adapter changes. Currently only notifications by
the witness protocol for server move is supported by the Linux client.
q) Allow mount.cifs to be more verbose in reporting errors with dialect
or unsupported feature errors.
or unsupported feature errors. This would now be easier due to the
implementation of the new mount API.
r) updating cifs documentation, and user guide.
@ -87,11 +90,10 @@ t) split cifs and smb3 support into separate modules so legacy (and less
secure) CIFS dialect can be disabled in environments that don't need it
and simplify the code.
v) POSIX Extensions for SMB3.1.1 (started, create and mkdir support added
so far).
v) Additional testing of POSIX Extensions for SMB3.1.1
w) Add support for additional strong encryption types, and additional spnego
authentication mechanisms (see MS-SMB2)
authentication mechanisms (see MS-SMB2). GCM-256 is now partially implemented.
x) Finish support for SMB3.1.1 compression

View File

@ -83,7 +83,7 @@ and encrypted shares and stronger signing and authentication algorithms.
There are additional mount options that may be helpful for SMB3 to get
improved POSIX behavior (NB: can use vers=3.0 to force only SMB3, never 2.1):
``mfsymlinks`` and ``cifsacl`` and ``idsfromsid``
``mfsymlinks`` and either ``cifsacl`` or ``modefromsid`` (usually with ``idsfromsid``)
Allowing User Mounts
====================

View File

@ -284,6 +284,9 @@ The following sysctls are available for the XFS filesystem:
removes unused preallocation from clean inodes and releases
the unused space back to the free pool.
fs.xfs.speculative_cow_prealloc_lifetime
This is an alias for speculative_prealloc_lifetime.
fs.xfs.error_level (Min: 0 Default: 3 Max: 11)
A volume knob for error reporting when internal errors occur.
This will generate detailed messages & backtraces for filesystem
@ -356,12 +359,13 @@ The following sysctls are available for the XFS filesystem:
Deprecated Sysctls
==================
=========================== ================
Name Removal Schedule
=========================== ================
fs.xfs.irix_sgid_inherit September 2025
fs.xfs.irix_symlink_mode September 2025
=========================== ================
=========================================== ================
Name Removal Schedule
=========================================== ================
fs.xfs.irix_sgid_inherit September 2025
fs.xfs.irix_symlink_mode September 2025
fs.xfs.speculative_cow_prealloc_lifetime September 2025
=========================================== ================
Removed Sysctls

View File

@ -49,8 +49,7 @@ extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include',
if major >= 3:
sys.stderr.write('''WARNING: The kernel documentation build process
support for Sphinx v3.0 and above is brand new. Be prepared for
possible issues in the generated output.
''')
possible issues in the generated output.\n''')
if (major > 3) or (minor > 0 or patch >= 2):
# Sphinx c function parser is more pedantic with regards to type
# checking. Due to that, having macros at c:function cause problems.

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | TODO |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | ok |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | ok |
| csky: | ok |
| h8300: | TODO |
| hexagon: | ok |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | TODO |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,14 +10,13 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| m68k: | TODO |
| microblaze: | ok |
| mips: | TODO |
| mips: | ok |
| nds32: | TODO |
| nios2: | TODO |
| openrisc: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | ok |
| hexagon: | ok |

View File

@ -10,8 +10,7 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |
| ia64: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | TODO |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |
@ -23,7 +22,7 @@
| openrisc: | TODO |
| parisc: | ok |
| powerpc: | ok |
| riscv: | TODO |
| riscv: | ok |
| s390: | ok |
| sh: | TODO |
| sparc: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |
@ -23,7 +22,7 @@
| openrisc: | TODO |
| parisc: | ok |
| powerpc: | ok |
| riscv: | TODO |
| riscv: | ok |
| s390: | ok |
| sh: | ok |
| sparc: | ok |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |
@ -23,7 +22,7 @@
| openrisc: | TODO |
| parisc: | ok |
| powerpc: | ok |
| riscv: | TODO |
| riscv: | ok |
| s390: | ok |
| sh: | ok |
| sparc: | ok |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | TODO |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |
@ -23,7 +22,7 @@
| openrisc: | TODO |
| parisc: | TODO |
| powerpc: | ok |
| riscv: | TODO |
| riscv: | ok |
| s390: | ok |
| sh: | TODO |
| sparc: | ok |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | TODO |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | ok |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | ok |
@ -23,7 +22,7 @@
| openrisc: | TODO |
| parisc: | ok |
| powerpc: | ok |
| riscv: | TODO |
| riscv: | ok |
| s390: | ok |
| sh: | ok |
| sparc: | ok |

View File

@ -10,14 +10,13 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
| mips: | ok |
| nds32: | TODO |
| nios2: | TODO |
| openrisc: | TODO |

View File

@ -10,14 +10,13 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
| mips: | ok |
| nds32: | TODO |
| nios2: | TODO |
| openrisc: | TODO |

View File

@ -33,7 +33,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | .. |
| arm: | .. |
| arm64: | ok |
| c6x: | .. |
| csky: | .. |
| h8300: | .. |
| hexagon: | .. |
@ -23,7 +22,7 @@
| openrisc: | .. |
| parisc: | .. |
| powerpc: | ok |
| riscv: | TODO |
| riscv: | ok |
| s390: | ok |
| sh: | .. |
| sparc: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | TODO |
| arm64: | ok |
| c6x: | ok |
| csky: | ok |
| h8300: | ok |
| hexagon: | ok |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | ok |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | TODO |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | .. |
| csky: | .. |
| h8300: | .. |
| hexagon: | .. |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | TODO |
| c6x: | .. |
| csky: | TODO |
| h8300: | .. |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | TODO |
| arm64: | TODO |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -10,7 +10,6 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| c6x: | TODO |
| csky: | TODO |
| h8300: | TODO |
| hexagon: | TODO |

View File

@ -883,3 +883,10 @@ For bvec based itererators bio_iov_iter_get_pages() now doesn't copy bvecs but
uses the one provided. Anyone issuing kiocb-I/O should ensure that the bvec and
page references stay until I/O has completed, i.e. until ->ki_complete() has
been called or returned with non -EIOCBQUEUED code.
---
**mandatory**
mnt_want_write_file() can now only be paired with mnt_drop_write_file(),
whereas previously it could be paired with mnt_drop_write() as well.

View File

@ -697,6 +697,10 @@ files are there, and which are missing.
number of processes currently runnable (running or on ready queue);
total number of processes in system;
last pid created.
All fields are separated by one space except "number of
processes currently runnable" and "total number of processes
in system", which are separated by a slash ('/'). Example:
0.61 0.61 0.55 3/828 22084
locks Kernel locks
meminfo Memory info
misc Miscellaneous

View File

@ -46,25 +46,38 @@ stack frame LR and CR save fields are not used.
Register preservation rules
---------------------------
Register preservation rules match the ELF ABI calling sequence with the
following differences:
Register preservation rules match the ELF ABI calling sequence with some
differences.
+------------------------------------------------------------------------+
| For the sc instruction, differences with the ELF ABI |
+--------------+--------------+------------------------------------------+
| r0 | Volatile | (System call number.) |
| rr3 | Volatile | (Parameter 1, and return value.) |
| rr4-r8 | Volatile | (Parameters 2-6.) |
| rcr0 | Volatile | (cr0.SO is the return error condition.) |
| rcr1, cr5-7 | Nonvolatile | |
| rlr | Nonvolatile | |
+--------------+--------------+------------------------------------------+
| For the scv 0 instruction, differences with the ELF ABI |
+--------------+--------------+------------------------------------------+
| r0 | Volatile | (System call number.) |
| r3 | Volatile | (Parameter 1, and return value.) |
| r4-r8 | Volatile | (Parameters 2-6.) |
+--------------+--------------+------------------------------------------+
For the sc instruction, the differences from the ELF ABI are as follows:
+--------------+--------------------+-----------------------------------------+
| Register | Preservation Rules | Purpose |
+==============+====================+=========================================+
| r0 | Volatile | (System call number.) |
+--------------+--------------------+-----------------------------------------+
| r3 | Volatile | (Parameter 1, and return value.) |
+--------------+--------------------+-----------------------------------------+
| r4-r8 | Volatile | (Parameters 2-6.) |
+--------------+--------------------+-----------------------------------------+
| cr0 | Volatile | (cr0.SO is the return error condition.) |
+--------------+--------------------+-----------------------------------------+
| cr1, cr5-7 | Nonvolatile | |
+--------------+--------------------+-----------------------------------------+
| lr | Nonvolatile | |
+--------------+--------------------+-----------------------------------------+
For the scv 0 instruction, the differences from the ELF ABI are as follows:
+--------------+--------------------+-----------------------------------------+
| Register | Preservation Rules | Purpose |
+==============+====================+=========================================+
| r0 | Volatile | (System call number.) |
+--------------+--------------------+-----------------------------------------+
| r3 | Volatile | (Parameter 1, and return value.) |
+--------------+--------------------+-----------------------------------------+
| r4-r8 | Volatile | (Parameters 2-6.) |
+--------------+--------------------+-----------------------------------------+
All floating point and vector data registers as well as control and status
registers are nonvolatile.

View File

@ -242,7 +242,7 @@ and try to avoid "fixes" which make the warning go away without addressing
its cause.
Note that not all compiler warnings are enabled by default. Build the
kernel with "make EXTRA_CFLAGS=-W" to get the full set.
kernel with "make KCFLAGS=-W" to get the full set.
The kernel provides several configuration options which turn on debugging
features; most of these are found in the "kernel hacking" submenu. Several

View File

@ -96,7 +96,7 @@ and elsewhere regarding submitting Linux kernel patches.
injection might be appropriate.
20) Newly-added code has been compiled with ``gcc -W`` (use
``make EXTRA_CFLAGS=-W``). This will generate lots of noise, but is good
``make KCFLAGS=-W``). This will generate lots of noise, but is good
for finding bugs like "warning: comparison between signed and unsigned".
21) Tested after it has been merged into the -mm patchset to make sure

View File

@ -256,7 +256,7 @@ e cercate di evitare le "riparazioni" che fan sparire l'avvertimento senza
però averne trovato la causa.
Tenete a mente che non tutti gli avvertimenti sono disabilitati di default.
Costruite il kernel con "make EXTRA_CFLAGS=-W" per ottenerli tutti.
Costruite il kernel con "make KCFLAGS=-W" per ottenerli tutti.
Il kernel fornisce differenti opzioni che abilitano funzionalità di debugging;
molti di queste sono trovano all'interno del sotto menu "kernel hacking".

View File

@ -104,7 +104,7 @@ sottomissione delle patch, in particolare
l'iniezione di fallimenti specifici per il sottosistema.
22) Il nuovo codice è stato compilato con ``gcc -W`` (usate
``make EXTRA_CFLAGS=-W``). Questo genererà molti avvisi, ma è ottimo
``make KCFLAGS=-W``). Questo genererà molti avvisi, ma è ottimo
per scovare bachi come "warning: comparison between signed and unsigned".
23) La patch è stata verificata dopo essere stata inclusa nella serie di patch

View File

@ -165,7 +165,7 @@ Linus对这个问题给出了最佳答案:
通常,这些警告都指向真正的问题。提交以供审阅的代码通常不会产生任何编译器警告。
在消除警告时,注意了解真正的原因,并尽量避免“修复”,使警告消失而不解决其原因。
请注意并非所有编译器警告都默认启用。使用“make EXTRA_CFLAGS=-W”构建内核以
请注意并非所有编译器警告都默认启用。使用“make KCFLAGS=-W”构建内核以
获得完整集合。
内核提供了几个配置选项可以打开调试功能大多数配置选项位于“kernel hacking”

View File

@ -249,7 +249,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
childti->pcb.ksp = (unsigned long) childstack;
childti->pcb.flags = 1; /* set FEN, clear everything else */
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* kernel thread */
memset(childstack, 0,
sizeof(struct switch_stack) + sizeof(struct pt_regs));

View File

@ -191,7 +191,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
childksp[0] = 0; /* fp */
childksp[1] = (unsigned long)ret_from_fork; /* blink */
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(c_regs, 0, sizeof(struct pt_regs));
c_callee->r13 = kthread_arg;

View File

@ -243,7 +243,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
thread->cpu_domain = get_domain();
#endif
if (likely(!(p->flags & PF_KTHREAD))) {
if (likely(!(p->flags & (PF_KTHREAD | PF_IO_WORKER)))) {
*childregs = *current_pt_regs();
childregs->ARM_r0 = 0;
if (stack_start)

View File

@ -396,7 +396,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
ptrauth_thread_init_kernel(p);
if (likely(!(p->flags & PF_KTHREAD))) {
if (likely(!(p->flags & (PF_KTHREAD | PF_IO_WORKER)))) {
*childregs = *current_pt_regs();
childregs->regs[0] = 0;

View File

@ -49,7 +49,7 @@ int copy_thread(unsigned long clone_flags,
/* setup thread.sp for switch_to !!! */
p->thread.sp = (unsigned long)childstack;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(childregs, 0, sizeof(struct pt_regs));
childstack->r15 = (unsigned long) ret_from_kernel_thread;
childstack->r10 = kthread_arg;

View File

@ -112,7 +112,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(childregs, 0, sizeof(struct pt_regs));
childregs->retpc = (unsigned long) ret_from_kernel_thread;
childregs->er4 = topstk; /* arg */

View File

@ -73,7 +73,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
sizeof(*ss));
ss->lr = (unsigned long)ret_from_fork;
p->thread.switch_sp = ss;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(childregs, 0, sizeof(struct pt_regs));
/* r24 <- fn, r25 <- arg */
ss->r24 = usp;

View File

@ -338,7 +338,7 @@ copy_thread(unsigned long clone_flags, unsigned long user_stack_base,
ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
if (unlikely(!user_stack_base)) {
/* fork_idle() called us */
return 0;

View File

@ -157,7 +157,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
*/
p->thread.fs = get_fs().seg;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* kernel thread */
memset(frame, 0, sizeof(struct fork_frame));
frame->regs.sr = PS_S;

View File

@ -59,7 +59,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
struct pt_regs *childregs = task_pt_regs(p);
struct thread_info *ti = task_thread_info(p);
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* if we're creating a new kernel thread then just zeroing all
* the registers. That's OK for a brand new thread.*/
memset(childregs, 0, sizeof(struct pt_regs));

View File

@ -120,7 +120,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
/* Put the stack after the struct pt_regs. */
childksp = (unsigned long) childregs;
p->thread.cp0_status = (read_c0_status() & ~(ST0_CU2|ST0_CU1)) | ST0_KERNEL_CUMASK;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* kernel thread */
unsigned long status = p->thread.cp0_status;
memset(childregs, 0, sizeof(struct pt_regs));

View File

@ -156,7 +156,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(childregs, 0, sizeof(struct pt_regs));
/* kernel thread fn */
p->thread.cpu_context.r6 = stack_start;

View File

@ -109,7 +109,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
struct switch_stack *childstack =
((struct switch_stack *)childregs) - 1;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(childstack, 0,
sizeof(struct switch_stack) + sizeof(struct pt_regs));

3
arch/openrisc/Kbuild Normal file
View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += lib/ kernel/ mm/
obj-y += boot/dts/

View File

@ -24,6 +24,10 @@ LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
KBUILD_CFLAGS += -pipe -ffixed-r10 -D__linux__
all: vmlinux.bin
boot := arch/$(ARCH)/boot
ifeq ($(CONFIG_OPENRISC_HAVE_INST_MUL),y)
KBUILD_CFLAGS += $(call cc-option,-mhard-mul)
else
@ -38,14 +42,13 @@ endif
head-y := arch/openrisc/kernel/head.o
core-y += arch/openrisc/lib/ \
arch/openrisc/kernel/ \
arch/openrisc/mm/
core-y += arch/openrisc/
libs-y += $(LIBGCC)
ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
BUILTIN_DTB := y
else
BUILTIN_DTB := n
endif
core-$(BUILTIN_DTB) += arch/openrisc/boot/dts/
PHONY += vmlinux.bin
vmlinux.bin: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
archclean:
$(Q)$(MAKE) $(clean)=$(boot)

2
arch/openrisc/boot/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
vmlinux.bin

View File

@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for bootable kernel images
#
targets += vmlinux.bin
OBJCOPYFLAGS_vmlinux.bin := -O binary
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)

View File

@ -34,6 +34,7 @@
#include <linux/init_task.h>
#include <linux/mqueue.h>
#include <linux/fs.h>
#include <linux/reboot.h>
#include <linux/uaccess.h>
#include <asm/io.h>
@ -49,10 +50,16 @@
*/
struct thread_info *current_thread_info_set[NR_CPUS] = { &init_thread_info, };
void machine_restart(void)
void machine_restart(char *cmd)
{
printk(KERN_INFO "*** MACHINE RESTART ***\n");
__asm__("l.nop 1");
do_kernel_restart(cmd);
/* Give a grace period for failure to restart of 1s */
mdelay(1000);
/* Whoops - the platform was unable to reboot. Tell the user! */
pr_emerg("Reboot failed -- System halted\n");
while (1);
}
/*
@ -167,7 +174,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
sp -= sizeof(struct pt_regs);
kregs = (struct pt_regs *)sp;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(kregs, 0, sizeof(struct pt_regs));
kregs->gpr[20] = usp; /* fn, kernel thread */
kregs->gpr[22] = arg;

View File

@ -16,6 +16,7 @@
#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <asm/cpuinfo.h>
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
@ -60,22 +61,32 @@ void __init smp_prepare_boot_cpu(void)
void __init smp_init_cpus(void)
{
int i;
struct device_node *cpu;
u32 cpu_id;
for (i = 0; i < NR_CPUS; i++)
set_cpu_possible(i, true);
for_each_of_cpu_node(cpu) {
if (of_property_read_u32(cpu, "reg", &cpu_id)) {
pr_warn("%s missing reg property", cpu->full_name);
continue;
}
if (cpu_id < NR_CPUS)
set_cpu_possible(cpu_id, true);
}
}
void __init smp_prepare_cpus(unsigned int max_cpus)
{
int i;
unsigned int cpu;
/*
* Initialise the present map, which describes the set of CPUs
* actually populated at the present time.
*/
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
for_each_possible_cpu(cpu) {
if (cpu < max_cpus)
set_cpu_present(cpu, true);
}
}
void __init smp_cpus_done(unsigned int max_cpus)

View File

@ -200,7 +200,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
extern void * const ret_from_kernel_thread;
extern void * const child_return;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* kernel thread */
memset(cregs, 0, sizeof(struct pt_regs));
if (!usp) /* idle thread */

View File

@ -1670,7 +1670,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
/* Copy registers */
sp -= sizeof(struct pt_regs);
childregs = (struct pt_regs *) sp;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* kernel thread */
memset(childregs, 0, sizeof(struct pt_regs));
childregs->gpr[1] = sp + sizeof(struct pt_regs);

View File

@ -124,7 +124,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
struct pt_regs *childregs = task_pt_regs(p);
/* p->thread holds context to be restored by __switch_to() */
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* Kernel thread */
memset(childregs, 0, sizeof(struct pt_regs));
childregs->gp = gp_in_global;

View File

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_S390_IRQ_WORK_H
#define _ASM_S390_IRQ_WORK_H
static inline bool arch_irq_work_has_interrupt(void)
{
return true;
}
void arch_irq_work_raise(void);
#endif /* _ASM_S390_IRQ_WORK_H */

View File

@ -135,7 +135,7 @@ static inline void pmd_populate(struct mm_struct *mm,
#define pmd_populate_kernel(mm, pmd, pte) pmd_populate(mm, pmd, pte)
#define pmd_pgtable(pmd) \
(pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE)
((pgtable_t)__va(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE))
/*
* page table entry allocation/free routines.

View File

@ -1219,8 +1219,8 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
#define p4d_deref(pud) (p4d_val(pud) & _REGION_ENTRY_ORIGIN)
#define pgd_deref(pgd) (pgd_val(pgd) & _REGION_ENTRY_ORIGIN)
#define p4d_deref(pud) ((unsigned long)__va(p4d_val(pud) & _REGION_ENTRY_ORIGIN))
#define pgd_deref(pgd) ((unsigned long)__va(pgd_val(pgd) & _REGION_ENTRY_ORIGIN))
static inline unsigned long pmd_deref(pmd_t pmd)
{
@ -1229,12 +1229,12 @@ static inline unsigned long pmd_deref(pmd_t pmd)
origin_mask = _SEGMENT_ENTRY_ORIGIN;
if (pmd_large(pmd))
origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE;
return pmd_val(pmd) & origin_mask;
return (unsigned long)__va(pmd_val(pmd) & origin_mask);
}
static inline unsigned long pmd_pfn(pmd_t pmd)
{
return pmd_deref(pmd) >> PAGE_SHIFT;
return __pa(pmd_deref(pmd)) >> PAGE_SHIFT;
}
static inline unsigned long pud_deref(pud_t pud)
@ -1244,12 +1244,12 @@ static inline unsigned long pud_deref(pud_t pud)
origin_mask = _REGION_ENTRY_ORIGIN;
if (pud_large(pud))
origin_mask = _REGION3_ENTRY_ORIGIN_LARGE;
return pud_val(pud) & origin_mask;
return (unsigned long)__va(pud_val(pud) & origin_mask);
}
static inline unsigned long pud_pfn(pud_t pud)
{
return pud_deref(pud) >> PAGE_SHIFT;
return __pa(pud_deref(pud)) >> PAGE_SHIFT;
}
/*
@ -1329,7 +1329,7 @@ static inline bool gup_fast_permitted(unsigned long start, unsigned long end)
}
#define gup_fast_permitted gup_fast_permitted
#define pfn_pte(pfn,pgprot) mk_pte_phys(__pa((pfn) << PAGE_SHIFT),(pgprot))
#define pfn_pte(pfn, pgprot) mk_pte_phys(((pfn) << PAGE_SHIFT), (pgprot))
#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
#define pte_page(x) pfn_to_page(pte_pfn(x))
@ -1636,7 +1636,7 @@ static inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
}
#define pmdp_collapse_flush pmdp_collapse_flush
#define pfn_pmd(pfn, pgprot) mk_pmd_phys(__pa((pfn) << PAGE_SHIFT), (pgprot))
#define pfn_pmd(pfn, pgprot) mk_pmd_phys(((pfn) << PAGE_SHIFT), (pgprot))
#define mk_pmd(page, pgprot) pfn_pmd(page_to_pfn(page), (pgprot))
static inline int pmd_trans_huge(pmd_t pmd)

View File

@ -0,0 +1,51 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright IBM Corp. 2021
* Interface implementation for communication with the CPU Measurement
* counter facility device driver.
*
* Author(s): Thomas Richter <tmricht@linux.ibm.com>
*
* Define for ioctl() commands to communicate with the CPU Measurement
* counter facility device driver.
*/
#ifndef _PERF_CPUM_CF_DIAG_H
#define _PERF_CPUM_CF_DIAG_H
#include <linux/ioctl.h>
#include <linux/types.h>
#define S390_HWCTR_DEVICE "hwctr"
#define S390_HWCTR_START_VERSION 1
struct s390_ctrset_start { /* Set CPUs to operate on */
__u64 version; /* Version of interface */
__u64 data_bytes; /* # of bytes required */
__u64 cpumask_len; /* Length of CPU mask in bytes */
__u64 *cpumask; /* Pointer to CPU mask */
__u64 counter_sets; /* Bit mask of counter sets to get */
};
struct s390_ctrset_setdata { /* Counter set data */
__u32 set; /* Counter set number */
__u32 no_cnts; /* # of counters stored in cv[] */
__u64 cv[0]; /* Counter values (variable length) */
};
struct s390_ctrset_cpudata { /* Counter set data per CPU */
__u32 cpu_nr; /* CPU number */
__u32 no_sets; /* # of counters sets in data[] */
struct s390_ctrset_setdata data[0];
};
struct s390_ctrset_read { /* Structure to get all ctr sets */
__u64 no_cpus; /* Total # of CPUs data taken from */
struct s390_ctrset_cpudata data[0];
};
#define S390_HWCTR_MAGIC 'C' /* Random magic # for ioctls */
#define S390_HWCTR_START _IOWR(S390_HWCTR_MAGIC, 1, struct s390_ctrset_start)
#define S390_HWCTR_STOP _IO(S390_HWCTR_MAGIC, 2)
#define S390_HWCTR_READ _IOWR(S390_HWCTR_MAGIC, 3, struct s390_ctrset_read)
#endif

View File

@ -2,7 +2,7 @@
/*
* Performance event support for s390x - CPU-measurement Counter Sets
*
* Copyright IBM Corp. 2019
* Copyright IBM Corp. 2019, 2021
* Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
* Thomas Richer <tmricht@linux.ibm.com>
*/
@ -17,6 +17,8 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/processor.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <asm/ctl_reg.h>
#include <asm/irq.h>
@ -24,15 +26,20 @@
#include <asm/timex.h>
#include <asm/debug.h>
#define CF_DIAG_CTRSET_DEF 0xfeef /* Counter set header mark */
#include <asm/perf_cpum_cf_diag.h>
#define CF_DIAG_CTRSET_DEF 0xfeef /* Counter set header mark */
#define CF_DIAG_MIN_INTERVAL 60 /* Minimum counter set read */
/* interval in seconds */
static unsigned long cf_diag_interval = CF_DIAG_MIN_INTERVAL;
static unsigned int cf_diag_cpu_speed;
static debug_info_t *cf_diag_dbg;
struct cf_diag_csd { /* Counter set data per CPU */
struct cf_diag_csd { /* Counter set data per CPU */
size_t used; /* Bytes used in data/start */
unsigned char start[PAGE_SIZE]; /* Counter set at event start */
unsigned char data[PAGE_SIZE]; /* Counter set at event delete */
unsigned int sets; /* # Counter set saved in data */
};
static DEFINE_PER_CPU(struct cf_diag_csd, cf_diag_csd);
@ -178,18 +185,35 @@ static void cf_diag_disable(struct pmu *pmu)
/* Number of perf events counting hardware events */
static atomic_t cf_diag_events = ATOMIC_INIT(0);
/* Used to avoid races in calling reserve/release_cpumf_hardware */
static DEFINE_MUTEX(cf_diag_reserve_mutex);
/* Release the PMU if event is the last perf event */
static void cf_diag_perf_event_destroy(struct perf_event *event)
{
debug_sprintf_event(cf_diag_dbg, 5,
"%s event %p cpu %d cf_diag_events %d\n",
__func__, event, event->cpu,
__func__, event, smp_processor_id(),
atomic_read(&cf_diag_events));
if (atomic_dec_return(&cf_diag_events) == 0)
__kernel_cpumcf_end();
}
static int get_authctrsets(void)
{
struct cpu_cf_events *cpuhw;
unsigned long auth = 0;
enum cpumf_ctr_set i;
cpuhw = &get_cpu_var(cpu_cf_events);
for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
if (cpuhw->info.auth_ctl & cpumf_ctr_ctl[i])
auth |= cpumf_ctr_ctl[i];
}
put_cpu_var(cpu_cf_events);
return auth;
}
/* Setup the event. Test for authorized counter sets and only include counter
* sets which are authorized at the time of the setup. Including unauthorized
* counter sets result in specification exception (and panic).
@ -197,15 +221,12 @@ static void cf_diag_perf_event_destroy(struct perf_event *event)
static int __hw_perf_event_init(struct perf_event *event)
{
struct perf_event_attr *attr = &event->attr;
struct cpu_cf_events *cpuhw;
enum cpumf_ctr_set i;
int err = 0;
debug_sprintf_event(cf_diag_dbg, 5, "%s event %p cpu %d\n", __func__,
event, event->cpu);
event->hw.config = attr->config;
event->hw.config_base = 0;
/* Add all authorized counter sets to config_base. The
* the hardware init function is either called per-cpu or just once
@ -215,11 +236,7 @@ static int __hw_perf_event_init(struct perf_event *event)
* Checking the authorization on any CPU is fine as the hardware
* applies the same authorization settings to all CPUs.
*/
cpuhw = &get_cpu_var(cpu_cf_events);
for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i)
if (cpuhw->info.auth_ctl & cpumf_ctr_ctl[i])
event->hw.config_base |= cpumf_ctr_ctl[i];
put_cpu_var(cpu_cf_events);
event->hw.config_base = get_authctrsets();
/* No authorized counter sets, nothing to count/sample */
if (!event->hw.config_base) {
@ -237,6 +254,25 @@ static int __hw_perf_event_init(struct perf_event *event)
return err;
}
/* Return 0 if the CPU-measurement counter facility is currently free
* and an error otherwise.
*/
static int cf_diag_perf_event_inuse(void)
{
int err = 0;
if (!atomic_inc_not_zero(&cf_diag_events)) {
mutex_lock(&cf_diag_reserve_mutex);
if (atomic_read(&cf_diag_events) == 0 &&
__kernel_cpumcf_begin())
err = -EBUSY;
else
err = atomic_inc_return(&cf_diag_events);
mutex_unlock(&cf_diag_reserve_mutex);
}
return err;
}
static int cf_diag_event_init(struct perf_event *event)
{
struct perf_event_attr *attr = &event->attr;
@ -264,13 +300,9 @@ static int cf_diag_event_init(struct perf_event *event)
}
/* Initialize for using the CPU-measurement counter facility */
if (atomic_inc_return(&cf_diag_events) == 1) {
if (__kernel_cpumcf_begin()) {
atomic_dec(&cf_diag_events);
err = -EBUSY;
goto out;
}
}
err = cf_diag_perf_event_inuse();
if (err < 0)
goto out;
event->destroy = cf_diag_perf_event_destroy;
err = __hw_perf_event_init(event);
@ -599,6 +631,8 @@ static void cf_diag_del(struct perf_event *event, int flags)
cpuhw->flags &= ~PMU_F_IN_USE;
}
/* Default counter set events and format attribute groups */
CPUMF_EVENT_ATTR(CF_DIAG, CF_DIAG, PERF_EVENT_CPUM_CF_DIAG);
static struct attribute *cf_diag_events_attr[] = {
@ -663,6 +697,452 @@ static void cf_diag_get_cpu_speed(void)
}
}
/* Code to create device and file I/O operations */
static atomic_t ctrset_opencnt = ATOMIC_INIT(0); /* Excl. access */
static int cf_diag_open(struct inode *inode, struct file *file)
{
int err = 0;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (atomic_xchg(&ctrset_opencnt, 1))
return -EBUSY;
/* Avoid concurrent access with perf_event_open() system call */
mutex_lock(&cf_diag_reserve_mutex);
if (atomic_read(&cf_diag_events) || __kernel_cpumcf_begin())
err = -EBUSY;
mutex_unlock(&cf_diag_reserve_mutex);
if (err) {
atomic_set(&ctrset_opencnt, 0);
return err;
}
file->private_data = NULL;
debug_sprintf_event(cf_diag_dbg, 2, "%s\n", __func__);
/* nonseekable_open() never fails */
return nonseekable_open(inode, file);
}
/* Variables for ioctl() interface support */
static DEFINE_MUTEX(cf_diag_ctrset_mutex);
static struct cf_diag_ctrset {
unsigned long ctrset; /* Bit mask of counter set to read */
cpumask_t mask; /* CPU mask to read from */
time64_t lastread; /* Epoch counter set last read */
} cf_diag_ctrset;
static void cf_diag_ctrset_clear(void)
{
cpumask_clear(&cf_diag_ctrset.mask);
cf_diag_ctrset.ctrset = 0;
}
static void cf_diag_release_cpu(void *p)
{
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
debug_sprintf_event(cf_diag_dbg, 3, "%s cpu %d\n", __func__,
smp_processor_id());
lcctl(0); /* Reset counter sets */
cpuhw->state = 0; /* Save state in CPU hardware state */
}
/* Release function is also called when application gets terminated without
* doing a proper ioctl(..., S390_HWCTR_STOP, ...) command.
* Since only one application is allowed to open the device, simple stop all
* CPU counter sets.
*/
static int cf_diag_release(struct inode *inode, struct file *file)
{
on_each_cpu(cf_diag_release_cpu, NULL, 1);
cf_diag_ctrset_clear();
atomic_set(&ctrset_opencnt, 0);
__kernel_cpumcf_end();
debug_sprintf_event(cf_diag_dbg, 2, "%s\n", __func__);
return 0;
}
struct cf_diag_call_on_cpu_parm { /* Parm struct for smp_call_on_cpu */
unsigned int sets; /* Counter set bit mask */
atomic_t cpus_ack; /* # CPUs successfully executed func */
};
static int cf_diag_all_copy(unsigned long arg, cpumask_t *mask)
{
struct s390_ctrset_read __user *ctrset_read;
unsigned int cpu, cpus, rc;
void __user *uptr;
ctrset_read = (struct s390_ctrset_read __user *)arg;
uptr = ctrset_read->data;
for_each_cpu(cpu, mask) {
struct cf_diag_csd *csd = per_cpu_ptr(&cf_diag_csd, cpu);
struct s390_ctrset_cpudata __user *ctrset_cpudata;
ctrset_cpudata = uptr;
debug_sprintf_event(cf_diag_dbg, 5, "%s cpu %d used %zd\n",
__func__, cpu, csd->used);
rc = put_user(cpu, &ctrset_cpudata->cpu_nr);
rc |= put_user(csd->sets, &ctrset_cpudata->no_sets);
rc |= copy_to_user(ctrset_cpudata->data, csd->data, csd->used);
if (rc)
return -EFAULT;
uptr += sizeof(struct s390_ctrset_cpudata) + csd->used;
cond_resched();
}
cpus = cpumask_weight(mask);
if (put_user(cpus, &ctrset_read->no_cpus))
return -EFAULT;
debug_sprintf_event(cf_diag_dbg, 5, "%s copied %ld\n",
__func__, uptr - (void __user *)ctrset_read->data);
return 0;
}
static size_t cf_diag_cpuset_read(struct s390_ctrset_setdata *p, int ctrset,
int ctrset_size, size_t room)
{
size_t need = 0;
int rc = -1;
need = sizeof(*p) + sizeof(u64) * ctrset_size;
debug_sprintf_event(cf_diag_dbg, 5,
"%s room %zd need %zd set %#x set_size %d\n",
__func__, room, need, ctrset, ctrset_size);
if (need <= room) {
p->set = cpumf_ctr_ctl[ctrset];
p->no_cnts = ctrset_size;
rc = ctr_stcctm(ctrset, ctrset_size, (u64 *)p->cv);
if (rc == 3) /* Nothing stored */
need = 0;
}
debug_sprintf_event(cf_diag_dbg, 5, "%s need %zd rc %d\n", __func__,
need, rc);
return need;
}
/* Read all counter sets. Since the perf_event_open() system call with
* event cpum_cf_diag/.../ is blocked when this interface is active, reuse
* the perf_event_open() data buffer to store the counter sets.
*/
static void cf_diag_cpu_read(void *parm)
{
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
struct cf_diag_csd *csd = this_cpu_ptr(&cf_diag_csd);
struct cf_diag_call_on_cpu_parm *p = parm;
int set, set_size;
size_t space;
debug_sprintf_event(cf_diag_dbg, 5,
"%s new %#x flags %#x state %#llx\n",
__func__, p->sets, cpuhw->flags,
cpuhw->state);
/* No data saved yet */
csd->used = 0;
csd->sets = 0;
memset(csd->data, 0, sizeof(csd->data));
/* Scan the counter sets */
for (set = CPUMF_CTR_SET_BASIC; set < CPUMF_CTR_SET_MAX; ++set) {
struct s390_ctrset_setdata *sp = (void *)csd->data + csd->used;
if (!(p->sets & cpumf_ctr_ctl[set]))
continue; /* Counter set not in list */
set_size = cf_diag_ctrset_size(set, &cpuhw->info);
space = sizeof(csd->data) - csd->used;
space = cf_diag_cpuset_read(sp, set, set_size, space);
if (space) {
csd->used += space;
csd->sets += 1;
}
debug_sprintf_event(cf_diag_dbg, 5, "%s sp %px space %zd\n",
__func__, sp, space);
}
debug_sprintf_event(cf_diag_dbg, 5, "%s sets %d used %zd\n", __func__,
csd->sets, csd->used);
}
static int cf_diag_all_read(unsigned long arg)
{
struct cf_diag_call_on_cpu_parm p;
cpumask_var_t mask;
time64_t now;
int rc = 0;
debug_sprintf_event(cf_diag_dbg, 5, "%s\n", __func__);
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
now = ktime_get_seconds();
if (cf_diag_ctrset.lastread + cf_diag_interval > now) {
debug_sprintf_event(cf_diag_dbg, 5, "%s now %lld "
" lastread %lld\n", __func__, now,
cf_diag_ctrset.lastread);
rc = -EAGAIN;
goto out;
} else {
cf_diag_ctrset.lastread = now;
}
p.sets = cf_diag_ctrset.ctrset;
cpumask_and(mask, &cf_diag_ctrset.mask, cpu_online_mask);
on_each_cpu_mask(mask, cf_diag_cpu_read, &p, 1);
rc = cf_diag_all_copy(arg, mask);
out:
free_cpumask_var(mask);
debug_sprintf_event(cf_diag_dbg, 5, "%s rc %d\n", __func__, rc);
return rc;
}
/* Stop all counter sets via ioctl interface */
static void cf_diag_ioctl_off(void *parm)
{
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
struct cf_diag_call_on_cpu_parm *p = parm;
int rc;
debug_sprintf_event(cf_diag_dbg, 5,
"%s new %#x flags %#x state %#llx\n",
__func__, p->sets, cpuhw->flags,
cpuhw->state);
ctr_set_multiple_disable(&cpuhw->state, p->sets);
ctr_set_multiple_stop(&cpuhw->state, p->sets);
rc = lcctl(cpuhw->state); /* Stop counter sets */
if (!cpuhw->state)
cpuhw->flags &= ~PMU_F_IN_USE;
debug_sprintf_event(cf_diag_dbg, 5,
"%s rc %d flags %#x state %#llx\n", __func__,
rc, cpuhw->flags, cpuhw->state);
}
/* Start counter sets on particular CPU */
static void cf_diag_ioctl_on(void *parm)
{
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
struct cf_diag_call_on_cpu_parm *p = parm;
int rc;
debug_sprintf_event(cf_diag_dbg, 5,
"%s new %#x flags %#x state %#llx\n",
__func__, p->sets, cpuhw->flags,
cpuhw->state);
if (!(cpuhw->flags & PMU_F_IN_USE))
cpuhw->state = 0;
cpuhw->flags |= PMU_F_IN_USE;
rc = lcctl(cpuhw->state); /* Reset unused counter sets */
ctr_set_multiple_enable(&cpuhw->state, p->sets);
ctr_set_multiple_start(&cpuhw->state, p->sets);
rc |= lcctl(cpuhw->state); /* Start counter sets */
if (!rc)
atomic_inc(&p->cpus_ack);
debug_sprintf_event(cf_diag_dbg, 5, "%s rc %d state %#llx\n",
__func__, rc, cpuhw->state);
}
static int cf_diag_all_stop(void)
{
struct cf_diag_call_on_cpu_parm p = {
.sets = cf_diag_ctrset.ctrset,
};
cpumask_var_t mask;
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
cpumask_and(mask, &cf_diag_ctrset.mask, cpu_online_mask);
on_each_cpu_mask(mask, cf_diag_ioctl_off, &p, 1);
free_cpumask_var(mask);
return 0;
}
static int cf_diag_all_start(void)
{
struct cf_diag_call_on_cpu_parm p = {
.sets = cf_diag_ctrset.ctrset,
.cpus_ack = ATOMIC_INIT(0),
};
cpumask_var_t mask;
int rc = 0;
if (!alloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
cpumask_and(mask, &cf_diag_ctrset.mask, cpu_online_mask);
on_each_cpu_mask(mask, cf_diag_ioctl_on, &p, 1);
if (atomic_read(&p.cpus_ack) != cpumask_weight(mask)) {
on_each_cpu_mask(mask, cf_diag_ioctl_off, &p, 1);
rc = -EIO;
}
free_cpumask_var(mask);
return rc;
}
/* Return the maximum required space for all possible CPUs in case one
* CPU will be onlined during the START, READ, STOP cycles.
* To find out the size of the counter sets, any one CPU will do. They
* all have the same counter sets.
*/
static size_t cf_diag_needspace(unsigned int sets)
{
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
size_t bytes = 0;
int i;
for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
if (!(sets & cpumf_ctr_ctl[i]))
continue;
bytes += cf_diag_ctrset_size(i, &cpuhw->info) * sizeof(u64) +
sizeof(((struct s390_ctrset_setdata *)0)->set) +
sizeof(((struct s390_ctrset_setdata *)0)->no_cnts);
}
bytes = sizeof(((struct s390_ctrset_read *)0)->no_cpus) + nr_cpu_ids *
(bytes + sizeof(((struct s390_ctrset_cpudata *)0)->cpu_nr) +
sizeof(((struct s390_ctrset_cpudata *)0)->no_sets));
debug_sprintf_event(cf_diag_dbg, 5, "%s bytes %ld\n", __func__,
bytes);
return bytes;
}
static long cf_diag_ioctl_read(unsigned long arg)
{
struct s390_ctrset_read read;
int ret = 0;
debug_sprintf_event(cf_diag_dbg, 5, "%s\n", __func__);
if (copy_from_user(&read, (char __user *)arg, sizeof(read)))
return -EFAULT;
ret = cf_diag_all_read(arg);
debug_sprintf_event(cf_diag_dbg, 5, "%s ret %d\n", __func__, ret);
return ret;
}
static long cf_diag_ioctl_stop(void)
{
int ret;
debug_sprintf_event(cf_diag_dbg, 5, "%s\n", __func__);
ret = cf_diag_all_stop();
cf_diag_ctrset_clear();
debug_sprintf_event(cf_diag_dbg, 5, "%s ret %d\n", __func__, ret);
return ret;
}
static long cf_diag_ioctl_start(unsigned long arg)
{
struct s390_ctrset_start __user *ustart;
struct s390_ctrset_start start;
void __user *umask;
unsigned int len;
int ret = 0;
size_t need;
if (cf_diag_ctrset.ctrset)
return -EBUSY;
ustart = (struct s390_ctrset_start __user *)arg;
if (copy_from_user(&start, ustart, sizeof(start)))
return -EFAULT;
if (start.version != S390_HWCTR_START_VERSION)
return -EINVAL;
if (start.counter_sets & ~(cpumf_ctr_ctl[CPUMF_CTR_SET_BASIC] |
cpumf_ctr_ctl[CPUMF_CTR_SET_USER] |
cpumf_ctr_ctl[CPUMF_CTR_SET_CRYPTO] |
cpumf_ctr_ctl[CPUMF_CTR_SET_EXT] |
cpumf_ctr_ctl[CPUMF_CTR_SET_MT_DIAG]))
return -EINVAL; /* Invalid counter set */
if (!start.counter_sets)
return -EINVAL; /* No counter set at all? */
cpumask_clear(&cf_diag_ctrset.mask);
len = min_t(u64, start.cpumask_len, cpumask_size());
umask = (void __user *)start.cpumask;
if (copy_from_user(&cf_diag_ctrset.mask, umask, len))
return -EFAULT;
if (cpumask_empty(&cf_diag_ctrset.mask))
return -EINVAL;
need = cf_diag_needspace(start.counter_sets);
if (put_user(need, &ustart->data_bytes))
ret = -EFAULT;
if (ret)
goto out;
cf_diag_ctrset.ctrset = start.counter_sets;
ret = cf_diag_all_start();
out:
if (ret)
cf_diag_ctrset_clear();
debug_sprintf_event(cf_diag_dbg, 2, "%s sets %#lx need %ld ret %d\n",
__func__, cf_diag_ctrset.ctrset, need, ret);
return ret;
}
static long cf_diag_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
int ret;
debug_sprintf_event(cf_diag_dbg, 2, "%s cmd %#x arg %lx\n", __func__,
cmd, arg);
get_online_cpus();
mutex_lock(&cf_diag_ctrset_mutex);
switch (cmd) {
case S390_HWCTR_START:
ret = cf_diag_ioctl_start(arg);
break;
case S390_HWCTR_STOP:
ret = cf_diag_ioctl_stop();
break;
case S390_HWCTR_READ:
ret = cf_diag_ioctl_read(arg);
break;
default:
ret = -ENOTTY;
break;
}
mutex_unlock(&cf_diag_ctrset_mutex);
put_online_cpus();
debug_sprintf_event(cf_diag_dbg, 2, "%s ret %d\n", __func__, ret);
return ret;
}
static const struct file_operations cf_diag_fops = {
.owner = THIS_MODULE,
.open = cf_diag_open,
.release = cf_diag_release,
.unlocked_ioctl = cf_diag_ioctl,
.compat_ioctl = cf_diag_ioctl,
.llseek = no_llseek
};
static struct miscdevice cf_diag_dev = {
.name = S390_HWCTR_DEVICE,
.minor = MISC_DYNAMIC_MINOR,
.fops = &cf_diag_fops,
};
static int cf_diag_online_cpu(unsigned int cpu)
{
struct cf_diag_call_on_cpu_parm p;
mutex_lock(&cf_diag_ctrset_mutex);
if (!cf_diag_ctrset.ctrset)
goto out;
p.sets = cf_diag_ctrset.ctrset;
cf_diag_ioctl_on(&p);
out:
mutex_unlock(&cf_diag_ctrset_mutex);
return 0;
}
static int cf_diag_offline_cpu(unsigned int cpu)
{
struct cf_diag_call_on_cpu_parm p;
mutex_lock(&cf_diag_ctrset_mutex);
if (!cf_diag_ctrset.ctrset)
goto out;
p.sets = cf_diag_ctrset.ctrset;
cf_diag_ioctl_off(&p);
out:
mutex_unlock(&cf_diag_ctrset_mutex);
return 0;
}
/* Initialize the counter set PMU to generate complete counter set data as
* event raw data. This relies on the CPU Measurement Counter Facility device
* already being loaded and initialized.
@ -685,21 +1165,43 @@ static int __init cf_diag_init(void)
return -ENOMEM;
}
rc = misc_register(&cf_diag_dev);
if (rc) {
pr_err("Registration of /dev/" S390_HWCTR_DEVICE
"failed rc=%d\n", rc);
goto out;
}
/* Setup s390dbf facility */
cf_diag_dbg = debug_register(KMSG_COMPONENT, 2, 1, 128);
if (!cf_diag_dbg) {
pr_err("Registration of s390dbf(cpum_cf_diag) failed\n");
return -ENOMEM;
rc = -ENOMEM;
goto out_dbf;
}
debug_register_view(cf_diag_dbg, &debug_sprintf_view);
rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", -1);
if (rc) {
debug_unregister_view(cf_diag_dbg, &debug_sprintf_view);
debug_unregister(cf_diag_dbg);
pr_err("Registration of PMU(cpum_cf_diag) failed with rc=%i\n",
rc);
goto out_perf;
}
rc = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_S390_CFD_ONLINE,
"perf/s390/cfd:online",
cf_diag_online_cpu, cf_diag_offline_cpu);
if (!rc)
goto out;
pr_err("Registration of CPUHP_AP_PERF_S390_CFD_ONLINE failed rc=%i\n",
rc);
perf_pmu_unregister(&cf_diag);
out_perf:
debug_unregister_view(cf_diag_dbg, &debug_sprintf_view);
debug_unregister(cf_diag_dbg);
out_dbf:
misc_deregister(&cf_diag_dev);
out:
return rc;
}
arch_initcall(cf_diag_init);
device_initcall(cf_diag_init);

View File

@ -130,7 +130,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
frame->sf.gprs[9] = (unsigned long)frame;
/* Store access registers to kernel stack of new process. */
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
/* kernel thread */
memset(&frame->childregs, 0, sizeof(struct pt_regs));
frame->childregs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT |

View File

@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irqflags.h>
#include <linux/irq_work.h>
#include <linux/cpu.h>
#include <linux/slab.h>
#include <linux/sched/hotplug.h>
@ -62,6 +63,7 @@ enum {
ec_call_function_single,
ec_stop_cpu,
ec_mcck_pending,
ec_irq_work,
};
enum {
@ -434,10 +436,12 @@ void notrace smp_yield_cpu(int cpu)
*/
void notrace smp_emergency_stop(void)
{
cpumask_t cpumask;
static arch_spinlock_t lock = __ARCH_SPIN_LOCK_UNLOCKED;
static cpumask_t cpumask;
u64 end;
int cpu;
arch_spin_lock(&lock);
cpumask_copy(&cpumask, cpu_online_mask);
cpumask_clear_cpu(smp_processor_id(), &cpumask);
@ -458,6 +462,7 @@ void notrace smp_emergency_stop(void)
break;
cpu_relax();
}
arch_spin_unlock(&lock);
}
NOKPROBE_SYMBOL(smp_emergency_stop);
@ -505,6 +510,8 @@ static void smp_handle_ext_call(void)
generic_smp_call_function_single_interrupt();
if (test_bit(ec_mcck_pending, &bits))
__s390_handle_mcck();
if (test_bit(ec_irq_work, &bits))
irq_work_run();
}
static void do_ext_call_interrupt(struct ext_code ext_code,
@ -537,6 +544,13 @@ void smp_send_reschedule(int cpu)
pcpu_ec_call(pcpu_devices + cpu, ec_schedule);
}
#ifdef CONFIG_IRQ_WORK
void arch_irq_work_raise(void)
{
pcpu_ec_call(pcpu_devices + smp_processor_id(), ec_irq_work);
}
#endif
/*
* parameter area for the set/clear control bit callbacks
*/
@ -775,11 +789,13 @@ static int smp_add_core(struct sclp_core_entry *core, cpumask_t *avail,
static int __smp_rescan_cpus(struct sclp_core_info *info, bool early)
{
struct sclp_core_entry *core;
cpumask_t avail;
static cpumask_t avail;
bool configured;
u16 core_id;
int nr, i;
get_online_cpus();
mutex_lock(&smp_cpu_state_mutex);
nr = 0;
cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask);
/*
@ -800,6 +816,8 @@ static int __smp_rescan_cpus(struct sclp_core_info *info, bool early)
configured = i < info->configured;
nr += smp_add_core(&info->core[i], &avail, configured, early);
}
mutex_unlock(&smp_cpu_state_mutex);
put_online_cpus();
return nr;
}
@ -847,9 +865,7 @@ void __init smp_detect_cpus(void)
pr_info("%d configured CPUs, %d standby CPUs\n", c_cpus, s_cpus);
/* Add CPUs present at boot */
get_online_cpus();
__smp_rescan_cpus(info, true);
put_online_cpus();
memblock_free_early((unsigned long)info, sizeof(*info));
}
@ -1178,11 +1194,7 @@ int __ref smp_rescan_cpus(void)
if (!info)
return -ENOMEM;
smp_get_core_info(info, 0);
get_online_cpus();
mutex_lock(&smp_cpu_state_mutex);
nr = __smp_rescan_cpus(info, false);
mutex_unlock(&smp_cpu_state_mutex);
put_online_cpus();
kfree(info);
if (nr)
topology_schedule_update();

View File

@ -62,16 +62,16 @@ static struct mask_info drawer_info;
struct cpu_topology_s390 cpu_topology[NR_CPUS];
EXPORT_SYMBOL_GPL(cpu_topology);
static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
static void cpu_group_map(cpumask_t *dst, struct mask_info *info, unsigned int cpu)
{
cpumask_t mask;
static cpumask_t mask;
cpumask_copy(&mask, cpumask_of(cpu));
switch (topology_mode) {
case TOPOLOGY_MODE_HW:
while (info) {
if (cpumask_test_cpu(cpu, &info->mask)) {
mask = info->mask;
cpumask_copy(&mask, &info->mask);
break;
}
info = info->next;
@ -89,23 +89,24 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
break;
}
cpumask_and(&mask, &mask, cpu_online_mask);
return mask;
cpumask_copy(dst, &mask);
}
static cpumask_t cpu_thread_map(unsigned int cpu)
static void cpu_thread_map(cpumask_t *dst, unsigned int cpu)
{
cpumask_t mask;
static cpumask_t mask;
int i;
cpumask_copy(&mask, cpumask_of(cpu));
if (topology_mode != TOPOLOGY_MODE_HW)
return mask;
goto out;
cpu -= cpu % (smp_cpu_mtid + 1);
for (i = 0; i <= smp_cpu_mtid; i++)
if (cpu_present(cpu + i))
cpumask_set_cpu(cpu + i, &mask);
cpumask_and(&mask, &mask, cpu_online_mask);
return mask;
out:
cpumask_copy(dst, &mask);
}
#define TOPOLOGY_CORE_BITS 64
@ -250,10 +251,10 @@ void update_cpu_masks(void)
for_each_possible_cpu(cpu) {
topo = &cpu_topology[cpu];
topo->thread_mask = cpu_thread_map(cpu);
topo->core_mask = cpu_group_map(&socket_info, cpu);
topo->book_mask = cpu_group_map(&book_info, cpu);
topo->drawer_mask = cpu_group_map(&drawer_info, cpu);
cpu_thread_map(&topo->thread_mask, cpu);
cpu_group_map(&topo->core_mask, &socket_info, cpu);
cpu_group_map(&topo->book_mask, &book_info, cpu);
cpu_group_map(&topo->drawer_mask, &drawer_info, cpu);
topo->booted_cores = 0;
if (topology_mode != TOPOLOGY_MODE_HW) {
id = topology_mode == TOPOLOGY_MODE_PACKAGE ? 0 : cpu;

View File

@ -58,7 +58,7 @@ unsigned long *crst_table_alloc(struct mm_struct *mm)
if (!page)
return NULL;
arch_set_page_dat(page, 2);
return (unsigned long *) page_to_phys(page);
return (unsigned long *) page_to_virt(page);
}
void crst_table_free(struct mm_struct *mm, unsigned long *table)
@ -161,7 +161,7 @@ struct page *page_table_alloc_pgste(struct mm_struct *mm)
page = alloc_page(GFP_KERNEL);
if (page) {
table = (u64 *)page_to_phys(page);
table = (u64 *)page_to_virt(page);
memset64(table, _PAGE_INVALID, PTRS_PER_PTE);
memset64(table + PTRS_PER_PTE, 0, PTRS_PER_PTE);
}
@ -194,7 +194,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
mask = atomic_read(&page->_refcount) >> 24;
mask = (mask | (mask >> 4)) & 3;
if (mask != 3) {
table = (unsigned long *) page_to_phys(page);
table = (unsigned long *) page_to_virt(page);
bit = mask & 1; /* =1 -> second 2K */
if (bit)
table += PTRS_PER_PTE;
@ -217,7 +217,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
}
arch_set_page_dat(page, 0);
/* Initialize page table */
table = (unsigned long *) page_to_phys(page);
table = (unsigned long *) page_to_virt(page);
if (mm_alloc_pgste(mm)) {
/* Return 4K page table with PGSTEs */
atomic_xor_bits(&page->_refcount, 3 << 24);
@ -239,10 +239,10 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
struct page *page;
unsigned int bit, mask;
page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
page = virt_to_page(table);
if (!mm_alloc_pgste(mm)) {
/* Free 2K page table fragment of a 4K page */
bit = (__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
bit = ((unsigned long) table & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
spin_lock_bh(&mm->context.lock);
mask = atomic_xor_bits(&page->_refcount, 1U << (bit + 24));
mask >>= 24;
@ -269,14 +269,14 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
unsigned int bit, mask;
mm = tlb->mm;
page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
page = virt_to_page(table);
if (mm_alloc_pgste(mm)) {
gmap_unlink(mm, table, vmaddr);
table = (unsigned long *) (__pa(table) | 3);
table = (unsigned long *) ((unsigned long)table | 3);
tlb_remove_table(tlb, table);
return;
}
bit = (__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t));
bit = ((unsigned long) table & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t));
spin_lock_bh(&mm->context.lock);
mask = atomic_xor_bits(&page->_refcount, 0x11U << (bit + 24));
mask >>= 24;
@ -285,7 +285,7 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
else
list_del(&page->lru);
spin_unlock_bh(&mm->context.lock);
table = (unsigned long *) (__pa(table) | (1U << bit));
table = (unsigned long *) ((unsigned long) table | (1U << bit));
tlb_remove_table(tlb, table);
}
@ -293,7 +293,7 @@ void __tlb_remove_table(void *_table)
{
unsigned int mask = (unsigned long) _table & 3;
void *table = (void *)((unsigned long) _table ^ mask);
struct page *page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
struct page *page = virt_to_page(table);
switch (mask) {
case 0: /* pmd, pud, or p4d */

View File

@ -27,14 +27,14 @@ static void __ref *vmem_alloc_pages(unsigned int order)
if (slab_is_available())
return (void *)__get_free_pages(GFP_KERNEL, order);
return (void *) memblock_phys_alloc(size, size);
return memblock_alloc(size, size);
}
static void vmem_free_pages(unsigned long addr, int order)
{
/* We don't expect boot memory to be removed ever. */
if (!slab_is_available() ||
WARN_ON_ONCE(PageReserved(phys_to_page(addr))))
WARN_ON_ONCE(PageReserved(virt_to_page(addr))))
return;
free_pages(addr, order);
}
@ -57,7 +57,7 @@ pte_t __ref *vmem_pte_alloc(void)
if (slab_is_available())
pte = (pte_t *) page_table_alloc(&init_mm);
else
pte = (pte_t *) memblock_phys_alloc(size, size);
pte = (pte_t *) memblock_alloc(size, size);
if (!pte)
return NULL;
memset64((u64 *)pte, _PAGE_INVALID, PTRS_PER_PTE);
@ -85,7 +85,7 @@ static void vmemmap_flush_unused_sub_pmd(void)
{
if (!unused_sub_pmd_start)
return;
memset(__va(unused_sub_pmd_start), PAGE_UNUSED,
memset((void *)unused_sub_pmd_start, PAGE_UNUSED,
ALIGN(unused_sub_pmd_start, PMD_SIZE) - unused_sub_pmd_start);
unused_sub_pmd_start = 0;
}
@ -98,7 +98,7 @@ static void vmemmap_mark_sub_pmd_used(unsigned long start, unsigned long end)
* getting removed (just in case the memmap never gets initialized,
* e.g., because the memory block never gets onlined).
*/
memset(__va(start), 0, sizeof(struct page));
memset((void *)start, 0, sizeof(struct page));
}
static void vmemmap_use_sub_pmd(unsigned long start, unsigned long end)
@ -119,7 +119,7 @@ static void vmemmap_use_sub_pmd(unsigned long start, unsigned long end)
static void vmemmap_use_new_sub_pmd(unsigned long start, unsigned long end)
{
void *page = __va(ALIGN_DOWN(start, PMD_SIZE));
unsigned long page = ALIGN_DOWN(start, PMD_SIZE);
vmemmap_flush_unused_sub_pmd();
@ -128,7 +128,7 @@ static void vmemmap_use_new_sub_pmd(unsigned long start, unsigned long end)
/* Mark the unused parts of the new memmap page PAGE_UNUSED. */
if (!IS_ALIGNED(start, PMD_SIZE))
memset(page, PAGE_UNUSED, start - __pa(page));
memset((void *)page, PAGE_UNUSED, start - page);
/*
* We want to avoid memset(PAGE_UNUSED) when populating the vmemmap of
* consecutive sections. Remember for the last added PMD the last
@ -141,11 +141,11 @@ static void vmemmap_use_new_sub_pmd(unsigned long start, unsigned long end)
/* Returns true if the PMD is completely unused and can be freed. */
static bool vmemmap_unuse_sub_pmd(unsigned long start, unsigned long end)
{
void *page = __va(ALIGN_DOWN(start, PMD_SIZE));
unsigned long page = ALIGN_DOWN(start, PMD_SIZE);
vmemmap_flush_unused_sub_pmd();
memset(__va(start), PAGE_UNUSED, end - start);
return !memchr_inv(page, PAGE_UNUSED, PMD_SIZE);
memset((void *)start, PAGE_UNUSED, end - start);
return !memchr_inv((void *)page, PAGE_UNUSED, PMD_SIZE);
}
/* __ref: we'll only call vmemmap_alloc_block() via vmemmap_populate() */
@ -166,7 +166,7 @@ static int __ref modify_pte_table(pmd_t *pmd, unsigned long addr,
if (pte_none(*pte))
continue;
if (!direct)
vmem_free_pages(pfn_to_phys(pte_pfn(*pte)), 0);
vmem_free_pages((unsigned long) pfn_to_virt(pte_pfn(*pte)), 0);
pte_clear(&init_mm, addr, pte);
} else if (pte_none(*pte)) {
if (!direct) {
@ -176,7 +176,7 @@ static int __ref modify_pte_table(pmd_t *pmd, unsigned long addr,
goto out;
pte_val(*pte) = __pa(new_page) | prot;
} else {
pte_val(*pte) = addr | prot;
pte_val(*pte) = __pa(addr) | prot;
}
} else {
continue;
@ -201,7 +201,7 @@ static void try_free_pte_table(pmd_t *pmd, unsigned long start)
if (!pte_none(*pte))
return;
}
vmem_pte_free(__va(pmd_deref(*pmd)));
vmem_pte_free((unsigned long *) pmd_deref(*pmd));
pmd_clear(pmd);
}
@ -242,7 +242,7 @@ static int __ref modify_pmd_table(pud_t *pud, unsigned long addr,
IS_ALIGNED(next, PMD_SIZE) &&
MACHINE_HAS_EDAT1 && addr && direct &&
!debug_pagealloc_enabled()) {
pmd_val(*pmd) = addr | prot;
pmd_val(*pmd) = __pa(addr) | prot;
pages++;
continue;
} else if (!direct && MACHINE_HAS_EDAT1) {
@ -338,7 +338,7 @@ static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end,
IS_ALIGNED(next, PUD_SIZE) &&
MACHINE_HAS_EDAT2 && addr && direct &&
!debug_pagealloc_enabled()) {
pud_val(*pud) = addr | prot;
pud_val(*pud) = __pa(addr) | prot;
pages++;
continue;
}

View File

@ -597,7 +597,7 @@ b9b3 cu42 RRE_RR
b9bd trtre RRF_U0RR
b9be srstu RRE_RR
b9bf trte RRF_U0RR
b9c0 selhhhr RRF_RURR
b9c0 selfhr RRF_RURR
b9c8 ahhhr RRF_R0RR2
b9c9 shhhr RRF_R0RR2
b9ca alhhhr RRF_R0RR2

View File

@ -27,11 +27,10 @@ static int openCnt;
static int gio_open(struct inode *inode, struct file *filp)
{
int minor;
int minor = iminor(inode);
int ret = -ENOENT;
preempt_disable();
minor = MINOR(inode->i_rdev);
if (minor < DEVCOUNT) {
if (openCnt > 0) {
ret = -EALREADY;
@ -46,9 +45,8 @@ static int gio_open(struct inode *inode, struct file *filp)
static int gio_close(struct inode *inode, struct file *filp)
{
int minor;
int minor = iminor(inode);
minor = MINOR(inode->i_rdev);
if (minor < DEVCOUNT) {
openCnt--;
}

View File

@ -114,7 +114,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
childregs = task_pt_regs(p);
p->thread.sp = (unsigned long) childregs;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(childregs, 0, sizeof(struct pt_regs));
p->thread.pc = (unsigned long) ret_from_kernel_thread;
childregs->regs[4] = arg;

View File

@ -309,7 +309,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
ti->ksp = (unsigned long) new_stack;
p->thread.kregs = childregs;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
extern int nwindows;
unsigned long psr;
memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);

View File

@ -597,7 +597,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
sizeof(struct sparc_stackf));
t->fpsaved[0] = 0;
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(child_trap_frame, 0, child_stack_sz);
__thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =
(current_pt_regs()->tstate + 1) & TSTATE_CWP;

View File

@ -157,7 +157,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
unsigned long arg, struct task_struct * p, unsigned long tls)
{
void (*handler)(void);
int kthread = current->flags & PF_KTHREAD;
int kthread = current->flags & (PF_KTHREAD | PF_IO_WORKER);
int ret = 0;
p->thread = (struct thread_struct) INIT_THREAD;

View File

@ -161,7 +161,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
#endif
/* Kernel thread ? */
if (unlikely(p->flags & PF_KTHREAD)) {
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(childregs, 0, sizeof(struct pt_regs));
kthread_frame_init(frame, sp, arg);
return 0;

View File

@ -217,7 +217,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
p->thread.sp = (unsigned long)childregs;
if (!(p->flags & PF_KTHREAD)) {
if (!(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
struct pt_regs *regs = current_pt_regs();
unsigned long usp = usp_thread_fn ?
usp_thread_fn : regs->areg[1];

View File

@ -663,7 +663,7 @@ static inline int is_loop_device(struct file *file)
{
struct inode *i = file->f_mapping->host;
return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
return i && S_ISBLK(i->i_mode) && imajor(i) == LOOP_MAJOR;
}
static int loop_validate_file(struct file *file, struct block_device *bdev)

View File

@ -480,7 +480,7 @@ static void dax_free_inode(struct inode *inode)
kfree(dax_dev->host);
dax_dev->host = NULL;
if (inode->i_rdev)
ida_simple_remove(&dax_minor_ida, MINOR(inode->i_rdev));
ida_simple_remove(&dax_minor_ida, iminor(inode));
kmem_cache_free(dax_cache, dax_dev);
}

Some files were not shown because too many files have changed in this diff Show More