mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
Merge branch 'timers/urgent' into timers/core
Pick up urgent bug fix and resolve the conflict. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
commit
303c146df1
@ -375,3 +375,19 @@ Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
Description: information about CPUs heterogeneity.
|
||||
|
||||
cpu_capacity: capacity of cpu#.
|
||||
|
||||
What: /sys/devices/system/cpu/vulnerabilities
|
||||
/sys/devices/system/cpu/vulnerabilities/meltdown
|
||||
/sys/devices/system/cpu/vulnerabilities/spectre_v1
|
||||
/sys/devices/system/cpu/vulnerabilities/spectre_v2
|
||||
Date: January 2018
|
||||
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
Description: Information about CPU vulnerabilities
|
||||
|
||||
The files are named after the code names of CPU
|
||||
vulnerabilities. The output of those files reflects the
|
||||
state of the CPUs in the system. Possible output values:
|
||||
|
||||
"Not affected" CPU is not affected by the vulnerability
|
||||
"Vulnerable" CPU is affected and no mitigation in effect
|
||||
"Mitigation: $M" CPU is affected and mitigation $M is in effect
|
||||
|
@ -713,9 +713,6 @@
|
||||
It will be ignored when crashkernel=X,high is not used
|
||||
or memory reserved is below 4G.
|
||||
|
||||
crossrelease_fullstack
|
||||
[KNL] Allow to record full stack trace in cross-release
|
||||
|
||||
cryptomgr.notests
|
||||
[KNL] Disable crypto self-tests
|
||||
|
||||
@ -2626,6 +2623,11 @@
|
||||
nosmt [KNL,S390] Disable symmetric multithreading (SMT).
|
||||
Equivalent to smt=1.
|
||||
|
||||
nospectre_v2 [X86] Disable all mitigations for the Spectre variant 2
|
||||
(indirect branch prediction) vulnerability. System may
|
||||
allow data leaks with this option, which is equivalent
|
||||
to spectre_v2=off.
|
||||
|
||||
noxsave [BUGS=X86] Disables x86 extended register state save
|
||||
and restore using xsave. The kernel will fallback to
|
||||
enabling legacy floating-point and sse state.
|
||||
@ -2712,8 +2714,6 @@
|
||||
steal time is computed, but won't influence scheduler
|
||||
behaviour
|
||||
|
||||
nopti [X86-64] Disable kernel page table isolation
|
||||
|
||||
nolapic [X86-32,APIC] Do not enable or use the local APIC.
|
||||
|
||||
nolapic_timer [X86-32,APIC] Do not use the local APIC timer.
|
||||
@ -3100,6 +3100,12 @@
|
||||
pcie_scan_all Scan all possible PCIe devices. Otherwise we
|
||||
only look for one device below a PCIe downstream
|
||||
port.
|
||||
big_root_window Try to add a big 64bit memory window to the PCIe
|
||||
root complex on AMD CPUs. Some GFX hardware
|
||||
can resize a BAR to allow access to all VRAM.
|
||||
Adding the window is slightly risky (it may
|
||||
conflict with unreported devices), so this
|
||||
taints the kernel.
|
||||
|
||||
pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power
|
||||
Management.
|
||||
@ -3288,11 +3294,20 @@
|
||||
pt. [PARIDE]
|
||||
See Documentation/blockdev/paride.txt.
|
||||
|
||||
pti= [X86_64]
|
||||
Control user/kernel address space isolation:
|
||||
on - enable
|
||||
off - disable
|
||||
auto - default setting
|
||||
pti= [X86_64] Control Page Table Isolation of user and
|
||||
kernel address spaces. Disabling this feature
|
||||
removes hardening, but improves performance of
|
||||
system calls and interrupts.
|
||||
|
||||
on - unconditionally enable
|
||||
off - unconditionally disable
|
||||
auto - kernel detects whether your CPU model is
|
||||
vulnerable to issues that PTI mitigates
|
||||
|
||||
Not specifying this option is equivalent to pti=auto.
|
||||
|
||||
nopti [X86_64]
|
||||
Equivalent to pti=off
|
||||
|
||||
pty.legacy_count=
|
||||
[KNL] Number of legacy pty's. Overwrites compiled-in
|
||||
@ -3943,6 +3958,29 @@
|
||||
sonypi.*= [HW] Sony Programmable I/O Control Device driver
|
||||
See Documentation/laptops/sonypi.txt
|
||||
|
||||
spectre_v2= [X86] Control mitigation of Spectre variant 2
|
||||
(indirect branch speculation) vulnerability.
|
||||
|
||||
on - unconditionally enable
|
||||
off - unconditionally disable
|
||||
auto - kernel detects whether your CPU model is
|
||||
vulnerable
|
||||
|
||||
Selecting 'on' will, and 'auto' may, choose a
|
||||
mitigation method at run time according to the
|
||||
CPU, the available microcode, the setting of the
|
||||
CONFIG_RETPOLINE configuration option, and the
|
||||
compiler with which the kernel was built.
|
||||
|
||||
Specific mitigations can also be selected manually:
|
||||
|
||||
retpoline - replace indirect branches
|
||||
retpoline,generic - google's original retpoline
|
||||
retpoline,amd - AMD-specific minimal thunk
|
||||
|
||||
Not specifying this option is equivalent to
|
||||
spectre_v2=auto.
|
||||
|
||||
spia_io_base= [HW,MTD]
|
||||
spia_fio_base=
|
||||
spia_pedr=
|
||||
|
@ -25,8 +25,8 @@ available from the following download page. At least "mkfs.nilfs2",
|
||||
cleaner or garbage collector) are required. Details on the tools are
|
||||
described in the man pages included in the package.
|
||||
|
||||
Project web page: http://nilfs.sourceforge.net/
|
||||
Download page: http://nilfs.sourceforge.net/en/download.html
|
||||
Project web page: https://nilfs.sourceforge.io/
|
||||
Download page: https://nilfs.sourceforge.io/en/download.html
|
||||
List info: http://vger.kernel.org/vger-lists.html#linux-nilfs
|
||||
|
||||
Caveats
|
||||
|
@ -200,10 +200,14 @@ module state. Dependency expressions have the following syntax:
|
||||
<expr> ::= <symbol> (1)
|
||||
<symbol> '=' <symbol> (2)
|
||||
<symbol> '!=' <symbol> (3)
|
||||
'(' <expr> ')' (4)
|
||||
'!' <expr> (5)
|
||||
<expr> '&&' <expr> (6)
|
||||
<expr> '||' <expr> (7)
|
||||
<symbol1> '<' <symbol2> (4)
|
||||
<symbol1> '>' <symbol2> (4)
|
||||
<symbol1> '<=' <symbol2> (4)
|
||||
<symbol1> '>=' <symbol2> (4)
|
||||
'(' <expr> ')' (5)
|
||||
'!' <expr> (6)
|
||||
<expr> '&&' <expr> (7)
|
||||
<expr> '||' <expr> (8)
|
||||
|
||||
Expressions are listed in decreasing order of precedence.
|
||||
|
||||
@ -214,10 +218,13 @@ Expressions are listed in decreasing order of precedence.
|
||||
otherwise 'n'.
|
||||
(3) If the values of both symbols are equal, it returns 'n',
|
||||
otherwise 'y'.
|
||||
(4) Returns the value of the expression. Used to override precedence.
|
||||
(5) Returns the result of (2-/expr/).
|
||||
(6) Returns the result of min(/expr/, /expr/).
|
||||
(7) Returns the result of max(/expr/, /expr/).
|
||||
(4) If value of <symbol1> is respectively lower, greater, lower-or-equal,
|
||||
or greater-or-equal than value of <symbol2>, it returns 'y',
|
||||
otherwise 'n'.
|
||||
(5) Returns the value of the expression. Used to override precedence.
|
||||
(6) Returns the result of (2-/expr/).
|
||||
(7) Returns the result of min(/expr/, /expr/).
|
||||
(8) Returns the result of max(/expr/, /expr/).
|
||||
|
||||
An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2
|
||||
respectively for calculations). A menu entry becomes visible when its
|
||||
|
@ -9,6 +9,7 @@ Contents:
|
||||
batman-adv
|
||||
kapi
|
||||
z8530book
|
||||
msg_zerocopy
|
||||
|
||||
.. only:: subproject
|
||||
|
||||
@ -16,4 +17,3 @@ Contents:
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
||||
|
||||
|
@ -72,6 +72,10 @@ this flag, a process must first signal intent by setting a socket option:
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &one, sizeof(one)))
|
||||
error(1, errno, "setsockopt zerocopy");
|
||||
|
||||
Setting the socket option only works when the socket is in its initial
|
||||
(TCP_CLOSED) state. Trying to set the option for a socket returned by accept(),
|
||||
for example, will lead to an EBUSY error. In this case, the option should be set
|
||||
to the listening socket and it will be inherited by the accepted sockets.
|
||||
|
||||
Transmission
|
||||
------------
|
||||
|
@ -693,7 +693,7 @@ such specification consists of a number of lines with an inverval value
|
||||
in each line. The rules stated above are best illustrated with an example:
|
||||
|
||||
# mkdir functions/uvc.usb0/control/header/h
|
||||
# cd functions/uvc.usb0/control/header/h
|
||||
# cd functions/uvc.usb0/control/
|
||||
# ln -s header/h class/fs
|
||||
# ln -s header/h class/ss
|
||||
# mkdir -p functions/uvc.usb0/streaming/uncompressed/u/360p
|
||||
|
@ -3403,6 +3403,52 @@ invalid, if invalid pages are written to (e.g. after the end of memory)
|
||||
or if no page table is present for the addresses (e.g. when using
|
||||
hugepages).
|
||||
|
||||
4.108 KVM_PPC_GET_CPU_CHAR
|
||||
|
||||
Capability: KVM_CAP_PPC_GET_CPU_CHAR
|
||||
Architectures: powerpc
|
||||
Type: vm ioctl
|
||||
Parameters: struct kvm_ppc_cpu_char (out)
|
||||
Returns: 0 on successful completion
|
||||
-EFAULT if struct kvm_ppc_cpu_char cannot be written
|
||||
|
||||
This ioctl gives userspace information about certain characteristics
|
||||
of the CPU relating to speculative execution of instructions and
|
||||
possible information leakage resulting from speculative execution (see
|
||||
CVE-2017-5715, CVE-2017-5753 and CVE-2017-5754). The information is
|
||||
returned in struct kvm_ppc_cpu_char, which looks like this:
|
||||
|
||||
struct kvm_ppc_cpu_char {
|
||||
__u64 character; /* characteristics of the CPU */
|
||||
__u64 behaviour; /* recommended software behaviour */
|
||||
__u64 character_mask; /* valid bits in character */
|
||||
__u64 behaviour_mask; /* valid bits in behaviour */
|
||||
};
|
||||
|
||||
For extensibility, the character_mask and behaviour_mask fields
|
||||
indicate which bits of character and behaviour have been filled in by
|
||||
the kernel. If the set of defined bits is extended in future then
|
||||
userspace will be able to tell whether it is running on a kernel that
|
||||
knows about the new bits.
|
||||
|
||||
The character field describes attributes of the CPU which can help
|
||||
with preventing inadvertent information disclosure - specifically,
|
||||
whether there is an instruction to flash-invalidate the L1 data cache
|
||||
(ori 30,30,0 or mtspr SPRN_TRIG2,rN), whether the L1 data cache is set
|
||||
to a mode where entries can only be used by the thread that created
|
||||
them, whether the bcctr[l] instruction prevents speculation, and
|
||||
whether a speculation barrier instruction (ori 31,31,0) is provided.
|
||||
|
||||
The behaviour field describes actions that software should take to
|
||||
prevent inadvertent information disclosure, and thus describes which
|
||||
vulnerabilities the hardware is subject to; specifically whether the
|
||||
L1 data cache should be flushed when returning to user mode from the
|
||||
kernel, and whether a speculation barrier should be placed between an
|
||||
array bounds check and the array access.
|
||||
|
||||
These fields use the same bit definitions as the new
|
||||
H_GET_CPU_CHARACTERISTICS hypercall.
|
||||
|
||||
5. The kvm_run structure
|
||||
------------------------
|
||||
|
||||
|
186
Documentation/x86/pti.txt
Normal file
186
Documentation/x86/pti.txt
Normal file
@ -0,0 +1,186 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
Page Table Isolation (pti, previously known as KAISER[1]) is a
|
||||
countermeasure against attacks on the shared user/kernel address
|
||||
space such as the "Meltdown" approach[2].
|
||||
|
||||
To mitigate this class of attacks, we create an independent set of
|
||||
page tables for use only when running userspace applications. When
|
||||
the kernel is entered via syscalls, interrupts or exceptions, the
|
||||
page tables are switched to the full "kernel" copy. When the system
|
||||
switches back to user mode, the user copy is used again.
|
||||
|
||||
The userspace page tables contain only a minimal amount of kernel
|
||||
data: only what is needed to enter/exit the kernel such as the
|
||||
entry/exit functions themselves and the interrupt descriptor table
|
||||
(IDT). There are a few strictly unnecessary things that get mapped
|
||||
such as the first C function when entering an interrupt (see
|
||||
comments in pti.c).
|
||||
|
||||
This approach helps to ensure that side-channel attacks leveraging
|
||||
the paging structures do not function when PTI is enabled. It can be
|
||||
enabled by setting CONFIG_PAGE_TABLE_ISOLATION=y at compile time.
|
||||
Once enabled at compile-time, it can be disabled at boot with the
|
||||
'nopti' or 'pti=' kernel parameters (see kernel-parameters.txt).
|
||||
|
||||
Page Table Management
|
||||
=====================
|
||||
|
||||
When PTI is enabled, the kernel manages two sets of page tables.
|
||||
The first set is very similar to the single set which is present in
|
||||
kernels without PTI. This includes a complete mapping of userspace
|
||||
that the kernel can use for things like copy_to_user().
|
||||
|
||||
Although _complete_, the user portion of the kernel page tables is
|
||||
crippled by setting the NX bit in the top level. This ensures
|
||||
that any missed kernel->user CR3 switch will immediately crash
|
||||
userspace upon executing its first instruction.
|
||||
|
||||
The userspace page tables map only the kernel data needed to enter
|
||||
and exit the kernel. This data is entirely contained in the 'struct
|
||||
cpu_entry_area' structure which is placed in the fixmap which gives
|
||||
each CPU's copy of the area a compile-time-fixed virtual address.
|
||||
|
||||
For new userspace mappings, the kernel makes the entries in its
|
||||
page tables like normal. The only difference is when the kernel
|
||||
makes entries in the top (PGD) level. In addition to setting the
|
||||
entry in the main kernel PGD, a copy of the entry is made in the
|
||||
userspace page tables' PGD.
|
||||
|
||||
This sharing at the PGD level also inherently shares all the lower
|
||||
layers of the page tables. This leaves a single, shared set of
|
||||
userspace page tables to manage. One PTE to lock, one set of
|
||||
accessed bits, dirty bits, etc...
|
||||
|
||||
Overhead
|
||||
========
|
||||
|
||||
Protection against side-channel attacks is important. But,
|
||||
this protection comes at a cost:
|
||||
|
||||
1. Increased Memory Use
|
||||
a. Each process now needs an order-1 PGD instead of order-0.
|
||||
(Consumes an additional 4k per process).
|
||||
b. The 'cpu_entry_area' structure must be 2MB in size and 2MB
|
||||
aligned so that it can be mapped by setting a single PMD
|
||||
entry. This consumes nearly 2MB of RAM once the kernel
|
||||
is decompressed, but no space in the kernel image itself.
|
||||
|
||||
2. Runtime Cost
|
||||
a. CR3 manipulation to switch between the page table copies
|
||||
must be done at interrupt, syscall, and exception entry
|
||||
and exit (it can be skipped when the kernel is interrupted,
|
||||
though.) Moves to CR3 are on the order of a hundred
|
||||
cycles, and are required at every entry and exit.
|
||||
b. A "trampoline" must be used for SYSCALL entry. This
|
||||
trampoline depends on a smaller set of resources than the
|
||||
non-PTI SYSCALL entry code, so requires mapping fewer
|
||||
things into the userspace page tables. The downside is
|
||||
that stacks must be switched at entry time.
|
||||
c. Global pages are disabled for all kernel structures not
|
||||
mapped into both kernel and userspace page tables. This
|
||||
feature of the MMU allows different processes to share TLB
|
||||
entries mapping the kernel. Losing the feature means more
|
||||
TLB misses after a context switch. The actual loss of
|
||||
performance is very small, however, never exceeding 1%.
|
||||
d. Process Context IDentifiers (PCID) is a CPU feature that
|
||||
allows us to skip flushing the entire TLB when switching page
|
||||
tables by setting a special bit in CR3 when the page tables
|
||||
are changed. This makes switching the page tables (at context
|
||||
switch, or kernel entry/exit) cheaper. But, on systems with
|
||||
PCID support, the context switch code must flush both the user
|
||||
and kernel entries out of the TLB. The user PCID TLB flush is
|
||||
deferred until the exit to userspace, minimizing the cost.
|
||||
See intel.com/sdm for the gory PCID/INVPCID details.
|
||||
e. The userspace page tables must be populated for each new
|
||||
process. Even without PTI, the shared kernel mappings
|
||||
are created by copying top-level (PGD) entries into each
|
||||
new process. But, with PTI, there are now *two* kernel
|
||||
mappings: one in the kernel page tables that maps everything
|
||||
and one for the entry/exit structures. At fork(), we need to
|
||||
copy both.
|
||||
f. In addition to the fork()-time copying, there must also
|
||||
be an update to the userspace PGD any time a set_pgd() is done
|
||||
on a PGD used to map userspace. This ensures that the kernel
|
||||
and userspace copies always map the same userspace
|
||||
memory.
|
||||
g. On systems without PCID support, each CR3 write flushes
|
||||
the entire TLB. That means that each syscall, interrupt
|
||||
or exception flushes the TLB.
|
||||
h. INVPCID is a TLB-flushing instruction which allows flushing
|
||||
of TLB entries for non-current PCIDs. Some systems support
|
||||
PCIDs, but do not support INVPCID. On these systems, addresses
|
||||
can only be flushed from the TLB for the current PCID. When
|
||||
flushing a kernel address, we need to flush all PCIDs, so a
|
||||
single kernel address flush will require a TLB-flushing CR3
|
||||
write upon the next use of every PCID.
|
||||
|
||||
Possible Future Work
|
||||
====================
|
||||
1. We can be more careful about not actually writing to CR3
|
||||
unless its value is actually changed.
|
||||
2. Allow PTI to be enabled/disabled at runtime in addition to the
|
||||
boot-time switching.
|
||||
|
||||
Testing
|
||||
========
|
||||
|
||||
To test stability of PTI, the following test procedure is recommended,
|
||||
ideally doing all of these in parallel:
|
||||
|
||||
1. Set CONFIG_DEBUG_ENTRY=y
|
||||
2. Run several copies of all of the tools/testing/selftests/x86/ tests
|
||||
(excluding MPX and protection_keys) in a loop on multiple CPUs for
|
||||
several minutes. These tests frequently uncover corner cases in the
|
||||
kernel entry code. In general, old kernels might cause these tests
|
||||
themselves to crash, but they should never crash the kernel.
|
||||
3. Run the 'perf' tool in a mode (top or record) that generates many
|
||||
frequent performance monitoring non-maskable interrupts (see "NMI"
|
||||
in /proc/interrupts). This exercises the NMI entry/exit code which
|
||||
is known to trigger bugs in code paths that did not expect to be
|
||||
interrupted, including nested NMIs. Using "-c" boosts the rate of
|
||||
NMIs, and using two -c with separate counters encourages nested NMIs
|
||||
and less deterministic behavior.
|
||||
|
||||
while true; do perf record -c 10000 -e instructions,cycles -a sleep 10; done
|
||||
|
||||
4. Launch a KVM virtual machine.
|
||||
5. Run 32-bit binaries on systems supporting the SYSCALL instruction.
|
||||
This has been a lightly-tested code path and needs extra scrutiny.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
Bugs in PTI cause a few different signatures of crashes
|
||||
that are worth noting here.
|
||||
|
||||
* Failures of the selftests/x86 code. Usually a bug in one of the
|
||||
more obscure corners of entry_64.S
|
||||
* Crashes in early boot, especially around CPU bringup. Bugs
|
||||
in the trampoline code or mappings cause these.
|
||||
* Crashes at the first interrupt. Caused by bugs in entry_64.S,
|
||||
like screwing up a page table switch. Also caused by
|
||||
incorrectly mapping the IRQ handler entry code.
|
||||
* Crashes at the first NMI. The NMI code is separate from main
|
||||
interrupt handlers and can have bugs that do not affect
|
||||
normal interrupts. Also caused by incorrectly mapping NMI
|
||||
code. NMIs that interrupt the entry code must be very
|
||||
careful and can be the cause of crashes that show up when
|
||||
running perf.
|
||||
* Kernel crashes at the first exit to userspace. entry_64.S
|
||||
bugs, or failing to map some of the exit code.
|
||||
* Crashes at first interrupt that interrupts userspace. The paths
|
||||
in entry_64.S that return to userspace are sometimes separate
|
||||
from the ones that return to the kernel.
|
||||
* Double faults: overflowing the kernel stack because of page
|
||||
faults upon page faults. Caused by touching non-pti-mapped
|
||||
data in the entry code, or forgetting to switch to kernel
|
||||
CR3 before calling into C functions which are not pti-mapped.
|
||||
* Userspace segfaults early in boot, sometimes manifesting
|
||||
as mount(8) failing to mount the rootfs. These have
|
||||
tended to be TLB invalidation issues. Usually invalidating
|
||||
the wrong PCID, or otherwise missing an invalidation.
|
||||
|
||||
1. https://gruss.cc/files/kaiser.pdf
|
||||
2. https://meltdownattack.com/meltdown.pdf
|
19
MAINTAINERS
19
MAINTAINERS
@ -62,7 +62,15 @@ trivial patch so apply some common sense.
|
||||
|
||||
7. When sending security related changes or reports to a maintainer
|
||||
please Cc: security@kernel.org, especially if the maintainer
|
||||
does not respond.
|
||||
does not respond. Please keep in mind that the security team is
|
||||
a small set of people who can be efficient only when working on
|
||||
verified bugs. Please only Cc: this list when you have identified
|
||||
that the bug would present a short-term risk to other users if it
|
||||
were publicly disclosed. For example, reports of address leaks do
|
||||
not represent an immediate threat and are better handled publicly,
|
||||
and ideally, should come with a patch proposal. Please do not send
|
||||
automated reports to this list either. Such bugs will be handled
|
||||
better and faster in the usual public places.
|
||||
|
||||
8. Happy hacking.
|
||||
|
||||
@ -9085,6 +9093,7 @@ F: drivers/usb/image/microtek.*
|
||||
|
||||
MIPS
|
||||
M: Ralf Baechle <ralf@linux-mips.org>
|
||||
M: James Hogan <jhogan@kernel.org>
|
||||
L: linux-mips@linux-mips.org
|
||||
W: http://www.linux-mips.org/
|
||||
T: git git://git.linux-mips.org/pub/scm/ralf/linux.git
|
||||
@ -9638,8 +9647,8 @@ F: include/uapi/linux/sunrpc/
|
||||
NILFS2 FILESYSTEM
|
||||
M: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
|
||||
L: linux-nilfs@vger.kernel.org
|
||||
W: http://nilfs.sourceforge.net/
|
||||
W: http://nilfs.osdn.jp/
|
||||
W: https://nilfs.sourceforge.io/
|
||||
W: https://nilfs.osdn.jp/
|
||||
T: git git://github.com/konis/nilfs2.git
|
||||
S: Supported
|
||||
F: Documentation/filesystems/nilfs2.txt
|
||||
@ -10134,7 +10143,7 @@ F: drivers/irqchip/irq-ompic.c
|
||||
F: drivers/irqchip/irq-or1k-*
|
||||
|
||||
OPENVSWITCH
|
||||
M: Pravin Shelar <pshelar@nicira.com>
|
||||
M: Pravin B Shelar <pshelar@ovn.org>
|
||||
L: netdev@vger.kernel.org
|
||||
L: dev@openvswitch.org
|
||||
W: http://openvswitch.org
|
||||
@ -12232,7 +12241,7 @@ M: Security Officers <security@kernel.org>
|
||||
S: Supported
|
||||
|
||||
SECURITY SUBSYSTEM
|
||||
M: James Morris <james.l.morris@oracle.com>
|
||||
M: James Morris <jmorris@namei.org>
|
||||
M: "Serge E. Hallyn" <serge@hallyn.com>
|
||||
L: linux-security-module@vger.kernel.org (suggested Cc:)
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git
|
||||
|
45
Makefile
45
Makefile
@ -2,7 +2,7 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 15
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc9
|
||||
NAME = Fearless Coyote
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@ -484,26 +484,6 @@ CLANG_GCC_TC := --gcc-toolchain=$(GCC_TOOLCHAIN)
|
||||
endif
|
||||
KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
|
||||
KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
|
||||
KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, unused-variable)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
|
||||
# Quiet clang warning: comparison of unsigned expression < 0 is always false
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare)
|
||||
# CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the
|
||||
# source of a reference will be _MergedGlobals and not on of the whitelisted names.
|
||||
# See modpost pattern 2
|
||||
KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,)
|
||||
KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior)
|
||||
KBUILD_CFLAGS += $(call cc-option, -no-integrated-as)
|
||||
KBUILD_AFLAGS += $(call cc-option, -no-integrated-as)
|
||||
else
|
||||
|
||||
# These warnings generated too much noise in a regular build.
|
||||
# Use make W=1 to enable them (see scripts/Makefile.extrawarn)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
|
||||
endif
|
||||
|
||||
ifeq ($(config-targets),1)
|
||||
@ -716,6 +696,29 @@ ifdef CONFIG_CC_STACKPROTECTOR
|
||||
endif
|
||||
KBUILD_CFLAGS += $(stackp-flag)
|
||||
|
||||
ifeq ($(cc-name),clang)
|
||||
KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, unused-variable)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
|
||||
# Quiet clang warning: comparison of unsigned expression < 0 is always false
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare)
|
||||
# CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the
|
||||
# source of a reference will be _MergedGlobals and not on of the whitelisted names.
|
||||
# See modpost pattern 2
|
||||
KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,)
|
||||
KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior)
|
||||
KBUILD_CFLAGS += $(call cc-option, -no-integrated-as)
|
||||
KBUILD_AFLAGS += $(call cc-option, -no-integrated-as)
|
||||
else
|
||||
|
||||
# These warnings generated too much noise in a regular build.
|
||||
# Use make W=1 to enable them (see scripts/Makefile.extrawarn)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FRAME_POINTER
|
||||
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||
else
|
||||
|
@ -102,6 +102,15 @@ sio_pci_route(void)
|
||||
alpha_mv.sys.sio.route_tab);
|
||||
}
|
||||
|
||||
static bool sio_pci_dev_irq_needs_level(const struct pci_dev *dev)
|
||||
{
|
||||
if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
|
||||
(dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned int __init
|
||||
sio_collect_irq_levels(void)
|
||||
{
|
||||
@ -110,8 +119,7 @@ sio_collect_irq_levels(void)
|
||||
|
||||
/* Iterate through the devices, collecting IRQ levels. */
|
||||
for_each_pci_dev(dev) {
|
||||
if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
|
||||
(dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
|
||||
if (!sio_pci_dev_irq_needs_level(dev))
|
||||
continue;
|
||||
|
||||
if (dev->irq)
|
||||
@ -120,8 +128,7 @@ sio_collect_irq_levels(void)
|
||||
return level_bits;
|
||||
}
|
||||
|
||||
static void __init
|
||||
sio_fixup_irq_levels(unsigned int level_bits)
|
||||
static void __sio_fixup_irq_levels(unsigned int level_bits, bool reset)
|
||||
{
|
||||
unsigned int old_level_bits;
|
||||
|
||||
@ -139,12 +146,21 @@ sio_fixup_irq_levels(unsigned int level_bits)
|
||||
*/
|
||||
old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
|
||||
|
||||
level_bits |= (old_level_bits & 0x71ff);
|
||||
if (reset)
|
||||
old_level_bits &= 0x71ff;
|
||||
|
||||
level_bits |= old_level_bits;
|
||||
|
||||
outb((level_bits >> 0) & 0xff, 0x4d0);
|
||||
outb((level_bits >> 8) & 0xff, 0x4d1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
sio_fixup_irq_levels(unsigned int level_bits)
|
||||
{
|
||||
__sio_fixup_irq_levels(level_bits, true);
|
||||
}
|
||||
|
||||
static inline int
|
||||
noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
@ -181,7 +197,14 @@ noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5;
|
||||
int irq = COMMON_TABLE_LOOKUP, tmp;
|
||||
tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
|
||||
return irq >= 0 ? tmp : -1;
|
||||
|
||||
irq = irq >= 0 ? tmp : -1;
|
||||
|
||||
/* Fixup IRQ level if an actual IRQ mapping is detected */
|
||||
if (sio_pci_dev_irq_needs_level(dev) && irq >= 0)
|
||||
__sio_fixup_irq_levels(1 << irq, false);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -18,7 +18,7 @@
|
||||
* The algorithm for the leading and trailing quadwords remains the same,
|
||||
* however the loop has been unrolled to enable better memory throughput,
|
||||
* and the code has been replicated for each of the entry points: __memset
|
||||
* and __memsetw to permit better scheduling to eliminate the stalling
|
||||
* and __memset16 to permit better scheduling to eliminate the stalling
|
||||
* encountered during the mask replication.
|
||||
* A future enhancement might be to put in a byte store loop for really
|
||||
* small (say < 32 bytes) memset()s. Whether or not that change would be
|
||||
@ -34,7 +34,7 @@
|
||||
.globl memset
|
||||
.globl __memset
|
||||
.globl ___memset
|
||||
.globl __memsetw
|
||||
.globl __memset16
|
||||
.globl __constant_c_memset
|
||||
|
||||
.ent ___memset
|
||||
@ -415,9 +415,9 @@ end:
|
||||
* to mask stalls. Note that entry point names also had to change
|
||||
*/
|
||||
.align 5
|
||||
.ent __memsetw
|
||||
.ent __memset16
|
||||
|
||||
__memsetw:
|
||||
__memset16:
|
||||
.frame $30,0,$26,0
|
||||
.prologue 0
|
||||
|
||||
@ -596,8 +596,8 @@ end_w:
|
||||
nop
|
||||
ret $31,($26),1 # L0 :
|
||||
|
||||
.end __memsetw
|
||||
EXPORT_SYMBOL(__memsetw)
|
||||
.end __memset16
|
||||
EXPORT_SYMBOL(__memset16)
|
||||
|
||||
memset = ___memset
|
||||
__memset = ___memset
|
||||
|
@ -35,6 +35,14 @@
|
||||
reg = <0x80 0x10>, <0x100 0x10>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&input_clk>;
|
||||
|
||||
/*
|
||||
* Set initial core pll output frequency to 90MHz.
|
||||
* It will be applied at the core pll driver probing
|
||||
* on early boot.
|
||||
*/
|
||||
assigned-clocks = <&core_clk>;
|
||||
assigned-clock-rates = <90000000>;
|
||||
};
|
||||
|
||||
core_intc: archs-intc@cpu {
|
||||
|
@ -35,6 +35,14 @@
|
||||
reg = <0x80 0x10>, <0x100 0x10>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&input_clk>;
|
||||
|
||||
/*
|
||||
* Set initial core pll output frequency to 100MHz.
|
||||
* It will be applied at the core pll driver probing
|
||||
* on early boot.
|
||||
*/
|
||||
assigned-clocks = <&core_clk>;
|
||||
assigned-clock-rates = <100000000>;
|
||||
};
|
||||
|
||||
core_intc: archs-intc@cpu {
|
||||
|
@ -114,6 +114,14 @@
|
||||
reg = <0x00 0x10>, <0x14B8 0x4>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&input_clk>;
|
||||
|
||||
/*
|
||||
* Set initial core pll output frequency to 1GHz.
|
||||
* It will be applied at the core pll driver probing
|
||||
* on early boot.
|
||||
*/
|
||||
assigned-clocks = <&core_clk>;
|
||||
assigned-clock-rates = <1000000000>;
|
||||
};
|
||||
|
||||
serial: serial@5000 {
|
||||
|
@ -49,10 +49,11 @@ CONFIG_SERIAL_8250_DW=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_DRM=y
|
||||
# CONFIG_DRM_FBDEV_EMULATION is not set
|
||||
CONFIG_DRM_UDL=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_UDL=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_HCD_PLATFORM=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -668,6 +668,7 @@ __arc_strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
return 0;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" mov lp_count, %5 \n"
|
||||
" lp 3f \n"
|
||||
"1: ldb.ab %3, [%2, 1] \n"
|
||||
" breq.d %3, 0, 3f \n"
|
||||
@ -684,8 +685,8 @@ __arc_strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
" .word 1b, 4b \n"
|
||||
" .previous \n"
|
||||
: "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
|
||||
: "g"(-EFAULT), "l"(count)
|
||||
: "memory");
|
||||
: "g"(-EFAULT), "r"(count)
|
||||
: "lp_count", "lp_start", "lp_end", "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ static void read_arc_build_cfg_regs(void)
|
||||
unsigned int exec_ctrl;
|
||||
|
||||
READ_BCR(AUX_EXEC_CTRL, exec_ctrl);
|
||||
cpu->extn.dual_enb = exec_ctrl & 1;
|
||||
cpu->extn.dual_enb = !(exec_ctrl & 1);
|
||||
|
||||
/* dual issue always present for this core */
|
||||
cpu->extn.dual = 1;
|
||||
|
@ -163,7 +163,7 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
|
||||
*/
|
||||
static int __print_sym(unsigned int address, void *unused)
|
||||
{
|
||||
__print_symbol(" %s\n", address);
|
||||
printk(" %pS\n", (void *)address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,7 @@ DO_ERROR_INFO(SIGILL, "Illegal Insn (or Seq)", insterror_is_error, ILL_ILLOPC)
|
||||
DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", __weak do_memory_error, BUS_ADRERR)
|
||||
DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
|
||||
DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN)
|
||||
DO_ERROR_INFO(SIGSEGV, "gcc generated __builtin_trap", do_trap5_error, 0)
|
||||
|
||||
/*
|
||||
* Entry Point for Misaligned Data access Exception, for emulating in software
|
||||
@ -115,6 +116,8 @@ void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
|
||||
* Thus TRAP_S <n> can be used for specific purpose
|
||||
* -1 used for software breakpointing (gdb)
|
||||
* -2 used by kprobes
|
||||
* -5 __builtin_trap() generated by gcc (2018.03 onwards) for toggle such as
|
||||
* -fno-isolate-erroneous-paths-dereference
|
||||
*/
|
||||
void do_non_swi_trap(unsigned long address, struct pt_regs *regs)
|
||||
{
|
||||
@ -134,6 +137,9 @@ void do_non_swi_trap(unsigned long address, struct pt_regs *regs)
|
||||
kgdb_trap(regs);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
do_trap5_error(address, regs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -155,3 +161,11 @@ void do_insterror_or_kprobe(unsigned long address, struct pt_regs *regs)
|
||||
|
||||
insterror_is_error(address, regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* abort() call generated by older gcc for __builtin_trap()
|
||||
*/
|
||||
void abort(void)
|
||||
{
|
||||
__asm__ __volatile__("trap_s 5\n");
|
||||
}
|
||||
|
@ -163,6 +163,9 @@ static void show_ecr_verbose(struct pt_regs *regs)
|
||||
else
|
||||
pr_cont("Bus Error, check PRM\n");
|
||||
#endif
|
||||
} else if (vec == ECR_V_TRAP) {
|
||||
if (regs->ecr_param == 5)
|
||||
pr_cont("gcc generated __builtin_trap\n");
|
||||
} else {
|
||||
pr_cont("Check Programmer's Manual\n");
|
||||
}
|
||||
|
@ -317,25 +317,23 @@ static void __init axs103_early_init(void)
|
||||
* Instead of duplicating defconfig/DT for SMP/QUAD, add a small hack
|
||||
* of fudging the freq in DT
|
||||
*/
|
||||
#define AXS103_QUAD_CORE_CPU_FREQ_HZ 50000000
|
||||
|
||||
unsigned int num_cores = (read_aux_reg(ARC_REG_MCIP_BCR) >> 16) & 0x3F;
|
||||
if (num_cores > 2) {
|
||||
u32 freq = 50, orig;
|
||||
/*
|
||||
* TODO: use cpu node "cpu-freq" param instead of platform-specific
|
||||
* "/cpu_card/core_clk" as it works only if we use fixed-clock for cpu.
|
||||
*/
|
||||
u32 freq;
|
||||
int off = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk");
|
||||
const struct fdt_property *prop;
|
||||
|
||||
prop = fdt_get_property(initial_boot_params, off,
|
||||
"clock-frequency", NULL);
|
||||
orig = be32_to_cpu(*(u32*)(prop->data)) / 1000000;
|
||||
"assigned-clock-rates", NULL);
|
||||
freq = be32_to_cpu(*(u32 *)(prop->data));
|
||||
|
||||
/* Patching .dtb in-place with new core clock value */
|
||||
if (freq != orig ) {
|
||||
freq = cpu_to_be32(freq * 1000000);
|
||||
if (freq != AXS103_QUAD_CORE_CPU_FREQ_HZ) {
|
||||
freq = cpu_to_be32(AXS103_QUAD_CORE_CPU_FREQ_HZ);
|
||||
fdt_setprop_inplace(initial_boot_params, off,
|
||||
"clock-frequency", &freq, sizeof(freq));
|
||||
"assigned-clock-rates", &freq, sizeof(freq));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -38,42 +38,6 @@ static void __init hsdk_init_per_cpu(unsigned int cpu)
|
||||
#define CREG_PAE (CREG_BASE + 0x180)
|
||||
#define CREG_PAE_UPDATE (CREG_BASE + 0x194)
|
||||
|
||||
#define CREG_CORE_IF_CLK_DIV (CREG_BASE + 0x4B8)
|
||||
#define CREG_CORE_IF_CLK_DIV_2 0x1
|
||||
#define CGU_BASE ARC_PERIPHERAL_BASE
|
||||
#define CGU_PLL_STATUS (ARC_PERIPHERAL_BASE + 0x4)
|
||||
#define CGU_PLL_CTRL (ARC_PERIPHERAL_BASE + 0x0)
|
||||
#define CGU_PLL_STATUS_LOCK BIT(0)
|
||||
#define CGU_PLL_STATUS_ERR BIT(1)
|
||||
#define CGU_PLL_CTRL_1GHZ 0x3A10
|
||||
#define HSDK_PLL_LOCK_TIMEOUT 500
|
||||
|
||||
#define HSDK_PLL_LOCKED() \
|
||||
!!(ioread32((void __iomem *) CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK)
|
||||
|
||||
#define HSDK_PLL_ERR() \
|
||||
!!(ioread32((void __iomem *) CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR)
|
||||
|
||||
static void __init hsdk_set_cpu_freq_1ghz(void)
|
||||
{
|
||||
u32 timeout = HSDK_PLL_LOCK_TIMEOUT;
|
||||
|
||||
/*
|
||||
* As we set cpu clock which exceeds 500MHz, the divider for the interface
|
||||
* clock must be programmed to div-by-2.
|
||||
*/
|
||||
iowrite32(CREG_CORE_IF_CLK_DIV_2, (void __iomem *) CREG_CORE_IF_CLK_DIV);
|
||||
|
||||
/* Set cpu clock to 1GHz */
|
||||
iowrite32(CGU_PLL_CTRL_1GHZ, (void __iomem *) CGU_PLL_CTRL);
|
||||
|
||||
while (!HSDK_PLL_LOCKED() && timeout--)
|
||||
cpu_relax();
|
||||
|
||||
if (!HSDK_PLL_LOCKED() || HSDK_PLL_ERR())
|
||||
pr_err("Failed to setup CPU frequency to 1GHz!");
|
||||
}
|
||||
|
||||
#define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000)
|
||||
#define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108)
|
||||
#define SDIO_UHS_REG_EXT_DIV_2 (2 << 30)
|
||||
@ -98,12 +62,6 @@ static void __init hsdk_init_early(void)
|
||||
* minimum possible div-by-2.
|
||||
*/
|
||||
iowrite32(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *) SDIO_UHS_REG_EXT);
|
||||
|
||||
/*
|
||||
* Setup CPU frequency to 1GHz.
|
||||
* TODO: remove it after smart hsdk pll driver will be introduced.
|
||||
*/
|
||||
hsdk_set_cpu_freq_1ghz();
|
||||
}
|
||||
|
||||
static const char *hsdk_compat[] __initconst = {
|
||||
|
@ -293,12 +293,12 @@
|
||||
label = "u-boot env";
|
||||
reg = <0 0x020000>;
|
||||
};
|
||||
partition@0x020000 {
|
||||
partition@20000 {
|
||||
/* The LCDK defaults to booting from this partition */
|
||||
label = "u-boot";
|
||||
reg = <0x020000 0x080000>;
|
||||
};
|
||||
partition@0x0a0000 {
|
||||
partition@a0000 {
|
||||
label = "free space";
|
||||
reg = <0x0a0000 0>;
|
||||
};
|
||||
|
@ -53,7 +53,8 @@
|
||||
};
|
||||
|
||||
pinctrl: pin-controller@10000 {
|
||||
pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header>;
|
||||
pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header
|
||||
&pmx_gpio_header_gpo>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
pmx_uart0: pmx-uart0 {
|
||||
@ -85,11 +86,16 @@
|
||||
* ground.
|
||||
*/
|
||||
pmx_gpio_header: pmx-gpio-header {
|
||||
marvell,pins = "mpp17", "mpp7", "mpp29", "mpp28",
|
||||
marvell,pins = "mpp17", "mpp29", "mpp28",
|
||||
"mpp35", "mpp34", "mpp40";
|
||||
marvell,function = "gpio";
|
||||
};
|
||||
|
||||
pmx_gpio_header_gpo: pxm-gpio-header-gpo {
|
||||
marvell,pins = "mpp7";
|
||||
marvell,function = "gpo";
|
||||
};
|
||||
|
||||
pmx_gpio_init: pmx-init {
|
||||
marvell,pins = "mpp38";
|
||||
marvell,function = "gpio";
|
||||
|
@ -1104,7 +1104,7 @@
|
||||
|
||||
be1_out_tcon0: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&tcon1_in_be0>;
|
||||
remote-endpoint = <&tcon0_in_be1>;
|
||||
};
|
||||
|
||||
be1_out_tcon1: endpoint@1 {
|
||||
|
@ -1354,7 +1354,7 @@
|
||||
|
||||
be1_out_tcon0: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&tcon1_in_be0>;
|
||||
remote-endpoint = <&tcon0_in_be1>;
|
||||
};
|
||||
|
||||
be1_out_tcon1: endpoint@1 {
|
||||
|
@ -10,6 +10,7 @@ CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=8
|
||||
CONFIG_AEABI=y
|
||||
CONFIG_HIGHMEM=y
|
||||
CONFIG_CMA=y
|
||||
CONFIG_ARM_APPENDED_DTB=y
|
||||
CONFIG_ARM_ATAG_DTB_COMPAT=y
|
||||
CONFIG_CPU_FREQ=y
|
||||
@ -33,6 +34,7 @@ CONFIG_CAN_SUN4I=y
|
||||
# CONFIG_WIRELESS is not set
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
CONFIG_DMA_CMA=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_AHCI_SUNXI=y
|
||||
|
@ -27,14 +27,58 @@
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
/*
|
||||
* eBPF prog stack layout:
|
||||
*
|
||||
* high
|
||||
* original ARM_SP => +-----+
|
||||
* | | callee saved registers
|
||||
* +-----+ <= (BPF_FP + SCRATCH_SIZE)
|
||||
* | ... | eBPF JIT scratch space
|
||||
* eBPF fp register => +-----+
|
||||
* (BPF_FP) | ... | eBPF prog stack
|
||||
* +-----+
|
||||
* |RSVD | JIT scratchpad
|
||||
* current ARM_SP => +-----+ <= (BPF_FP - STACK_SIZE + SCRATCH_SIZE)
|
||||
* | |
|
||||
* | ... | Function call stack
|
||||
* | |
|
||||
* +-----+
|
||||
* low
|
||||
*
|
||||
* The callee saved registers depends on whether frame pointers are enabled.
|
||||
* With frame pointers (to be compliant with the ABI):
|
||||
*
|
||||
* high
|
||||
* original ARM_SP => +------------------+ \
|
||||
* | pc | |
|
||||
* current ARM_FP => +------------------+ } callee saved registers
|
||||
* |r4-r8,r10,fp,ip,lr| |
|
||||
* +------------------+ /
|
||||
* low
|
||||
*
|
||||
* Without frame pointers:
|
||||
*
|
||||
* high
|
||||
* original ARM_SP => +------------------+
|
||||
* | r4-r8,r10,fp,lr | callee saved registers
|
||||
* current ARM_FP => +------------------+
|
||||
* low
|
||||
*
|
||||
* When popping registers off the stack at the end of a BPF function, we
|
||||
* reference them via the current ARM_FP register.
|
||||
*/
|
||||
#define CALLEE_MASK (1 << ARM_R4 | 1 << ARM_R5 | 1 << ARM_R6 | \
|
||||
1 << ARM_R7 | 1 << ARM_R8 | 1 << ARM_R10 | \
|
||||
1 << ARM_FP)
|
||||
#define CALLEE_PUSH_MASK (CALLEE_MASK | 1 << ARM_LR)
|
||||
#define CALLEE_POP_MASK (CALLEE_MASK | 1 << ARM_PC)
|
||||
|
||||
#define STACK_OFFSET(k) (k)
|
||||
#define TMP_REG_1 (MAX_BPF_JIT_REG + 0) /* TEMP Register 1 */
|
||||
#define TMP_REG_2 (MAX_BPF_JIT_REG + 1) /* TEMP Register 2 */
|
||||
#define TCALL_CNT (MAX_BPF_JIT_REG + 2) /* Tail Call Count */
|
||||
|
||||
/* Flags used for JIT optimization */
|
||||
#define SEEN_CALL (1 << 0)
|
||||
|
||||
#define FLAG_IMM_OVERFLOW (1 << 0)
|
||||
|
||||
/*
|
||||
@ -95,7 +139,6 @@ static const u8 bpf2a32[][2] = {
|
||||
* idx : index of current last JITed instruction.
|
||||
* prologue_bytes : bytes used in prologue.
|
||||
* epilogue_offset : offset of epilogue starting.
|
||||
* seen : bit mask used for JIT optimization.
|
||||
* offsets : array of eBPF instruction offsets in
|
||||
* JITed code.
|
||||
* target : final JITed code.
|
||||
@ -110,7 +153,6 @@ struct jit_ctx {
|
||||
unsigned int idx;
|
||||
unsigned int prologue_bytes;
|
||||
unsigned int epilogue_offset;
|
||||
u32 seen;
|
||||
u32 flags;
|
||||
u32 *offsets;
|
||||
u32 *target;
|
||||
@ -179,8 +221,13 @@ static void jit_fill_hole(void *area, unsigned int size)
|
||||
*ptr++ = __opcode_to_mem_arm(ARM_INST_UDF);
|
||||
}
|
||||
|
||||
/* Stack must be multiples of 16 Bytes */
|
||||
#define STACK_ALIGN(sz) (((sz) + 3) & ~3)
|
||||
#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
|
||||
/* EABI requires the stack to be aligned to 64-bit boundaries */
|
||||
#define STACK_ALIGNMENT 8
|
||||
#else
|
||||
/* Stack must be aligned to 32-bit boundaries */
|
||||
#define STACK_ALIGNMENT 4
|
||||
#endif
|
||||
|
||||
/* Stack space for BPF_REG_2, BPF_REG_3, BPF_REG_4,
|
||||
* BPF_REG_5, BPF_REG_7, BPF_REG_8, BPF_REG_9,
|
||||
@ -194,7 +241,7 @@ static void jit_fill_hole(void *area, unsigned int size)
|
||||
+ SCRATCH_SIZE + \
|
||||
+ 4 /* extra for skb_copy_bits buffer */)
|
||||
|
||||
#define STACK_SIZE STACK_ALIGN(_STACK_SIZE)
|
||||
#define STACK_SIZE ALIGN(_STACK_SIZE, STACK_ALIGNMENT)
|
||||
|
||||
/* Get the offset of eBPF REGISTERs stored on scratch space. */
|
||||
#define STACK_VAR(off) (STACK_SIZE-off-4)
|
||||
@ -285,16 +332,19 @@ static inline void emit_mov_i(const u8 rd, u32 val, struct jit_ctx *ctx)
|
||||
emit_mov_i_no8m(rd, val, ctx);
|
||||
}
|
||||
|
||||
static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
|
||||
static void emit_bx_r(u8 tgt_reg, struct jit_ctx *ctx)
|
||||
{
|
||||
ctx->seen |= SEEN_CALL;
|
||||
#if __LINUX_ARM_ARCH__ < 5
|
||||
emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
|
||||
|
||||
if (elf_hwcap & HWCAP_THUMB)
|
||||
emit(ARM_BX(tgt_reg), ctx);
|
||||
else
|
||||
emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx);
|
||||
}
|
||||
|
||||
static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
|
||||
{
|
||||
#if __LINUX_ARM_ARCH__ < 5
|
||||
emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
|
||||
emit_bx_r(tgt_reg, ctx);
|
||||
#else
|
||||
emit(ARM_BLX_R(tgt_reg), ctx);
|
||||
#endif
|
||||
@ -354,7 +404,6 @@ static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
|
||||
}
|
||||
|
||||
/* Call appropriate function */
|
||||
ctx->seen |= SEEN_CALL;
|
||||
emit_mov_i(ARM_IP, op == BPF_DIV ?
|
||||
(u32)jit_udiv32 : (u32)jit_mod32, ctx);
|
||||
emit_blx_r(ARM_IP, ctx);
|
||||
@ -620,8 +669,6 @@ static inline void emit_a32_lsh_r64(const u8 dst[], const u8 src[], bool dstk,
|
||||
/* Do LSH operation */
|
||||
emit(ARM_SUB_I(ARM_IP, rt, 32), ctx);
|
||||
emit(ARM_RSB_I(tmp2[0], rt, 32), ctx);
|
||||
/* As we are using ARM_LR */
|
||||
ctx->seen |= SEEN_CALL;
|
||||
emit(ARM_MOV_SR(ARM_LR, rm, SRTYPE_ASL, rt), ctx);
|
||||
emit(ARM_ORR_SR(ARM_LR, ARM_LR, rd, SRTYPE_ASL, ARM_IP), ctx);
|
||||
emit(ARM_ORR_SR(ARM_IP, ARM_LR, rd, SRTYPE_LSR, tmp2[0]), ctx);
|
||||
@ -656,8 +703,6 @@ static inline void emit_a32_arsh_r64(const u8 dst[], const u8 src[], bool dstk,
|
||||
/* Do the ARSH operation */
|
||||
emit(ARM_RSB_I(ARM_IP, rt, 32), ctx);
|
||||
emit(ARM_SUBS_I(tmp2[0], rt, 32), ctx);
|
||||
/* As we are using ARM_LR */
|
||||
ctx->seen |= SEEN_CALL;
|
||||
emit(ARM_MOV_SR(ARM_LR, rd, SRTYPE_LSR, rt), ctx);
|
||||
emit(ARM_ORR_SR(ARM_LR, ARM_LR, rm, SRTYPE_ASL, ARM_IP), ctx);
|
||||
_emit(ARM_COND_MI, ARM_B(0), ctx);
|
||||
@ -692,8 +737,6 @@ static inline void emit_a32_lsr_r64(const u8 dst[], const u8 src[], bool dstk,
|
||||
/* Do LSH operation */
|
||||
emit(ARM_RSB_I(ARM_IP, rt, 32), ctx);
|
||||
emit(ARM_SUBS_I(tmp2[0], rt, 32), ctx);
|
||||
/* As we are using ARM_LR */
|
||||
ctx->seen |= SEEN_CALL;
|
||||
emit(ARM_MOV_SR(ARM_LR, rd, SRTYPE_LSR, rt), ctx);
|
||||
emit(ARM_ORR_SR(ARM_LR, ARM_LR, rm, SRTYPE_ASL, ARM_IP), ctx);
|
||||
emit(ARM_ORR_SR(ARM_LR, ARM_LR, rm, SRTYPE_LSR, tmp2[0]), ctx);
|
||||
@ -828,8 +871,6 @@ static inline void emit_a32_mul_r64(const u8 dst[], const u8 src[], bool dstk,
|
||||
/* Do Multiplication */
|
||||
emit(ARM_MUL(ARM_IP, rd, rn), ctx);
|
||||
emit(ARM_MUL(ARM_LR, rm, rt), ctx);
|
||||
/* As we are using ARM_LR */
|
||||
ctx->seen |= SEEN_CALL;
|
||||
emit(ARM_ADD_R(ARM_LR, ARM_IP, ARM_LR), ctx);
|
||||
|
||||
emit(ARM_UMULL(ARM_IP, rm, rd, rt), ctx);
|
||||
@ -872,33 +913,53 @@ static inline void emit_str_r(const u8 dst, const u8 src, bool dstk,
|
||||
}
|
||||
|
||||
/* dst = *(size*)(src + off) */
|
||||
static inline void emit_ldx_r(const u8 dst, const u8 src, bool dstk,
|
||||
const s32 off, struct jit_ctx *ctx, const u8 sz){
|
||||
static inline void emit_ldx_r(const u8 dst[], const u8 src, bool dstk,
|
||||
s32 off, struct jit_ctx *ctx, const u8 sz){
|
||||
const u8 *tmp = bpf2a32[TMP_REG_1];
|
||||
u8 rd = dstk ? tmp[1] : dst;
|
||||
const u8 *rd = dstk ? tmp : dst;
|
||||
u8 rm = src;
|
||||
s32 off_max;
|
||||
|
||||
if (off) {
|
||||
if (sz == BPF_H)
|
||||
off_max = 0xff;
|
||||
else
|
||||
off_max = 0xfff;
|
||||
|
||||
if (off < 0 || off > off_max) {
|
||||
emit_a32_mov_i(tmp[0], off, false, ctx);
|
||||
emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
|
||||
rm = tmp[0];
|
||||
off = 0;
|
||||
} else if (rd[1] == rm) {
|
||||
emit(ARM_MOV_R(tmp[0], rm), ctx);
|
||||
rm = tmp[0];
|
||||
}
|
||||
switch (sz) {
|
||||
case BPF_W:
|
||||
/* Load a Word */
|
||||
emit(ARM_LDR_I(rd, rm, 0), ctx);
|
||||
case BPF_B:
|
||||
/* Load a Byte */
|
||||
emit(ARM_LDRB_I(rd[1], rm, off), ctx);
|
||||
emit_a32_mov_i(dst[0], 0, dstk, ctx);
|
||||
break;
|
||||
case BPF_H:
|
||||
/* Load a HalfWord */
|
||||
emit(ARM_LDRH_I(rd, rm, 0), ctx);
|
||||
emit(ARM_LDRH_I(rd[1], rm, off), ctx);
|
||||
emit_a32_mov_i(dst[0], 0, dstk, ctx);
|
||||
break;
|
||||
case BPF_B:
|
||||
/* Load a Byte */
|
||||
emit(ARM_LDRB_I(rd, rm, 0), ctx);
|
||||
case BPF_W:
|
||||
/* Load a Word */
|
||||
emit(ARM_LDR_I(rd[1], rm, off), ctx);
|
||||
emit_a32_mov_i(dst[0], 0, dstk, ctx);
|
||||
break;
|
||||
case BPF_DW:
|
||||
/* Load a Double Word */
|
||||
emit(ARM_LDR_I(rd[1], rm, off), ctx);
|
||||
emit(ARM_LDR_I(rd[0], rm, off + 4), ctx);
|
||||
break;
|
||||
}
|
||||
if (dstk)
|
||||
emit(ARM_STR_I(rd, ARM_SP, STACK_VAR(dst)), ctx);
|
||||
emit(ARM_STR_I(rd[1], ARM_SP, STACK_VAR(dst[1])), ctx);
|
||||
if (dstk && sz == BPF_DW)
|
||||
emit(ARM_STR_I(rd[0], ARM_SP, STACK_VAR(dst[0])), ctx);
|
||||
}
|
||||
|
||||
/* Arithmatic Operation */
|
||||
@ -906,7 +967,6 @@ static inline void emit_ar_r(const u8 rd, const u8 rt, const u8 rm,
|
||||
const u8 rn, struct jit_ctx *ctx, u8 op) {
|
||||
switch (op) {
|
||||
case BPF_JSET:
|
||||
ctx->seen |= SEEN_CALL;
|
||||
emit(ARM_AND_R(ARM_IP, rt, rn), ctx);
|
||||
emit(ARM_AND_R(ARM_LR, rd, rm), ctx);
|
||||
emit(ARM_ORRS_R(ARM_IP, ARM_LR, ARM_IP), ctx);
|
||||
@ -945,7 +1005,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
const u8 *tcc = bpf2a32[TCALL_CNT];
|
||||
const int idx0 = ctx->idx;
|
||||
#define cur_offset (ctx->idx - idx0)
|
||||
#define jmp_offset (out_offset - (cur_offset))
|
||||
#define jmp_offset (out_offset - (cur_offset) - 2)
|
||||
u32 off, lo, hi;
|
||||
|
||||
/* if (index >= array->map.max_entries)
|
||||
@ -956,7 +1016,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
emit_a32_mov_i(tmp[1], off, false, ctx);
|
||||
emit(ARM_LDR_I(tmp2[1], ARM_SP, STACK_VAR(r2[1])), ctx);
|
||||
emit(ARM_LDR_R(tmp[1], tmp2[1], tmp[1]), ctx);
|
||||
/* index (64 bit) */
|
||||
/* index is 32-bit for arrays */
|
||||
emit(ARM_LDR_I(tmp2[1], ARM_SP, STACK_VAR(r3[1])), ctx);
|
||||
/* index >= array->map.max_entries */
|
||||
emit(ARM_CMP_R(tmp2[1], tmp[1]), ctx);
|
||||
@ -997,7 +1057,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
emit_a32_mov_i(tmp2[1], off, false, ctx);
|
||||
emit(ARM_LDR_R(tmp[1], tmp[1], tmp2[1]), ctx);
|
||||
emit(ARM_ADD_I(tmp[1], tmp[1], ctx->prologue_bytes), ctx);
|
||||
emit(ARM_BX(tmp[1]), ctx);
|
||||
emit_bx_r(tmp[1], ctx);
|
||||
|
||||
/* out: */
|
||||
if (out_offset == -1)
|
||||
@ -1070,54 +1130,22 @@ static void build_prologue(struct jit_ctx *ctx)
|
||||
const u8 r2 = bpf2a32[BPF_REG_1][1];
|
||||
const u8 r3 = bpf2a32[BPF_REG_1][0];
|
||||
const u8 r4 = bpf2a32[BPF_REG_6][1];
|
||||
const u8 r5 = bpf2a32[BPF_REG_6][0];
|
||||
const u8 r6 = bpf2a32[TMP_REG_1][1];
|
||||
const u8 r7 = bpf2a32[TMP_REG_1][0];
|
||||
const u8 r8 = bpf2a32[TMP_REG_2][1];
|
||||
const u8 r10 = bpf2a32[TMP_REG_2][0];
|
||||
const u8 fplo = bpf2a32[BPF_REG_FP][1];
|
||||
const u8 fphi = bpf2a32[BPF_REG_FP][0];
|
||||
const u8 sp = ARM_SP;
|
||||
const u8 *tcc = bpf2a32[TCALL_CNT];
|
||||
|
||||
u16 reg_set = 0;
|
||||
|
||||
/*
|
||||
* eBPF prog stack layout
|
||||
*
|
||||
* high
|
||||
* original ARM_SP => +-----+ eBPF prologue
|
||||
* |FP/LR|
|
||||
* current ARM_FP => +-----+
|
||||
* | ... | callee saved registers
|
||||
* eBPF fp register => +-----+ <= (BPF_FP)
|
||||
* | ... | eBPF JIT scratch space
|
||||
* | | eBPF prog stack
|
||||
* +-----+
|
||||
* |RSVD | JIT scratchpad
|
||||
* current A64_SP => +-----+ <= (BPF_FP - STACK_SIZE)
|
||||
* | |
|
||||
* | ... | Function call stack
|
||||
* | |
|
||||
* +-----+
|
||||
* low
|
||||
*/
|
||||
|
||||
/* Save callee saved registers. */
|
||||
reg_set |= (1<<r4) | (1<<r5) | (1<<r6) | (1<<r7) | (1<<r8) | (1<<r10);
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
reg_set |= (1<<ARM_FP) | (1<<ARM_IP) | (1<<ARM_LR) | (1<<ARM_PC);
|
||||
emit(ARM_MOV_R(ARM_IP, sp), ctx);
|
||||
u16 reg_set = CALLEE_PUSH_MASK | 1 << ARM_IP | 1 << ARM_PC;
|
||||
emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx);
|
||||
emit(ARM_PUSH(reg_set), ctx);
|
||||
emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx);
|
||||
#else
|
||||
/* Check if call instruction exists in BPF body */
|
||||
if (ctx->seen & SEEN_CALL)
|
||||
reg_set |= (1<<ARM_LR);
|
||||
emit(ARM_PUSH(reg_set), ctx);
|
||||
emit(ARM_PUSH(CALLEE_PUSH_MASK), ctx);
|
||||
emit(ARM_MOV_R(ARM_FP, ARM_SP), ctx);
|
||||
#endif
|
||||
/* Save frame pointer for later */
|
||||
emit(ARM_SUB_I(ARM_IP, sp, SCRATCH_SIZE), ctx);
|
||||
emit(ARM_SUB_I(ARM_IP, ARM_SP, SCRATCH_SIZE), ctx);
|
||||
|
||||
ctx->stack_size = imm8m(STACK_SIZE);
|
||||
|
||||
@ -1140,33 +1168,19 @@ static void build_prologue(struct jit_ctx *ctx)
|
||||
/* end of prologue */
|
||||
}
|
||||
|
||||
/* restore callee saved registers. */
|
||||
static void build_epilogue(struct jit_ctx *ctx)
|
||||
{
|
||||
const u8 r4 = bpf2a32[BPF_REG_6][1];
|
||||
const u8 r5 = bpf2a32[BPF_REG_6][0];
|
||||
const u8 r6 = bpf2a32[TMP_REG_1][1];
|
||||
const u8 r7 = bpf2a32[TMP_REG_1][0];
|
||||
const u8 r8 = bpf2a32[TMP_REG_2][1];
|
||||
const u8 r10 = bpf2a32[TMP_REG_2][0];
|
||||
u16 reg_set = 0;
|
||||
|
||||
/* unwind function call stack */
|
||||
emit(ARM_ADD_I(ARM_SP, ARM_SP, ctx->stack_size), ctx);
|
||||
|
||||
/* restore callee saved registers. */
|
||||
reg_set |= (1<<r4) | (1<<r5) | (1<<r6) | (1<<r7) | (1<<r8) | (1<<r10);
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
/* the first instruction of the prologue was: mov ip, sp */
|
||||
reg_set |= (1<<ARM_FP) | (1<<ARM_SP) | (1<<ARM_PC);
|
||||
/* When using frame pointers, some additional registers need to
|
||||
* be loaded. */
|
||||
u16 reg_set = CALLEE_POP_MASK | 1 << ARM_SP;
|
||||
emit(ARM_SUB_I(ARM_SP, ARM_FP, hweight16(reg_set) * 4), ctx);
|
||||
emit(ARM_LDM(ARM_SP, reg_set), ctx);
|
||||
#else
|
||||
if (ctx->seen & SEEN_CALL)
|
||||
reg_set |= (1<<ARM_PC);
|
||||
/* Restore callee saved registers. */
|
||||
emit(ARM_POP(reg_set), ctx);
|
||||
/* Return back to the callee function */
|
||||
if (!(ctx->seen & SEEN_CALL))
|
||||
emit(ARM_BX(ARM_LR), ctx);
|
||||
emit(ARM_MOV_R(ARM_SP, ARM_FP), ctx);
|
||||
emit(ARM_POP(CALLEE_POP_MASK), ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1394,8 +1408,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
emit_rev32(rt, rt, ctx);
|
||||
goto emit_bswap_uxt;
|
||||
case 64:
|
||||
/* Because of the usage of ARM_LR */
|
||||
ctx->seen |= SEEN_CALL;
|
||||
emit_rev32(ARM_LR, rt, ctx);
|
||||
emit_rev32(rt, rd, ctx);
|
||||
emit(ARM_MOV_R(rd, ARM_LR), ctx);
|
||||
@ -1448,22 +1460,7 @@ exit:
|
||||
rn = sstk ? tmp2[1] : src_lo;
|
||||
if (sstk)
|
||||
emit(ARM_LDR_I(rn, ARM_SP, STACK_VAR(src_lo)), ctx);
|
||||
switch (BPF_SIZE(code)) {
|
||||
case BPF_W:
|
||||
/* Load a Word */
|
||||
case BPF_H:
|
||||
/* Load a Half-Word */
|
||||
case BPF_B:
|
||||
/* Load a Byte */
|
||||
emit_ldx_r(dst_lo, rn, dstk, off, ctx, BPF_SIZE(code));
|
||||
emit_a32_mov_i(dst_hi, 0, dstk, ctx);
|
||||
break;
|
||||
case BPF_DW:
|
||||
/* Load a double word */
|
||||
emit_ldx_r(dst_lo, rn, dstk, off, ctx, BPF_W);
|
||||
emit_ldx_r(dst_hi, rn, dstk, off+4, ctx, BPF_W);
|
||||
break;
|
||||
}
|
||||
emit_ldx_r(dst, rn, dstk, off, ctx, BPF_SIZE(code));
|
||||
break;
|
||||
/* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + imm)) */
|
||||
case BPF_LD | BPF_ABS | BPF_W:
|
||||
|
@ -66,6 +66,7 @@
|
||||
<&cpu1>,
|
||||
<&cpu2>,
|
||||
<&cpu3>;
|
||||
interrupt-parent = <&intc>;
|
||||
};
|
||||
|
||||
psci {
|
||||
|
@ -63,8 +63,10 @@
|
||||
cpm_ethernet: ethernet@0 {
|
||||
compatible = "marvell,armada-7k-pp22";
|
||||
reg = <0x0 0x100000>, <0x129000 0xb000>;
|
||||
clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>, <&cpm_clk 1 5>;
|
||||
clock-names = "pp_clk", "gop_clk", "mg_clk";
|
||||
clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>,
|
||||
<&cpm_clk 1 5>, <&cpm_clk 1 18>;
|
||||
clock-names = "pp_clk", "gop_clk",
|
||||
"mg_clk","axi_clk";
|
||||
marvell,system-controller = <&cpm_syscon0>;
|
||||
status = "disabled";
|
||||
dma-coherent;
|
||||
@ -155,7 +157,8 @@
|
||||
#size-cells = <0>;
|
||||
compatible = "marvell,orion-mdio";
|
||||
reg = <0x12a200 0x10>;
|
||||
clocks = <&cpm_clk 1 9>, <&cpm_clk 1 5>;
|
||||
clocks = <&cpm_clk 1 9>, <&cpm_clk 1 5>,
|
||||
<&cpm_clk 1 6>, <&cpm_clk 1 18>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@ -338,8 +341,8 @@
|
||||
compatible = "marvell,armada-cp110-sdhci";
|
||||
reg = <0x780000 0x300>;
|
||||
interrupts = <ICU_GRP_NSR 27 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-names = "core";
|
||||
clocks = <&cpm_clk 1 4>;
|
||||
clock-names = "core","axi";
|
||||
clocks = <&cpm_clk 1 4>, <&cpm_clk 1 18>;
|
||||
dma-coherent;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -63,8 +63,10 @@
|
||||
cps_ethernet: ethernet@0 {
|
||||
compatible = "marvell,armada-7k-pp22";
|
||||
reg = <0x0 0x100000>, <0x129000 0xb000>;
|
||||
clocks = <&cps_clk 1 3>, <&cps_clk 1 9>, <&cps_clk 1 5>;
|
||||
clock-names = "pp_clk", "gop_clk", "mg_clk";
|
||||
clocks = <&cps_clk 1 3>, <&cps_clk 1 9>,
|
||||
<&cps_clk 1 5>, <&cps_clk 1 18>;
|
||||
clock-names = "pp_clk", "gop_clk",
|
||||
"mg_clk", "axi_clk";
|
||||
marvell,system-controller = <&cps_syscon0>;
|
||||
status = "disabled";
|
||||
dma-coherent;
|
||||
@ -155,7 +157,8 @@
|
||||
#size-cells = <0>;
|
||||
compatible = "marvell,orion-mdio";
|
||||
reg = <0x12a200 0x10>;
|
||||
clocks = <&cps_clk 1 9>, <&cps_clk 1 5>;
|
||||
clocks = <&cps_clk 1 9>, <&cps_clk 1 5>,
|
||||
<&cps_clk 1 6>, <&cps_clk 1 18>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -45,7 +45,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
|
||||
ret = kvm_psci_call(vcpu);
|
||||
if (ret < 0) {
|
||||
kvm_inject_undefined(vcpu);
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
|
||||
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
{
|
||||
kvm_inject_undefined(vcpu);
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,8 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
|
||||
/* Stack must be multiples of 16B */
|
||||
#define STACK_ALIGN(sz) (((sz) + 15) & ~15)
|
||||
|
||||
#define PROLOGUE_OFFSET 8
|
||||
/* Tail call offset to jump into */
|
||||
#define PROLOGUE_OFFSET 7
|
||||
|
||||
static int build_prologue(struct jit_ctx *ctx)
|
||||
{
|
||||
@ -200,19 +201,19 @@ static int build_prologue(struct jit_ctx *ctx)
|
||||
/* Initialize tail_call_cnt */
|
||||
emit(A64_MOVZ(1, tcc, 0, 0), ctx);
|
||||
|
||||
/* 4 byte extra for skb_copy_bits buffer */
|
||||
ctx->stack_size = prog->aux->stack_depth + 4;
|
||||
ctx->stack_size = STACK_ALIGN(ctx->stack_size);
|
||||
|
||||
/* Set up function call stack */
|
||||
emit(A64_SUB_I(1, A64_SP, A64_SP, ctx->stack_size), ctx);
|
||||
|
||||
cur_offset = ctx->idx - idx0;
|
||||
if (cur_offset != PROLOGUE_OFFSET) {
|
||||
pr_err_once("PROLOGUE_OFFSET = %d, expected %d!\n",
|
||||
cur_offset, PROLOGUE_OFFSET);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 4 byte extra for skb_copy_bits buffer */
|
||||
ctx->stack_size = prog->aux->stack_depth + 4;
|
||||
ctx->stack_size = STACK_ALIGN(ctx->stack_size);
|
||||
|
||||
/* Set up function call stack */
|
||||
emit(A64_SUB_I(1, A64_SP, A64_SP, ctx->stack_size), ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -260,11 +261,12 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
emit(A64_LDR64(prg, tmp, prg), ctx);
|
||||
emit(A64_CBZ(1, prg, jmp_offset), ctx);
|
||||
|
||||
/* goto *(prog->bpf_func + prologue_size); */
|
||||
/* goto *(prog->bpf_func + prologue_offset); */
|
||||
off = offsetof(struct bpf_prog, bpf_func);
|
||||
emit_a64_mov_i64(tmp, off, ctx);
|
||||
emit(A64_LDR64(tmp, prg, tmp), ctx);
|
||||
emit(A64_ADD_I(1, tmp, tmp, sizeof(u32) * PROLOGUE_OFFSET), ctx);
|
||||
emit(A64_ADD_I(1, A64_SP, A64_SP, ctx->stack_size), ctx);
|
||||
emit(A64_BR(tmp), ctx);
|
||||
|
||||
/* out: */
|
||||
|
@ -65,29 +65,30 @@ ia64_atomic_fetch_##op (int i, atomic_t *v) \
|
||||
ATOMIC_OPS(add, +)
|
||||
ATOMIC_OPS(sub, -)
|
||||
|
||||
#define atomic_add_return(i,v) \
|
||||
#ifdef __OPTIMIZE__
|
||||
#define __ia64_atomic_const(i) __builtin_constant_p(i) ? \
|
||||
((i) == 1 || (i) == 4 || (i) == 8 || (i) == 16 || \
|
||||
(i) == -1 || (i) == -4 || (i) == -8 || (i) == -16) : 0
|
||||
|
||||
#define atomic_add_return(i, v) \
|
||||
({ \
|
||||
int __ia64_aar_i = (i); \
|
||||
(__builtin_constant_p(i) \
|
||||
&& ( (__ia64_aar_i == 1) || (__ia64_aar_i == 4) \
|
||||
|| (__ia64_aar_i == 8) || (__ia64_aar_i == 16) \
|
||||
|| (__ia64_aar_i == -1) || (__ia64_aar_i == -4) \
|
||||
|| (__ia64_aar_i == -8) || (__ia64_aar_i == -16))) \
|
||||
? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter) \
|
||||
: ia64_atomic_add(__ia64_aar_i, v); \
|
||||
int __i = (i); \
|
||||
static const int __ia64_atomic_p = __ia64_atomic_const(i); \
|
||||
__ia64_atomic_p ? ia64_fetch_and_add(__i, &(v)->counter) : \
|
||||
ia64_atomic_add(__i, v); \
|
||||
})
|
||||
|
||||
#define atomic_sub_return(i,v) \
|
||||
#define atomic_sub_return(i, v) \
|
||||
({ \
|
||||
int __ia64_asr_i = (i); \
|
||||
(__builtin_constant_p(i) \
|
||||
&& ( (__ia64_asr_i == 1) || (__ia64_asr_i == 4) \
|
||||
|| (__ia64_asr_i == 8) || (__ia64_asr_i == 16) \
|
||||
|| (__ia64_asr_i == -1) || (__ia64_asr_i == -4) \
|
||||
|| (__ia64_asr_i == -8) || (__ia64_asr_i == -16))) \
|
||||
? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter) \
|
||||
: ia64_atomic_sub(__ia64_asr_i, v); \
|
||||
int __i = (i); \
|
||||
static const int __ia64_atomic_p = __ia64_atomic_const(i); \
|
||||
__ia64_atomic_p ? ia64_fetch_and_add(-__i, &(v)->counter) : \
|
||||
ia64_atomic_sub(__i, v); \
|
||||
})
|
||||
#else
|
||||
#define atomic_add_return(i, v) ia64_atomic_add(i, v)
|
||||
#define atomic_sub_return(i, v) ia64_atomic_sub(i, v)
|
||||
#endif
|
||||
|
||||
#define atomic_fetch_add(i,v) \
|
||||
({ \
|
||||
|
@ -88,7 +88,7 @@ void vtime_flush(struct task_struct *tsk)
|
||||
}
|
||||
|
||||
if (ti->softirq_time) {
|
||||
delta = cycle_to_nsec(ti->softirq_time));
|
||||
delta = cycle_to_nsec(ti->softirq_time);
|
||||
account_system_index_time(tsk, delta, CPUTIME_SOFTIRQ);
|
||||
}
|
||||
|
||||
|
@ -259,6 +259,7 @@ config BCM47XX
|
||||
select LEDS_GPIO_REGISTER
|
||||
select BCM47XX_NVRAM
|
||||
select BCM47XX_SPROM
|
||||
select BCM47XX_SSB if !BCM47XX_BCMA
|
||||
help
|
||||
Support for BCM47XX based boards
|
||||
|
||||
@ -389,6 +390,7 @@ config LANTIQ
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_MIPS16
|
||||
select SYS_SUPPORTS_MULTITHREADING
|
||||
select SYS_SUPPORTS_VPE_LOADER
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select GPIOLIB
|
||||
select SWAP_IO_SPACE
|
||||
@ -516,6 +518,7 @@ config MIPS_MALTA
|
||||
select SYS_SUPPORTS_MIPS16
|
||||
select SYS_SUPPORTS_MULTITHREADING
|
||||
select SYS_SUPPORTS_SMARTMIPS
|
||||
select SYS_SUPPORTS_VPE_LOADER
|
||||
select SYS_SUPPORTS_ZBOOT
|
||||
select SYS_SUPPORTS_RELOCATABLE
|
||||
select USE_OF
|
||||
@ -2281,9 +2284,16 @@ config MIPSR2_TO_R6_EMULATOR
|
||||
The only reason this is a build-time option is to save ~14K from the
|
||||
final kernel image.
|
||||
|
||||
config SYS_SUPPORTS_VPE_LOADER
|
||||
bool
|
||||
depends on SYS_SUPPORTS_MULTITHREADING
|
||||
help
|
||||
Indicates that the platform supports the VPE loader, and provides
|
||||
physical_memsize.
|
||||
|
||||
config MIPS_VPE_LOADER
|
||||
bool "VPE loader support."
|
||||
depends on SYS_SUPPORTS_MULTITHREADING && MODULES
|
||||
depends on SYS_SUPPORTS_VPE_LOADER && MODULES
|
||||
select CPU_MIPSR2_IRQ_VI
|
||||
select CPU_MIPSR2_IRQ_EI
|
||||
select MIPS_MT
|
||||
|
@ -124,30 +124,36 @@ config SCACHE_DEBUGFS
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
menuconfig MIPS_CPS_NS16550
|
||||
menuconfig MIPS_CPS_NS16550_BOOL
|
||||
bool "CPS SMP NS16550 UART output"
|
||||
depends on MIPS_CPS
|
||||
help
|
||||
Output debug information via an ns16550 compatible UART if exceptions
|
||||
occur early in the boot process of a secondary core.
|
||||
|
||||
if MIPS_CPS_NS16550
|
||||
if MIPS_CPS_NS16550_BOOL
|
||||
|
||||
config MIPS_CPS_NS16550
|
||||
def_bool MIPS_CPS_NS16550_BASE != 0
|
||||
|
||||
config MIPS_CPS_NS16550_BASE
|
||||
hex "UART Base Address"
|
||||
default 0x1b0003f8 if MIPS_MALTA
|
||||
default 0
|
||||
help
|
||||
The base address of the ns16550 compatible UART on which to output
|
||||
debug information from the early stages of core startup.
|
||||
|
||||
This is only used if non-zero.
|
||||
|
||||
config MIPS_CPS_NS16550_SHIFT
|
||||
int "UART Register Shift"
|
||||
default 0 if MIPS_MALTA
|
||||
default 0
|
||||
help
|
||||
The number of bits to shift ns16550 register indices by in order to
|
||||
form their addresses. That is, log base 2 of the span between
|
||||
adjacent ns16550 registers in the system.
|
||||
|
||||
endif # MIPS_CPS_NS16550
|
||||
endif # MIPS_CPS_NS16550_BOOL
|
||||
|
||||
endmenu
|
||||
|
@ -575,7 +575,7 @@ static int __init ar7_register_uarts(void)
|
||||
uart_port.type = PORT_AR7;
|
||||
uart_port.uartclk = clk_get_rate(bus_clk) / 2;
|
||||
uart_port.iotype = UPIO_MEM32;
|
||||
uart_port.flags = UPF_FIXED_TYPE;
|
||||
uart_port.flags = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF;
|
||||
uart_port.regshift = 2;
|
||||
|
||||
uart_port.line = 0;
|
||||
|
@ -73,6 +73,7 @@ const char *get_system_type(void)
|
||||
|
||||
void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
struct uart_port s;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
@ -85,6 +86,7 @@ void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
|
||||
s.uartclk = uartclk;
|
||||
|
||||
early_serial_setup(&s);
|
||||
#endif /* CONFIG_SERIAL_8250_CONSOLE */
|
||||
}
|
||||
|
||||
int __init ath25_add_wmac(int nr, u32 base, int irq)
|
||||
|
@ -235,6 +235,7 @@ LEAF(mips_cps_core_init)
|
||||
has_mt t0, 3f
|
||||
|
||||
.set push
|
||||
.set MIPS_ISA_LEVEL_RAW
|
||||
.set mt
|
||||
|
||||
/* Only allow 1 TC per VPE to execute... */
|
||||
@ -388,6 +389,7 @@ LEAF(mips_cps_boot_vpes)
|
||||
#elif defined(CONFIG_MIPS_MT)
|
||||
|
||||
.set push
|
||||
.set MIPS_ISA_LEVEL_RAW
|
||||
.set mt
|
||||
|
||||
/* If the core doesn't support MT then return */
|
||||
|
@ -292,7 +292,6 @@ void mips_cm_lock_other(unsigned int cluster, unsigned int core,
|
||||
*this_cpu_ptr(&cm_core_lock_flags));
|
||||
} else {
|
||||
WARN_ON(cluster != 0);
|
||||
WARN_ON(vp != 0);
|
||||
WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL);
|
||||
|
||||
/*
|
||||
|
@ -705,6 +705,18 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
|
||||
struct task_struct *t;
|
||||
int max_users;
|
||||
|
||||
/* If nothing to change, return right away, successfully. */
|
||||
if (value == mips_get_process_fp_mode(task))
|
||||
return 0;
|
||||
|
||||
/* Only accept a mode change if 64-bit FP enabled for o32. */
|
||||
if (!IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* And only for o32 tasks. */
|
||||
if (IS_ENABLED(CONFIG_64BIT) && !test_thread_flag(TIF_32BIT_REGS))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Check the value is valid */
|
||||
if (value & ~known_bits)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -419,25 +419,38 @@ static int gpr64_set(struct task_struct *target,
|
||||
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
static int fpr_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
/*
|
||||
* Copy the floating-point context to the supplied NT_PRFPREG buffer,
|
||||
* !CONFIG_CPU_HAS_MSA variant. FP context's general register slots
|
||||
* correspond 1:1 to buffer slots. Only general registers are copied.
|
||||
*/
|
||||
static int fpr_get_fpa(struct task_struct *target,
|
||||
unsigned int *pos, unsigned int *count,
|
||||
void **kbuf, void __user **ubuf)
|
||||
{
|
||||
unsigned i;
|
||||
int err;
|
||||
return user_regset_copyout(pos, count, kbuf, ubuf,
|
||||
&target->thread.fpu,
|
||||
0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the floating-point context to the supplied NT_PRFPREG buffer,
|
||||
* CONFIG_CPU_HAS_MSA variant. Only lower 64 bits of FP context's
|
||||
* general register slots are copied to buffer slots. Only general
|
||||
* registers are copied.
|
||||
*/
|
||||
static int fpr_get_msa(struct task_struct *target,
|
||||
unsigned int *pos, unsigned int *count,
|
||||
void **kbuf, void __user **ubuf)
|
||||
{
|
||||
unsigned int i;
|
||||
u64 fpr_val;
|
||||
int err;
|
||||
|
||||
/* XXX fcr31 */
|
||||
|
||||
if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
|
||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fpu,
|
||||
0, sizeof(elf_fpregset_t));
|
||||
|
||||
BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
|
||||
for (i = 0; i < NUM_FPU_REGS; i++) {
|
||||
fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
|
||||
err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
err = user_regset_copyout(pos, count, kbuf, ubuf,
|
||||
&fpr_val, i * sizeof(elf_fpreg_t),
|
||||
(i + 1) * sizeof(elf_fpreg_t));
|
||||
if (err)
|
||||
@ -447,27 +460,64 @@ static int fpr_get(struct task_struct *target,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fpr_set(struct task_struct *target,
|
||||
/*
|
||||
* Copy the floating-point context to the supplied NT_PRFPREG buffer.
|
||||
* Choose the appropriate helper for general registers, and then copy
|
||||
* the FCSR register separately.
|
||||
*/
|
||||
static int fpr_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
unsigned i;
|
||||
const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
|
||||
int err;
|
||||
|
||||
if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
|
||||
err = fpr_get_fpa(target, &pos, &count, &kbuf, &ubuf);
|
||||
else
|
||||
err = fpr_get_msa(target, &pos, &count, &kbuf, &ubuf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fpu.fcr31,
|
||||
fcr31_pos, fcr31_pos + sizeof(u32));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the supplied NT_PRFPREG buffer to the floating-point context,
|
||||
* !CONFIG_CPU_HAS_MSA variant. Buffer slots correspond 1:1 to FP
|
||||
* context's general register slots. Only general registers are copied.
|
||||
*/
|
||||
static int fpr_set_fpa(struct task_struct *target,
|
||||
unsigned int *pos, unsigned int *count,
|
||||
const void **kbuf, const void __user **ubuf)
|
||||
{
|
||||
return user_regset_copyin(pos, count, kbuf, ubuf,
|
||||
&target->thread.fpu,
|
||||
0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the supplied NT_PRFPREG buffer to the floating-point context,
|
||||
* CONFIG_CPU_HAS_MSA variant. Buffer slots are copied to lower 64
|
||||
* bits only of FP context's general register slots. Only general
|
||||
* registers are copied.
|
||||
*/
|
||||
static int fpr_set_msa(struct task_struct *target,
|
||||
unsigned int *pos, unsigned int *count,
|
||||
const void **kbuf, const void __user **ubuf)
|
||||
{
|
||||
unsigned int i;
|
||||
u64 fpr_val;
|
||||
|
||||
/* XXX fcr31 */
|
||||
|
||||
init_fp_ctx(target);
|
||||
|
||||
if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
|
||||
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fpu,
|
||||
0, sizeof(elf_fpregset_t));
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
|
||||
for (i = 0; i < NUM_FPU_REGS && count >= sizeof(elf_fpreg_t); i++) {
|
||||
err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
for (i = 0; i < NUM_FPU_REGS && *count > 0; i++) {
|
||||
err = user_regset_copyin(pos, count, kbuf, ubuf,
|
||||
&fpr_val, i * sizeof(elf_fpreg_t),
|
||||
(i + 1) * sizeof(elf_fpreg_t));
|
||||
if (err)
|
||||
@ -478,6 +528,53 @@ static int fpr_set(struct task_struct *target,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the supplied NT_PRFPREG buffer to the floating-point context.
|
||||
* Choose the appropriate helper for general registers, and then copy
|
||||
* the FCSR register separately.
|
||||
*
|
||||
* We optimize for the case where `count % sizeof(elf_fpreg_t) == 0',
|
||||
* which is supposed to have been guaranteed by the kernel before
|
||||
* calling us, e.g. in `ptrace_regset'. We enforce that requirement,
|
||||
* so that we can safely avoid preinitializing temporaries for
|
||||
* partial register writes.
|
||||
*/
|
||||
static int fpr_set(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
|
||||
u32 fcr31;
|
||||
int err;
|
||||
|
||||
BUG_ON(count % sizeof(elf_fpreg_t));
|
||||
|
||||
if (pos + count > sizeof(elf_fpregset_t))
|
||||
return -EIO;
|
||||
|
||||
init_fp_ctx(target);
|
||||
|
||||
if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
|
||||
err = fpr_set_fpa(target, &pos, &count, &kbuf, &ubuf);
|
||||
else
|
||||
err = fpr_set_msa(target, &pos, &count, &kbuf, &ubuf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (count > 0) {
|
||||
err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&fcr31,
|
||||
fcr31_pos, fcr31_pos + sizeof(u32));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ptrace_setfcr31(target, fcr31);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
enum mips_regset {
|
||||
REGSET_GPR,
|
||||
REGSET_FPR,
|
||||
|
@ -16,4 +16,5 @@ obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
|
||||
obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
|
||||
|
||||
# libgcc-style stuff needed in the kernel
|
||||
obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o
|
||||
obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o multi3.o \
|
||||
ucmpdi2.o
|
||||
|
@ -10,10 +10,18 @@ typedef int word_type __attribute__ ((mode (__word__)));
|
||||
struct DWstruct {
|
||||
int high, low;
|
||||
};
|
||||
|
||||
struct TWstruct {
|
||||
long long high, low;
|
||||
};
|
||||
#elif defined(__LITTLE_ENDIAN)
|
||||
struct DWstruct {
|
||||
int low, high;
|
||||
};
|
||||
|
||||
struct TWstruct {
|
||||
long long low, high;
|
||||
};
|
||||
#else
|
||||
#error I feel sick.
|
||||
#endif
|
||||
@ -23,4 +31,13 @@ typedef union {
|
||||
long long ll;
|
||||
} DWunion;
|
||||
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6)
|
||||
typedef int ti_type __attribute__((mode(TI)));
|
||||
|
||||
typedef union {
|
||||
struct TWstruct s;
|
||||
ti_type ti;
|
||||
} TWunion;
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_LIBGCC_H */
|
||||
|
54
arch/mips/lib/multi3.c
Normal file
54
arch/mips/lib/multi3.c
Normal file
@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "libgcc.h"
|
||||
|
||||
/*
|
||||
* GCC 7 suboptimally generates __multi3 calls for mips64r6, so for that
|
||||
* specific case only we'll implement it here.
|
||||
*
|
||||
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
|
||||
*/
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ == 7)
|
||||
|
||||
/* multiply 64-bit values, low 64-bits returned */
|
||||
static inline long long notrace dmulu(long long a, long long b)
|
||||
{
|
||||
long long res;
|
||||
|
||||
asm ("dmulu %0,%1,%2" : "=r" (res) : "r" (a), "r" (b));
|
||||
return res;
|
||||
}
|
||||
|
||||
/* multiply 64-bit unsigned values, high 64-bits of 128-bit result returned */
|
||||
static inline long long notrace dmuhu(long long a, long long b)
|
||||
{
|
||||
long long res;
|
||||
|
||||
asm ("dmuhu %0,%1,%2" : "=r" (res) : "r" (a), "r" (b));
|
||||
return res;
|
||||
}
|
||||
|
||||
/* multiply 128-bit values, low 128-bits returned */
|
||||
ti_type notrace __multi3(ti_type a, ti_type b)
|
||||
{
|
||||
TWunion res, aa, bb;
|
||||
|
||||
aa.ti = a;
|
||||
bb.ti = b;
|
||||
|
||||
/*
|
||||
* a * b = (a.lo * b.lo)
|
||||
* + 2^64 * (a.hi * b.lo + a.lo * b.hi)
|
||||
* [+ 2^128 * (a.hi * b.hi)]
|
||||
*/
|
||||
res.s.low = dmulu(aa.s.low, bb.s.low);
|
||||
res.s.high = dmuhu(aa.s.low, bb.s.low);
|
||||
res.s.high += dmulu(aa.s.high, bb.s.low);
|
||||
res.s.high += dmulu(aa.s.low, bb.s.high);
|
||||
|
||||
return res.ti;
|
||||
}
|
||||
EXPORT_SYMBOL(__multi3);
|
||||
|
||||
#endif /* 64BIT && CPU_MIPSR6 && GCC7 */
|
@ -40,7 +40,7 @@
|
||||
|
||||
#include "uasm.c"
|
||||
|
||||
static const struct insn const insn_table_MM[insn_invalid] = {
|
||||
static const struct insn insn_table_MM[insn_invalid] = {
|
||||
[insn_addu] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_addu32_op), RT | RS | RD},
|
||||
[insn_addiu] = {M(mm_addiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM},
|
||||
[insn_and] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_and_op), RT | RS | RD},
|
||||
|
@ -109,9 +109,9 @@ static int rt_timer_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
rt->irq = platform_get_irq(pdev, 0);
|
||||
if (!rt->irq) {
|
||||
if (rt->irq < 0) {
|
||||
dev_err(&pdev->dev, "failed to load irq\n");
|
||||
return -ENOENT;
|
||||
return rt->irq;
|
||||
}
|
||||
|
||||
rt->membase = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
@ -2,4 +2,6 @@
|
||||
# Makefile for the RB532 board specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y += irq.o time.o setup.o serial.o prom.o gpio.o devices.o
|
||||
obj-$(CONFIG_SERIAL_8250_CONSOLE) += serial.o
|
||||
|
||||
obj-y += irq.o time.o setup.o prom.o gpio.o devices.o
|
||||
|
@ -310,6 +310,8 @@ static int __init plat_setup_devices(void)
|
||||
return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
|
||||
static int __init setup_kmac(char *s)
|
||||
{
|
||||
printk(KERN_INFO "korina mac = %s\n", s);
|
||||
@ -322,4 +324,6 @@ static int __init setup_kmac(char *s)
|
||||
|
||||
__setup("kmac=", setup_kmac);
|
||||
|
||||
#endif /* CONFIG_NET */
|
||||
|
||||
arch_initcall(plat_setup_devices);
|
||||
|
@ -12,6 +12,7 @@
|
||||
for the semaphore. */
|
||||
|
||||
#define __PA_LDCW_ALIGNMENT 16
|
||||
#define __PA_LDCW_ALIGN_ORDER 4
|
||||
#define __ldcw_align(a) ({ \
|
||||
unsigned long __ret = (unsigned long) &(a)->lock[0]; \
|
||||
__ret = (__ret + __PA_LDCW_ALIGNMENT - 1) \
|
||||
@ -29,6 +30,7 @@
|
||||
ldcd). */
|
||||
|
||||
#define __PA_LDCW_ALIGNMENT 4
|
||||
#define __PA_LDCW_ALIGN_ORDER 2
|
||||
#define __ldcw_align(a) (&(a)->slock)
|
||||
#define __LDCW "ldcw,co"
|
||||
|
||||
|
@ -870,7 +870,7 @@ static void print_parisc_device(struct parisc_device *dev)
|
||||
static int count;
|
||||
|
||||
print_pa_hwpath(dev, hw_path);
|
||||
printk(KERN_INFO "%d. %s at 0x%p [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
|
||||
printk(KERN_INFO "%d. %s at 0x%px [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
|
||||
++count, dev->name, (void*) dev->hpa.start, hw_path, dev->id.hw_type,
|
||||
dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/signal.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/ldcw.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
#include <linux/linkage.h>
|
||||
@ -46,6 +47,14 @@
|
||||
#endif
|
||||
|
||||
.import pa_tlb_lock,data
|
||||
.macro load_pa_tlb_lock reg
|
||||
#if __PA_LDCW_ALIGNMENT > 4
|
||||
load32 PA(pa_tlb_lock) + __PA_LDCW_ALIGNMENT-1, \reg
|
||||
depi 0,31,__PA_LDCW_ALIGN_ORDER, \reg
|
||||
#else
|
||||
load32 PA(pa_tlb_lock), \reg
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* space_to_prot macro creates a prot id from a space id */
|
||||
|
||||
@ -457,7 +466,7 @@
|
||||
.macro tlb_lock spc,ptp,pte,tmp,tmp1,fault
|
||||
#ifdef CONFIG_SMP
|
||||
cmpib,COND(=),n 0,\spc,2f
|
||||
load32 PA(pa_tlb_lock),\tmp
|
||||
load_pa_tlb_lock \tmp
|
||||
1: LDCW 0(\tmp),\tmp1
|
||||
cmpib,COND(=) 0,\tmp1,1b
|
||||
nop
|
||||
@ -480,7 +489,7 @@
|
||||
/* Release pa_tlb_lock lock. */
|
||||
.macro tlb_unlock1 spc,tmp
|
||||
#ifdef CONFIG_SMP
|
||||
load32 PA(pa_tlb_lock),\tmp
|
||||
load_pa_tlb_lock \tmp
|
||||
tlb_unlock0 \spc,\tmp
|
||||
#endif
|
||||
.endm
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <asm/assembly.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/ldcw.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.text
|
||||
@ -333,8 +334,12 @@ ENDPROC_CFI(flush_data_cache_local)
|
||||
|
||||
.macro tlb_lock la,flags,tmp
|
||||
#ifdef CONFIG_SMP
|
||||
ldil L%pa_tlb_lock,%r1
|
||||
ldo R%pa_tlb_lock(%r1),\la
|
||||
#if __PA_LDCW_ALIGNMENT > 4
|
||||
load32 pa_tlb_lock + __PA_LDCW_ALIGNMENT-1, \la
|
||||
depi 0,31,__PA_LDCW_ALIGN_ORDER, \la
|
||||
#else
|
||||
load32 pa_tlb_lock, \la
|
||||
#endif
|
||||
rsm PSW_SM_I,\flags
|
||||
1: LDCW 0(\la),\tmp
|
||||
cmpib,<>,n 0,\tmp,3f
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/ptrace.h>
|
||||
@ -183,6 +184,44 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Idle thread support
|
||||
*
|
||||
* Detect when running on QEMU with SeaBIOS PDC Firmware and let
|
||||
* QEMU idle the host too.
|
||||
*/
|
||||
|
||||
int running_on_qemu __read_mostly;
|
||||
|
||||
void __cpuidle arch_cpu_idle_dead(void)
|
||||
{
|
||||
/* nop on real hardware, qemu will offline CPU. */
|
||||
asm volatile("or %%r31,%%r31,%%r31\n":::);
|
||||
}
|
||||
|
||||
void __cpuidle arch_cpu_idle(void)
|
||||
{
|
||||
local_irq_enable();
|
||||
|
||||
/* nop on real hardware, qemu will idle sleep. */
|
||||
asm volatile("or %%r10,%%r10,%%r10\n":::);
|
||||
}
|
||||
|
||||
static int __init parisc_idle_init(void)
|
||||
{
|
||||
const char *marker;
|
||||
|
||||
/* check QEMU/SeaBIOS marker in PAGE0 */
|
||||
marker = (char *) &PAGE0->pad0;
|
||||
running_on_qemu = (memcmp(marker, "SeaBIOS", 8) == 0);
|
||||
|
||||
if (!running_on_qemu)
|
||||
cpu_idle_poll_ctrl(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(parisc_idle_init);
|
||||
|
||||
/*
|
||||
* Copy architecture-specific thread state
|
||||
*/
|
||||
|
@ -631,11 +631,11 @@ void __init mem_init(void)
|
||||
mem_init_print_info(NULL);
|
||||
#ifdef CONFIG_DEBUG_KERNEL /* double-sanity-check paranoia */
|
||||
printk("virtual kernel memory layout:\n"
|
||||
" vmalloc : 0x%p - 0x%p (%4ld MB)\n"
|
||||
" memory : 0x%p - 0x%p (%4ld MB)\n"
|
||||
" .init : 0x%p - 0x%p (%4ld kB)\n"
|
||||
" .data : 0x%p - 0x%p (%4ld kB)\n"
|
||||
" .text : 0x%p - 0x%p (%4ld kB)\n",
|
||||
" vmalloc : 0x%px - 0x%px (%4ld MB)\n"
|
||||
" memory : 0x%px - 0x%px (%4ld MB)\n"
|
||||
" .init : 0x%px - 0x%px (%4ld kB)\n"
|
||||
" .data : 0x%px - 0x%px (%4ld kB)\n"
|
||||
" .text : 0x%px - 0x%px (%4ld kB)\n",
|
||||
|
||||
(void*)VMALLOC_START, (void*)VMALLOC_END,
|
||||
(VMALLOC_END - VMALLOC_START) >> 20,
|
||||
|
@ -166,6 +166,7 @@ config PPC
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
|
||||
select GENERIC_CMOS_UPDATE
|
||||
select GENERIC_CPU_AUTOPROBE
|
||||
select GENERIC_CPU_VULNERABILITIES if PPC_BOOK3S_64
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_IRQ_SHOW_LEVEL
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
|
@ -209,5 +209,11 @@ exc_##label##_book3e:
|
||||
ori r3,r3,vector_offset@l; \
|
||||
mtspr SPRN_IVOR##vector_number,r3;
|
||||
|
||||
#define RFI_TO_KERNEL \
|
||||
rfi
|
||||
|
||||
#define RFI_TO_USER \
|
||||
rfi
|
||||
|
||||
#endif /* _ASM_POWERPC_EXCEPTION_64E_H */
|
||||
|
||||
|
@ -74,6 +74,59 @@
|
||||
*/
|
||||
#define EX_R3 EX_DAR
|
||||
|
||||
/*
|
||||
* Macros for annotating the expected destination of (h)rfid
|
||||
*
|
||||
* The nop instructions allow us to insert one or more instructions to flush the
|
||||
* L1-D cache when returning to userspace or a guest.
|
||||
*/
|
||||
#define RFI_FLUSH_SLOT \
|
||||
RFI_FLUSH_FIXUP_SECTION; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop
|
||||
|
||||
#define RFI_TO_KERNEL \
|
||||
rfid
|
||||
|
||||
#define RFI_TO_USER \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define RFI_TO_USER_OR_KERNEL \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define RFI_TO_GUEST \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_KERNEL \
|
||||
hrfid
|
||||
|
||||
#define HRFI_TO_USER \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_USER_OR_KERNEL \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_GUEST \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_UNKNOWN \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
#define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \
|
||||
mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \
|
||||
@ -218,7 +271,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
|
||||
mtspr SPRN_##h##SRR0,r12; \
|
||||
mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \
|
||||
mtspr SPRN_##h##SRR1,r10; \
|
||||
h##rfid; \
|
||||
h##RFI_TO_KERNEL; \
|
||||
b . /* prevent speculative execution */
|
||||
#define EXCEPTION_PROLOG_PSERIES_1(label, h) \
|
||||
__EXCEPTION_PROLOG_PSERIES_1(label, h)
|
||||
@ -232,7 +285,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
|
||||
mtspr SPRN_##h##SRR0,r12; \
|
||||
mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \
|
||||
mtspr SPRN_##h##SRR1,r10; \
|
||||
h##rfid; \
|
||||
h##RFI_TO_KERNEL; \
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
#define EXCEPTION_PROLOG_PSERIES_1_NORI(label, h) \
|
||||
|
@ -187,7 +187,20 @@ label##3: \
|
||||
FTR_ENTRY_OFFSET label##1b-label##3b; \
|
||||
.popsection;
|
||||
|
||||
#define RFI_FLUSH_FIXUP_SECTION \
|
||||
951: \
|
||||
.pushsection __rfi_flush_fixup,"a"; \
|
||||
.align 2; \
|
||||
952: \
|
||||
FTR_ENTRY_OFFSET 951b-952b; \
|
||||
.popsection;
|
||||
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <linux/types.h>
|
||||
|
||||
extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
|
||||
|
||||
void apply_feature_fixups(void);
|
||||
void setup_feature_keys(void);
|
||||
#endif
|
||||
|
@ -241,6 +241,7 @@
|
||||
#define H_GET_HCA_INFO 0x1B8
|
||||
#define H_GET_PERF_COUNT 0x1BC
|
||||
#define H_MANAGE_TRACE 0x1C0
|
||||
#define H_GET_CPU_CHARACTERISTICS 0x1C8
|
||||
#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
|
||||
#define H_QUERY_INT_STATE 0x1E4
|
||||
#define H_POLL_PENDING 0x1D8
|
||||
@ -330,6 +331,17 @@
|
||||
#define H_SIGNAL_SYS_RESET_ALL_OTHERS -2
|
||||
/* >= 0 values are CPU number */
|
||||
|
||||
/* H_GET_CPU_CHARACTERISTICS return values */
|
||||
#define H_CPU_CHAR_SPEC_BAR_ORI31 (1ull << 63) // IBM bit 0
|
||||
#define H_CPU_CHAR_BCCTRL_SERIALISED (1ull << 62) // IBM bit 1
|
||||
#define H_CPU_CHAR_L1D_FLUSH_ORI30 (1ull << 61) // IBM bit 2
|
||||
#define H_CPU_CHAR_L1D_FLUSH_TRIG2 (1ull << 60) // IBM bit 3
|
||||
#define H_CPU_CHAR_L1D_THREAD_PRIV (1ull << 59) // IBM bit 4
|
||||
|
||||
#define H_CPU_BEHAV_FAVOUR_SECURITY (1ull << 63) // IBM bit 0
|
||||
#define H_CPU_BEHAV_L1D_FLUSH_PR (1ull << 62) // IBM bit 1
|
||||
#define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ull << 61) // IBM bit 2
|
||||
|
||||
/* Flag values used in H_REGISTER_PROC_TBL hcall */
|
||||
#define PROC_TABLE_OP_MASK 0x18
|
||||
#define PROC_TABLE_DEREG 0x10
|
||||
@ -341,6 +353,7 @@
|
||||
#define PROC_TABLE_GTSE 0x01
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments
|
||||
@ -436,6 +449,11 @@ static inline unsigned int get_longbusy_msecs(int longbusy_rc)
|
||||
}
|
||||
}
|
||||
|
||||
struct h_cpu_char_result {
|
||||
u64 character;
|
||||
u64 behaviour;
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_HVCALL_H */
|
||||
|
@ -232,6 +232,16 @@ struct paca_struct {
|
||||
struct sibling_subcore_state *sibling_subcore_state;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
/*
|
||||
* rfi fallback flush must be in its own cacheline to prevent
|
||||
* other paca data leaking into the L1d
|
||||
*/
|
||||
u64 exrfi[EX_SIZE] __aligned(0x80);
|
||||
void *rfi_flush_fallback_area;
|
||||
u64 l1d_flush_congruence;
|
||||
u64 l1d_flush_sets;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern void copy_mm_to_paca(struct mm_struct *mm);
|
||||
|
@ -326,4 +326,18 @@ static inline long plapr_signal_sys_reset(long cpu)
|
||||
return plpar_hcall_norets(H_SIGNAL_SYS_RESET, cpu);
|
||||
}
|
||||
|
||||
static inline long plpar_get_cpu_characteristics(struct h_cpu_char_result *p)
|
||||
{
|
||||
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
|
||||
long rc;
|
||||
|
||||
rc = plpar_hcall(H_GET_CPU_CHARACTERISTICS, retbuf);
|
||||
if (rc == H_SUCCESS) {
|
||||
p->character = retbuf[0];
|
||||
p->behaviour = retbuf[1];
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* _ASM_POWERPC_PLPAR_WRAPPERS_H */
|
||||
|
@ -39,6 +39,19 @@ static inline void pseries_big_endian_exceptions(void) {}
|
||||
static inline void pseries_little_endian_exceptions(void) {}
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
|
||||
void rfi_flush_enable(bool enable);
|
||||
|
||||
/* These are bit flags */
|
||||
enum l1d_flush_type {
|
||||
L1D_FLUSH_NONE = 0x1,
|
||||
L1D_FLUSH_FALLBACK = 0x2,
|
||||
L1D_FLUSH_ORI = 0x4,
|
||||
L1D_FLUSH_MTTRIG = 0x8,
|
||||
};
|
||||
|
||||
void __init setup_rfi_flush(enum l1d_flush_type, bool enable);
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_SETUP_H */
|
||||
|
@ -443,6 +443,31 @@ struct kvm_ppc_rmmu_info {
|
||||
__u32 ap_encodings[8];
|
||||
};
|
||||
|
||||
/* For KVM_PPC_GET_CPU_CHAR */
|
||||
struct kvm_ppc_cpu_char {
|
||||
__u64 character; /* characteristics of the CPU */
|
||||
__u64 behaviour; /* recommended software behaviour */
|
||||
__u64 character_mask; /* valid bits in character */
|
||||
__u64 behaviour_mask; /* valid bits in behaviour */
|
||||
};
|
||||
|
||||
/*
|
||||
* Values for character and character_mask.
|
||||
* These are identical to the values used by H_GET_CPU_CHARACTERISTICS.
|
||||
*/
|
||||
#define KVM_PPC_CPU_CHAR_SPEC_BAR_ORI31 (1ULL << 63)
|
||||
#define KVM_PPC_CPU_CHAR_BCCTRL_SERIALISED (1ULL << 62)
|
||||
#define KVM_PPC_CPU_CHAR_L1D_FLUSH_ORI30 (1ULL << 61)
|
||||
#define KVM_PPC_CPU_CHAR_L1D_FLUSH_TRIG2 (1ULL << 60)
|
||||
#define KVM_PPC_CPU_CHAR_L1D_THREAD_PRIV (1ULL << 59)
|
||||
#define KVM_PPC_CPU_CHAR_BR_HINT_HONOURED (1ULL << 58)
|
||||
#define KVM_PPC_CPU_CHAR_MTTRIG_THR_RECONF (1ULL << 57)
|
||||
#define KVM_PPC_CPU_CHAR_COUNT_CACHE_DIS (1ULL << 56)
|
||||
|
||||
#define KVM_PPC_CPU_BEHAV_FAVOUR_SECURITY (1ULL << 63)
|
||||
#define KVM_PPC_CPU_BEHAV_L1D_FLUSH_PR (1ULL << 62)
|
||||
#define KVM_PPC_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ULL << 61)
|
||||
|
||||
/* Per-vcpu XICS interrupt controller state */
|
||||
#define KVM_REG_PPC_ICP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
|
||||
|
||||
|
@ -237,6 +237,11 @@ int main(void)
|
||||
OFFSET(PACA_NMI_EMERG_SP, paca_struct, nmi_emergency_sp);
|
||||
OFFSET(PACA_IN_MCE, paca_struct, in_mce);
|
||||
OFFSET(PACA_IN_NMI, paca_struct, in_nmi);
|
||||
OFFSET(PACA_RFI_FLUSH_FALLBACK_AREA, paca_struct, rfi_flush_fallback_area);
|
||||
OFFSET(PACA_EXRFI, paca_struct, exrfi);
|
||||
OFFSET(PACA_L1D_FLUSH_CONGRUENCE, paca_struct, l1d_flush_congruence);
|
||||
OFFSET(PACA_L1D_FLUSH_SETS, paca_struct, l1d_flush_sets);
|
||||
|
||||
#endif
|
||||
OFFSET(PACAHWCPUID, paca_struct, hw_cpu_id);
|
||||
OFFSET(PACAKEXECSTATE, paca_struct, kexec_state);
|
||||
|
@ -37,6 +37,11 @@
|
||||
#include <asm/tm.h>
|
||||
#include <asm/ppc-opcode.h>
|
||||
#include <asm/export.h>
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
#include <asm/exception-64s.h>
|
||||
#else
|
||||
#include <asm/exception-64e.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* System calls.
|
||||
@ -262,13 +267,23 @@ BEGIN_FTR_SECTION
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
||||
|
||||
ld r13,GPR13(r1) /* only restore r13 if returning to usermode */
|
||||
ld r2,GPR2(r1)
|
||||
ld r1,GPR1(r1)
|
||||
mtlr r4
|
||||
mtcr r5
|
||||
mtspr SPRN_SRR0,r7
|
||||
mtspr SPRN_SRR1,r8
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
/* exit to kernel */
|
||||
1: ld r2,GPR2(r1)
|
||||
ld r1,GPR1(r1)
|
||||
mtlr r4
|
||||
mtcr r5
|
||||
mtspr SPRN_SRR0,r7
|
||||
mtspr SPRN_SRR1,r8
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
.Lsyscall_error:
|
||||
@ -397,8 +412,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
||||
mtmsrd r10, 1
|
||||
mtspr SPRN_SRR0, r11
|
||||
mtspr SPRN_SRR1, r12
|
||||
|
||||
rfid
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
#endif
|
||||
_ASM_NOKPROBE_SYMBOL(system_call_common);
|
||||
@ -878,7 +892,7 @@ BEGIN_FTR_SECTION
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
||||
ACCOUNT_CPU_USER_EXIT(r13, r2, r4)
|
||||
REST_GPR(13, r1)
|
||||
1:
|
||||
|
||||
mtspr SPRN_SRR1,r3
|
||||
|
||||
ld r2,_CCR(r1)
|
||||
@ -891,8 +905,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
||||
ld r3,GPR3(r1)
|
||||
ld r4,GPR4(r1)
|
||||
ld r1,GPR1(r1)
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
rfid
|
||||
1: mtspr SPRN_SRR1,r3
|
||||
|
||||
ld r2,_CCR(r1)
|
||||
mtcrf 0xFF,r2
|
||||
ld r2,_NIP(r1)
|
||||
mtspr SPRN_SRR0,r2
|
||||
|
||||
ld r0,GPR0(r1)
|
||||
ld r2,GPR2(r1)
|
||||
ld r3,GPR3(r1)
|
||||
ld r4,GPR4(r1)
|
||||
ld r1,GPR1(r1)
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
@ -1073,7 +1101,7 @@ __enter_rtas:
|
||||
|
||||
mtspr SPRN_SRR0,r5
|
||||
mtspr SPRN_SRR1,r6
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
rtas_return_loc:
|
||||
@ -1098,7 +1126,7 @@ rtas_return_loc:
|
||||
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
_ASM_NOKPROBE_SYMBOL(__enter_rtas)
|
||||
_ASM_NOKPROBE_SYMBOL(rtas_return_loc)
|
||||
@ -1171,7 +1199,7 @@ _GLOBAL(enter_prom)
|
||||
LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE)
|
||||
andc r11,r11,r12
|
||||
mtsrr1 r11
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
|
||||
1: /* Return from OF */
|
||||
|
@ -256,7 +256,7 @@ BEGIN_FTR_SECTION
|
||||
LOAD_HANDLER(r12, machine_check_handle_early)
|
||||
1: mtspr SPRN_SRR0,r12
|
||||
mtspr SPRN_SRR1,r11
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
2:
|
||||
/* Stack overflow. Stay on emergency stack and panic.
|
||||
@ -445,7 +445,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
|
||||
li r3,MSR_ME
|
||||
andc r10,r10,r3 /* Turn off MSR_ME */
|
||||
mtspr SPRN_SRR1,r10
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
2:
|
||||
/*
|
||||
@ -463,7 +463,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
|
||||
*/
|
||||
bl machine_check_queue_event
|
||||
MACHINE_CHECK_HANDLER_WINDUP
|
||||
rfid
|
||||
RFI_TO_USER_OR_KERNEL
|
||||
9:
|
||||
/* Deliver the machine check to host kernel in V mode. */
|
||||
MACHINE_CHECK_HANDLER_WINDUP
|
||||
@ -598,6 +598,9 @@ EXC_COMMON_BEGIN(slb_miss_common)
|
||||
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
|
||||
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
|
||||
|
||||
andi. r9,r11,MSR_PR // Check for exception from userspace
|
||||
cmpdi cr4,r9,MSR_PR // And save the result in CR4 for later
|
||||
|
||||
/*
|
||||
* Test MSR_RI before calling slb_allocate_realmode, because the
|
||||
* MSR in r11 gets clobbered. However we still want to allocate
|
||||
@ -624,9 +627,12 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
|
||||
|
||||
/* All done -- return from exception. */
|
||||
|
||||
bne cr4,1f /* returning to kernel */
|
||||
|
||||
.machine push
|
||||
.machine "power4"
|
||||
mtcrf 0x80,r9
|
||||
mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */
|
||||
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
|
||||
mtcrf 0x02,r9 /* I/D indication is in cr6 */
|
||||
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
|
||||
@ -640,8 +646,29 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
|
||||
ld r11,PACA_EXSLB+EX_R11(r13)
|
||||
ld r12,PACA_EXSLB+EX_R12(r13)
|
||||
ld r13,PACA_EXSLB+EX_R13(r13)
|
||||
rfid
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
1:
|
||||
.machine push
|
||||
.machine "power4"
|
||||
mtcrf 0x80,r9
|
||||
mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */
|
||||
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
|
||||
mtcrf 0x02,r9 /* I/D indication is in cr6 */
|
||||
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
|
||||
.machine pop
|
||||
|
||||
RESTORE_CTR(r9, PACA_EXSLB)
|
||||
RESTORE_PPR_PACA(PACA_EXSLB, r9)
|
||||
mr r3,r12
|
||||
ld r9,PACA_EXSLB+EX_R9(r13)
|
||||
ld r10,PACA_EXSLB+EX_R10(r13)
|
||||
ld r11,PACA_EXSLB+EX_R11(r13)
|
||||
ld r12,PACA_EXSLB+EX_R12(r13)
|
||||
ld r13,PACA_EXSLB+EX_R13(r13)
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
|
||||
2: std r3,PACA_EXSLB+EX_DAR(r13)
|
||||
mr r3,r12
|
||||
@ -651,7 +678,7 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
|
||||
mtspr SPRN_SRR0,r10
|
||||
ld r10,PACAKMSR(r13)
|
||||
mtspr SPRN_SRR1,r10
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
|
||||
8: std r3,PACA_EXSLB+EX_DAR(r13)
|
||||
@ -662,7 +689,7 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
|
||||
mtspr SPRN_SRR0,r10
|
||||
ld r10,PACAKMSR(r13)
|
||||
mtspr SPRN_SRR1,r10
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
|
||||
EXC_COMMON_BEGIN(unrecov_slb)
|
||||
@ -901,7 +928,7 @@ EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
|
||||
mtspr SPRN_SRR0,r10 ; \
|
||||
ld r10,PACAKMSR(r13) ; \
|
||||
mtspr SPRN_SRR1,r10 ; \
|
||||
rfid ; \
|
||||
RFI_TO_KERNEL ; \
|
||||
b . ; /* prevent speculative execution */
|
||||
|
||||
#ifdef CONFIG_PPC_FAST_ENDIAN_SWITCH
|
||||
@ -917,7 +944,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
|
||||
xori r12,r12,MSR_LE ; \
|
||||
mtspr SPRN_SRR1,r12 ; \
|
||||
mr r13,r9 ; \
|
||||
rfid ; /* return to userspace */ \
|
||||
RFI_TO_USER ; /* return to userspace */ \
|
||||
b . ; /* prevent speculative execution */
|
||||
#else
|
||||
#define SYSCALL_FASTENDIAN_TEST
|
||||
@ -1063,7 +1090,7 @@ TRAMP_REAL_BEGIN(hmi_exception_early)
|
||||
mtcr r11
|
||||
REST_GPR(11, r1)
|
||||
ld r1,GPR1(r1)
|
||||
hrfid
|
||||
HRFI_TO_USER_OR_KERNEL
|
||||
|
||||
1: mtcr r11
|
||||
REST_GPR(11, r1)
|
||||
@ -1314,7 +1341,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
|
||||
ld r11,PACA_EXGEN+EX_R11(r13)
|
||||
ld r12,PACA_EXGEN+EX_R12(r13)
|
||||
ld r13,PACA_EXGEN+EX_R13(r13)
|
||||
HRFID
|
||||
HRFI_TO_UNKNOWN
|
||||
b .
|
||||
#endif
|
||||
|
||||
@ -1418,10 +1445,94 @@ masked_##_H##interrupt: \
|
||||
ld r10,PACA_EXGEN+EX_R10(r13); \
|
||||
ld r11,PACA_EXGEN+EX_R11(r13); \
|
||||
/* returns to kernel where r13 must be set up, so don't restore it */ \
|
||||
##_H##rfid; \
|
||||
##_H##RFI_TO_KERNEL; \
|
||||
b .; \
|
||||
MASKED_DEC_HANDLER(_H)
|
||||
|
||||
TRAMP_REAL_BEGIN(rfi_flush_fallback)
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
std r12,PACA_EXRFI+EX_R12(r13)
|
||||
std r8,PACA_EXRFI+EX_R13(r13)
|
||||
mfctr r9
|
||||
ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
|
||||
ld r11,PACA_L1D_FLUSH_SETS(r13)
|
||||
ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13)
|
||||
/*
|
||||
* The load adresses are at staggered offsets within cachelines,
|
||||
* which suits some pipelines better (on others it should not
|
||||
* hurt).
|
||||
*/
|
||||
addi r12,r12,8
|
||||
mtctr r11
|
||||
DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
|
||||
|
||||
/* order ld/st prior to dcbt stop all streams with flushing */
|
||||
sync
|
||||
1: li r8,0
|
||||
.rept 8 /* 8-way set associative */
|
||||
ldx r11,r10,r8
|
||||
add r8,r8,r12
|
||||
xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not
|
||||
add r8,r8,r11 // Add 0, this creates a dependency on the ldx
|
||||
.endr
|
||||
addi r10,r10,128 /* 128 byte cache line */
|
||||
bdnz 1b
|
||||
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
ld r12,PACA_EXRFI+EX_R12(r13)
|
||||
ld r8,PACA_EXRFI+EX_R13(r13)
|
||||
GET_SCRATCH0(r13);
|
||||
rfid
|
||||
|
||||
TRAMP_REAL_BEGIN(hrfi_flush_fallback)
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
std r12,PACA_EXRFI+EX_R12(r13)
|
||||
std r8,PACA_EXRFI+EX_R13(r13)
|
||||
mfctr r9
|
||||
ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
|
||||
ld r11,PACA_L1D_FLUSH_SETS(r13)
|
||||
ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13)
|
||||
/*
|
||||
* The load adresses are at staggered offsets within cachelines,
|
||||
* which suits some pipelines better (on others it should not
|
||||
* hurt).
|
||||
*/
|
||||
addi r12,r12,8
|
||||
mtctr r11
|
||||
DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
|
||||
|
||||
/* order ld/st prior to dcbt stop all streams with flushing */
|
||||
sync
|
||||
1: li r8,0
|
||||
.rept 8 /* 8-way set associative */
|
||||
ldx r11,r10,r8
|
||||
add r8,r8,r12
|
||||
xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not
|
||||
add r8,r8,r11 // Add 0, this creates a dependency on the ldx
|
||||
.endr
|
||||
addi r10,r10,128 /* 128 byte cache line */
|
||||
bdnz 1b
|
||||
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
ld r12,PACA_EXRFI+EX_R12(r13)
|
||||
ld r8,PACA_EXRFI+EX_R13(r13)
|
||||
GET_SCRATCH0(r13);
|
||||
hrfid
|
||||
|
||||
/*
|
||||
* Real mode exceptions actually use this too, but alternate
|
||||
* instruction code patches (which end up in the common .text area)
|
||||
@ -1441,7 +1552,7 @@ TRAMP_REAL_BEGIN(kvmppc_skip_interrupt)
|
||||
addi r13, r13, 4
|
||||
mtspr SPRN_SRR0, r13
|
||||
GET_SCRATCH0(r13)
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
|
||||
TRAMP_REAL_BEGIN(kvmppc_skip_Hinterrupt)
|
||||
@ -1453,7 +1564,7 @@ TRAMP_REAL_BEGIN(kvmppc_skip_Hinterrupt)
|
||||
addi r13, r13, 4
|
||||
mtspr SPRN_HSRR0, r13
|
||||
GET_SCRATCH0(r13)
|
||||
hrfid
|
||||
HRFI_TO_KERNEL
|
||||
b .
|
||||
#endif
|
||||
|
||||
|
@ -242,14 +242,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
unsigned short maj;
|
||||
unsigned short min;
|
||||
|
||||
/* We only show online cpus: disable preempt (overzealous, I
|
||||
* knew) to prevent cpu going down. */
|
||||
preempt_disable();
|
||||
if (!cpu_online(cpu_id)) {
|
||||
preempt_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
pvr = per_cpu(cpu_pvr, cpu_id);
|
||||
#else
|
||||
@ -358,9 +350,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
#ifdef CONFIG_SMP
|
||||
seq_printf(m, "\n");
|
||||
#endif
|
||||
|
||||
preempt_enable();
|
||||
|
||||
/* If this is the last cpu, print the summary */
|
||||
if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids)
|
||||
show_cpuinfo_summary(m);
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <linux/memory.h>
|
||||
#include <linux/nmi.h>
|
||||
|
||||
#include <asm/debugfs.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/kdump.h>
|
||||
#include <asm/prom.h>
|
||||
@ -801,3 +802,141 @@ static int __init disable_hardlockup_detector(void)
|
||||
return 0;
|
||||
}
|
||||
early_initcall(disable_hardlockup_detector);
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
static enum l1d_flush_type enabled_flush_types;
|
||||
static void *l1d_flush_fallback_area;
|
||||
static bool no_rfi_flush;
|
||||
bool rfi_flush;
|
||||
|
||||
static int __init handle_no_rfi_flush(char *p)
|
||||
{
|
||||
pr_info("rfi-flush: disabled on command line.");
|
||||
no_rfi_flush = true;
|
||||
return 0;
|
||||
}
|
||||
early_param("no_rfi_flush", handle_no_rfi_flush);
|
||||
|
||||
/*
|
||||
* The RFI flush is not KPTI, but because users will see doco that says to use
|
||||
* nopti we hijack that option here to also disable the RFI flush.
|
||||
*/
|
||||
static int __init handle_no_pti(char *p)
|
||||
{
|
||||
pr_info("rfi-flush: disabling due to 'nopti' on command line.\n");
|
||||
handle_no_rfi_flush(NULL);
|
||||
return 0;
|
||||
}
|
||||
early_param("nopti", handle_no_pti);
|
||||
|
||||
static void do_nothing(void *unused)
|
||||
{
|
||||
/*
|
||||
* We don't need to do the flush explicitly, just enter+exit kernel is
|
||||
* sufficient, the RFI exit handlers will do the right thing.
|
||||
*/
|
||||
}
|
||||
|
||||
void rfi_flush_enable(bool enable)
|
||||
{
|
||||
if (rfi_flush == enable)
|
||||
return;
|
||||
|
||||
if (enable) {
|
||||
do_rfi_flush_fixups(enabled_flush_types);
|
||||
on_each_cpu(do_nothing, NULL, 1);
|
||||
} else
|
||||
do_rfi_flush_fixups(L1D_FLUSH_NONE);
|
||||
|
||||
rfi_flush = enable;
|
||||
}
|
||||
|
||||
static void init_fallback_flush(void)
|
||||
{
|
||||
u64 l1d_size, limit;
|
||||
int cpu;
|
||||
|
||||
l1d_size = ppc64_caches.l1d.size;
|
||||
limit = min(safe_stack_limit(), ppc64_rma_size);
|
||||
|
||||
/*
|
||||
* Align to L1d size, and size it at 2x L1d size, to catch possible
|
||||
* hardware prefetch runoff. We don't have a recipe for load patterns to
|
||||
* reliably avoid the prefetcher.
|
||||
*/
|
||||
l1d_flush_fallback_area = __va(memblock_alloc_base(l1d_size * 2, l1d_size, limit));
|
||||
memset(l1d_flush_fallback_area, 0, l1d_size * 2);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
/*
|
||||
* The fallback flush is currently coded for 8-way
|
||||
* associativity. Different associativity is possible, but it
|
||||
* will be treated as 8-way and may not evict the lines as
|
||||
* effectively.
|
||||
*
|
||||
* 128 byte lines are mandatory.
|
||||
*/
|
||||
u64 c = l1d_size / 8;
|
||||
|
||||
paca[cpu].rfi_flush_fallback_area = l1d_flush_fallback_area;
|
||||
paca[cpu].l1d_flush_congruence = c;
|
||||
paca[cpu].l1d_flush_sets = c / 128;
|
||||
}
|
||||
}
|
||||
|
||||
void __init setup_rfi_flush(enum l1d_flush_type types, bool enable)
|
||||
{
|
||||
if (types & L1D_FLUSH_FALLBACK) {
|
||||
pr_info("rfi-flush: Using fallback displacement flush\n");
|
||||
init_fallback_flush();
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_ORI)
|
||||
pr_info("rfi-flush: Using ori type flush\n");
|
||||
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
pr_info("rfi-flush: Using mttrig type flush\n");
|
||||
|
||||
enabled_flush_types = types;
|
||||
|
||||
if (!no_rfi_flush)
|
||||
rfi_flush_enable(enable);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int rfi_flush_set(void *data, u64 val)
|
||||
{
|
||||
if (val == 1)
|
||||
rfi_flush_enable(true);
|
||||
else if (val == 0)
|
||||
rfi_flush_enable(false);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfi_flush_get(void *data, u64 *val)
|
||||
{
|
||||
*val = rfi_flush ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n");
|
||||
|
||||
static __init int rfi_flush_debugfs_init(void)
|
||||
{
|
||||
debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(rfi_flush_debugfs_init);
|
||||
#endif
|
||||
|
||||
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (rfi_flush)
|
||||
return sprintf(buf, "Mitigation: RFI Flush\n");
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
@ -132,6 +132,15 @@ SECTIONS
|
||||
/* Read-only data */
|
||||
RO_DATA(PAGE_SIZE)
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
. = ALIGN(8);
|
||||
__rfi_flush_fixup : AT(ADDR(__rfi_flush_fixup) - LOAD_OFFSET) {
|
||||
__start___rfi_flush_fixup = .;
|
||||
*(__rfi_flush_fixup)
|
||||
__stop___rfi_flush_fixup = .;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXCEPTION_TABLE(0)
|
||||
|
||||
NOTES :kernel :notes
|
||||
|
@ -235,6 +235,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
|
||||
gpte->may_read = true;
|
||||
gpte->may_write = true;
|
||||
gpte->page_size = MMU_PAGE_4K;
|
||||
gpte->wimg = HPTE_R_M;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -65,11 +65,17 @@ struct kvm_resize_hpt {
|
||||
u32 order;
|
||||
|
||||
/* These fields protected by kvm->lock */
|
||||
int error;
|
||||
bool prepare_done;
|
||||
|
||||
/* Private to the work thread, until prepare_done is true,
|
||||
* then protected by kvm->resize_hpt_sem */
|
||||
/* Possible values and their usage:
|
||||
* <0 an error occurred during allocation,
|
||||
* -EBUSY allocation is in the progress,
|
||||
* 0 allocation made successfuly.
|
||||
*/
|
||||
int error;
|
||||
|
||||
/* Private to the work thread, until error != -EBUSY,
|
||||
* then protected by kvm->lock.
|
||||
*/
|
||||
struct kvm_hpt_info hpt;
|
||||
};
|
||||
|
||||
@ -159,8 +165,6 @@ long kvmppc_alloc_reset_hpt(struct kvm *kvm, int order)
|
||||
* Reset all the reverse-mapping chains for all memslots
|
||||
*/
|
||||
kvmppc_rmap_reset(kvm);
|
||||
/* Ensure that each vcpu will flush its TLB on next entry. */
|
||||
cpumask_setall(&kvm->arch.need_tlb_flush);
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
@ -176,6 +180,10 @@ long kvmppc_alloc_reset_hpt(struct kvm *kvm, int order)
|
||||
kvmppc_set_hpt(kvm, &info);
|
||||
|
||||
out:
|
||||
if (err == 0)
|
||||
/* Ensure that each vcpu will flush its TLB on next entry. */
|
||||
cpumask_setall(&kvm->arch.need_tlb_flush);
|
||||
|
||||
mutex_unlock(&kvm->lock);
|
||||
return err;
|
||||
}
|
||||
@ -1413,16 +1421,20 @@ static void resize_hpt_pivot(struct kvm_resize_hpt *resize)
|
||||
|
||||
static void resize_hpt_release(struct kvm *kvm, struct kvm_resize_hpt *resize)
|
||||
{
|
||||
BUG_ON(kvm->arch.resize_hpt != resize);
|
||||
if (WARN_ON(!mutex_is_locked(&kvm->lock)))
|
||||
return;
|
||||
|
||||
if (!resize)
|
||||
return;
|
||||
|
||||
if (resize->hpt.virt)
|
||||
kvmppc_free_hpt(&resize->hpt);
|
||||
if (resize->error != -EBUSY) {
|
||||
if (resize->hpt.virt)
|
||||
kvmppc_free_hpt(&resize->hpt);
|
||||
kfree(resize);
|
||||
}
|
||||
|
||||
kvm->arch.resize_hpt = NULL;
|
||||
kfree(resize);
|
||||
if (kvm->arch.resize_hpt == resize)
|
||||
kvm->arch.resize_hpt = NULL;
|
||||
}
|
||||
|
||||
static void resize_hpt_prepare_work(struct work_struct *work)
|
||||
@ -1431,17 +1443,41 @@ static void resize_hpt_prepare_work(struct work_struct *work)
|
||||
struct kvm_resize_hpt,
|
||||
work);
|
||||
struct kvm *kvm = resize->kvm;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
resize_hpt_debug(resize, "resize_hpt_prepare_work(): order = %d\n",
|
||||
resize->order);
|
||||
|
||||
err = resize_hpt_allocate(resize);
|
||||
if (WARN_ON(resize->error != -EBUSY))
|
||||
return;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
|
||||
/* Request is still current? */
|
||||
if (kvm->arch.resize_hpt == resize) {
|
||||
/* We may request large allocations here:
|
||||
* do not sleep with kvm->lock held for a while.
|
||||
*/
|
||||
mutex_unlock(&kvm->lock);
|
||||
|
||||
resize_hpt_debug(resize, "resize_hpt_prepare_work(): order = %d\n",
|
||||
resize->order);
|
||||
|
||||
err = resize_hpt_allocate(resize);
|
||||
|
||||
/* We have strict assumption about -EBUSY
|
||||
* when preparing for HPT resize.
|
||||
*/
|
||||
if (WARN_ON(err == -EBUSY))
|
||||
err = -EINPROGRESS;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
/* It is possible that kvm->arch.resize_hpt != resize
|
||||
* after we grab kvm->lock again.
|
||||
*/
|
||||
}
|
||||
|
||||
resize->error = err;
|
||||
resize->prepare_done = true;
|
||||
|
||||
if (kvm->arch.resize_hpt != resize)
|
||||
resize_hpt_release(kvm, resize);
|
||||
|
||||
mutex_unlock(&kvm->lock);
|
||||
}
|
||||
@ -1466,14 +1502,12 @@ long kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm,
|
||||
|
||||
if (resize) {
|
||||
if (resize->order == shift) {
|
||||
/* Suitable resize in progress */
|
||||
if (resize->prepare_done) {
|
||||
ret = resize->error;
|
||||
if (ret != 0)
|
||||
resize_hpt_release(kvm, resize);
|
||||
} else {
|
||||
/* Suitable resize in progress? */
|
||||
ret = resize->error;
|
||||
if (ret == -EBUSY)
|
||||
ret = 100; /* estimated time in ms */
|
||||
}
|
||||
else if (ret)
|
||||
resize_hpt_release(kvm, resize);
|
||||
|
||||
goto out;
|
||||
}
|
||||
@ -1493,6 +1527,8 @@ long kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm,
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
resize->error = -EBUSY;
|
||||
resize->order = shift;
|
||||
resize->kvm = kvm;
|
||||
INIT_WORK(&resize->work, resize_hpt_prepare_work);
|
||||
@ -1547,16 +1583,12 @@ long kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm,
|
||||
if (!resize || (resize->order != shift))
|
||||
goto out;
|
||||
|
||||
ret = -EBUSY;
|
||||
if (!resize->prepare_done)
|
||||
goto out;
|
||||
|
||||
ret = resize->error;
|
||||
if (ret != 0)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = resize_hpt_rehash(resize);
|
||||
if (ret != 0)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
resize_hpt_pivot(resize);
|
||||
|
@ -79,7 +79,7 @@ _GLOBAL_TOC(kvmppc_hv_entry_trampoline)
|
||||
mtmsrd r0,1 /* clear RI in MSR */
|
||||
mtsrr0 r5
|
||||
mtsrr1 r6
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
kvmppc_call_hv_entry:
|
||||
BEGIN_FTR_SECTION
|
||||
@ -199,7 +199,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
||||
mtmsrd r6, 1 /* Clear RI in MSR */
|
||||
mtsrr0 r8
|
||||
mtsrr1 r7
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
/* Virtual-mode return */
|
||||
.Lvirt_return:
|
||||
@ -1167,8 +1167,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
||||
|
||||
ld r0, VCPU_GPR(R0)(r4)
|
||||
ld r4, VCPU_GPR(R4)(r4)
|
||||
|
||||
hrfid
|
||||
HRFI_TO_GUEST
|
||||
b .
|
||||
|
||||
secondary_too_late:
|
||||
@ -3320,7 +3319,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
|
||||
ld r4, PACAKMSR(r13)
|
||||
mtspr SPRN_SRR0, r3
|
||||
mtspr SPRN_SRR1, r4
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
9: addi r3, r1, STACK_FRAME_OVERHEAD
|
||||
bl kvmppc_bad_interrupt
|
||||
b 9b
|
||||
|
@ -60,6 +60,7 @@ static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac);
|
||||
#define MSR_USER32 MSR_USER
|
||||
#define MSR_USER64 MSR_USER
|
||||
#define HW_PAGE_SIZE PAGE_SIZE
|
||||
#define HPTE_R_M _PAGE_COHERENT
|
||||
#endif
|
||||
|
||||
static bool kvmppc_is_split_real(struct kvm_vcpu *vcpu)
|
||||
@ -557,6 +558,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||
pte.eaddr = eaddr;
|
||||
pte.vpage = eaddr >> 12;
|
||||
pte.page_size = MMU_PAGE_64K;
|
||||
pte.wimg = HPTE_R_M;
|
||||
}
|
||||
|
||||
switch (kvmppc_get_msr(vcpu) & (MSR_DR|MSR_IR)) {
|
||||
|
@ -46,6 +46,9 @@
|
||||
|
||||
#define FUNC(name) name
|
||||
|
||||
#define RFI_TO_KERNEL RFI
|
||||
#define RFI_TO_GUEST RFI
|
||||
|
||||
.macro INTERRUPT_TRAMPOLINE intno
|
||||
|
||||
.global kvmppc_trampoline_\intno
|
||||
@ -141,7 +144,7 @@ kvmppc_handler_skip_ins:
|
||||
GET_SCRATCH0(r13)
|
||||
|
||||
/* And get back into the code */
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -164,6 +167,6 @@ _GLOBAL_TOC(kvmppc_entry_trampoline)
|
||||
ori r5, r5, MSR_EE
|
||||
mtsrr0 r7
|
||||
mtsrr1 r6
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
#include "book3s_segment.S"
|
||||
|
@ -156,7 +156,7 @@ no_dcbz32_on:
|
||||
PPC_LL r9, SVCPU_R9(r3)
|
||||
PPC_LL r3, (SVCPU_R3)(r3)
|
||||
|
||||
RFI
|
||||
RFI_TO_GUEST
|
||||
kvmppc_handler_trampoline_enter_end:
|
||||
|
||||
|
||||
@ -407,5 +407,5 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
|
||||
cmpwi r12, BOOK3S_INTERRUPT_DOORBELL
|
||||
beqa BOOK3S_INTERRUPT_DOORBELL
|
||||
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
kvmppc_handler_trampoline_exit_end:
|
||||
|
@ -39,6 +39,10 @@
|
||||
#include <asm/iommu.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <asm/xive.h>
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/plpar_wrappers.h>
|
||||
#endif
|
||||
|
||||
#include "timing.h"
|
||||
#include "irq.h"
|
||||
@ -548,6 +552,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
#ifdef CONFIG_KVM_XICS
|
||||
case KVM_CAP_IRQ_XICS:
|
||||
#endif
|
||||
case KVM_CAP_PPC_GET_CPU_CHAR:
|
||||
r = 1;
|
||||
break;
|
||||
|
||||
@ -1759,6 +1764,124 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
/*
|
||||
* These functions check whether the underlying hardware is safe
|
||||
* against attacks based on observing the effects of speculatively
|
||||
* executed instructions, and whether it supplies instructions for
|
||||
* use in workarounds. The information comes from firmware, either
|
||||
* via the device tree on powernv platforms or from an hcall on
|
||||
* pseries platforms.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
static int pseries_get_cpu_char(struct kvm_ppc_cpu_char *cp)
|
||||
{
|
||||
struct h_cpu_char_result c;
|
||||
unsigned long rc;
|
||||
|
||||
if (!machine_is(pseries))
|
||||
return -ENOTTY;
|
||||
|
||||
rc = plpar_get_cpu_characteristics(&c);
|
||||
if (rc == H_SUCCESS) {
|
||||
cp->character = c.character;
|
||||
cp->behaviour = c.behaviour;
|
||||
cp->character_mask = KVM_PPC_CPU_CHAR_SPEC_BAR_ORI31 |
|
||||
KVM_PPC_CPU_CHAR_BCCTRL_SERIALISED |
|
||||
KVM_PPC_CPU_CHAR_L1D_FLUSH_ORI30 |
|
||||
KVM_PPC_CPU_CHAR_L1D_FLUSH_TRIG2 |
|
||||
KVM_PPC_CPU_CHAR_L1D_THREAD_PRIV |
|
||||
KVM_PPC_CPU_CHAR_BR_HINT_HONOURED |
|
||||
KVM_PPC_CPU_CHAR_MTTRIG_THR_RECONF |
|
||||
KVM_PPC_CPU_CHAR_COUNT_CACHE_DIS;
|
||||
cp->behaviour_mask = KVM_PPC_CPU_BEHAV_FAVOUR_SECURITY |
|
||||
KVM_PPC_CPU_BEHAV_L1D_FLUSH_PR |
|
||||
KVM_PPC_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int pseries_get_cpu_char(struct kvm_ppc_cpu_char *cp)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool have_fw_feat(struct device_node *fw_features,
|
||||
const char *state, const char *name)
|
||||
{
|
||||
struct device_node *np;
|
||||
bool r = false;
|
||||
|
||||
np = of_get_child_by_name(fw_features, name);
|
||||
if (np) {
|
||||
r = of_property_read_bool(np, state);
|
||||
of_node_put(np);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int kvmppc_get_cpu_char(struct kvm_ppc_cpu_char *cp)
|
||||
{
|
||||
struct device_node *np, *fw_features;
|
||||
int r;
|
||||
|
||||
memset(cp, 0, sizeof(*cp));
|
||||
r = pseries_get_cpu_char(cp);
|
||||
if (r != -ENOTTY)
|
||||
return r;
|
||||
|
||||
np = of_find_node_by_name(NULL, "ibm,opal");
|
||||
if (np) {
|
||||
fw_features = of_get_child_by_name(np, "fw-features");
|
||||
of_node_put(np);
|
||||
if (!fw_features)
|
||||
return 0;
|
||||
if (have_fw_feat(fw_features, "enabled",
|
||||
"inst-spec-barrier-ori31,31,0"))
|
||||
cp->character |= KVM_PPC_CPU_CHAR_SPEC_BAR_ORI31;
|
||||
if (have_fw_feat(fw_features, "enabled",
|
||||
"fw-bcctrl-serialized"))
|
||||
cp->character |= KVM_PPC_CPU_CHAR_BCCTRL_SERIALISED;
|
||||
if (have_fw_feat(fw_features, "enabled",
|
||||
"inst-l1d-flush-ori30,30,0"))
|
||||
cp->character |= KVM_PPC_CPU_CHAR_L1D_FLUSH_ORI30;
|
||||
if (have_fw_feat(fw_features, "enabled",
|
||||
"inst-l1d-flush-trig2"))
|
||||
cp->character |= KVM_PPC_CPU_CHAR_L1D_FLUSH_TRIG2;
|
||||
if (have_fw_feat(fw_features, "enabled",
|
||||
"fw-l1d-thread-split"))
|
||||
cp->character |= KVM_PPC_CPU_CHAR_L1D_THREAD_PRIV;
|
||||
if (have_fw_feat(fw_features, "enabled",
|
||||
"fw-count-cache-disabled"))
|
||||
cp->character |= KVM_PPC_CPU_CHAR_COUNT_CACHE_DIS;
|
||||
cp->character_mask = KVM_PPC_CPU_CHAR_SPEC_BAR_ORI31 |
|
||||
KVM_PPC_CPU_CHAR_BCCTRL_SERIALISED |
|
||||
KVM_PPC_CPU_CHAR_L1D_FLUSH_ORI30 |
|
||||
KVM_PPC_CPU_CHAR_L1D_FLUSH_TRIG2 |
|
||||
KVM_PPC_CPU_CHAR_L1D_THREAD_PRIV |
|
||||
KVM_PPC_CPU_CHAR_COUNT_CACHE_DIS;
|
||||
|
||||
if (have_fw_feat(fw_features, "enabled",
|
||||
"speculation-policy-favor-security"))
|
||||
cp->behaviour |= KVM_PPC_CPU_BEHAV_FAVOUR_SECURITY;
|
||||
if (!have_fw_feat(fw_features, "disabled",
|
||||
"needs-l1d-flush-msr-pr-0-to-1"))
|
||||
cp->behaviour |= KVM_PPC_CPU_BEHAV_L1D_FLUSH_PR;
|
||||
if (!have_fw_feat(fw_features, "disabled",
|
||||
"needs-spec-barrier-for-bound-checks"))
|
||||
cp->behaviour |= KVM_PPC_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
|
||||
cp->behaviour_mask = KVM_PPC_CPU_BEHAV_FAVOUR_SECURITY |
|
||||
KVM_PPC_CPU_BEHAV_L1D_FLUSH_PR |
|
||||
KVM_PPC_CPU_BEHAV_BNDS_CHK_SPEC_BAR;
|
||||
|
||||
of_node_put(fw_features);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
long kvm_arch_vm_ioctl(struct file *filp,
|
||||
unsigned int ioctl, unsigned long arg)
|
||||
{
|
||||
@ -1861,6 +1984,14 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
case KVM_PPC_GET_CPU_CHAR: {
|
||||
struct kvm_ppc_cpu_char cpuchar;
|
||||
|
||||
r = kvmppc_get_cpu_char(&cpuchar);
|
||||
if (r >= 0 && copy_to_user(argp, &cpuchar, sizeof(cpuchar)))
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
struct kvm *kvm = filp->private_data;
|
||||
r = kvm->arch.kvm_ops->arch_vm_ioctl(filp, ioctl, arg);
|
||||
|
@ -116,6 +116,47 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types)
|
||||
{
|
||||
unsigned int instrs[3], *dest;
|
||||
long *start, *end;
|
||||
int i;
|
||||
|
||||
start = PTRRELOC(&__start___rfi_flush_fixup),
|
||||
end = PTRRELOC(&__stop___rfi_flush_fixup);
|
||||
|
||||
instrs[0] = 0x60000000; /* nop */
|
||||
instrs[1] = 0x60000000; /* nop */
|
||||
instrs[2] = 0x60000000; /* nop */
|
||||
|
||||
if (types & L1D_FLUSH_FALLBACK)
|
||||
/* b .+16 to fallback flush */
|
||||
instrs[0] = 0x48000010;
|
||||
|
||||
i = 0;
|
||||
if (types & L1D_FLUSH_ORI) {
|
||||
instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
|
||||
instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
|
||||
|
||||
for (i = 0; start < end; start++, i++) {
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction(dest, instrs[0]);
|
||||
patch_instruction(dest + 1, instrs[1]);
|
||||
patch_instruction(dest + 2, instrs[2]);
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "rfi-flush: patched %d locations\n", i);
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
||||
{
|
||||
long *start, *end;
|
||||
|
@ -145,6 +145,11 @@ static noinline int bad_area(struct pt_regs *regs, unsigned long address)
|
||||
return __bad_area(regs, address, SEGV_MAPERR);
|
||||
}
|
||||
|
||||
static noinline int bad_access(struct pt_regs *regs, unsigned long address)
|
||||
{
|
||||
return __bad_area(regs, address, SEGV_ACCERR);
|
||||
}
|
||||
|
||||
static int do_sigbus(struct pt_regs *regs, unsigned long address,
|
||||
unsigned int fault)
|
||||
{
|
||||
@ -490,7 +495,7 @@ retry:
|
||||
|
||||
good_area:
|
||||
if (unlikely(access_error(is_write, is_exec, vma)))
|
||||
return bad_area(regs, address);
|
||||
return bad_access(regs, address);
|
||||
|
||||
/*
|
||||
* If for any reason at all we couldn't handle the fault,
|
||||
|
@ -37,13 +37,62 @@
|
||||
#include <asm/kexec.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/tm.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include "powernv.h"
|
||||
|
||||
static void pnv_setup_rfi_flush(void)
|
||||
{
|
||||
struct device_node *np, *fw_features;
|
||||
enum l1d_flush_type type;
|
||||
int enable;
|
||||
|
||||
/* Default to fallback in case fw-features are not available */
|
||||
type = L1D_FLUSH_FALLBACK;
|
||||
enable = 1;
|
||||
|
||||
np = of_find_node_by_name(NULL, "ibm,opal");
|
||||
fw_features = of_get_child_by_name(np, "fw-features");
|
||||
of_node_put(np);
|
||||
|
||||
if (fw_features) {
|
||||
np = of_get_child_by_name(fw_features, "inst-l1d-flush-trig2");
|
||||
if (np && of_property_read_bool(np, "enabled"))
|
||||
type = L1D_FLUSH_MTTRIG;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
np = of_get_child_by_name(fw_features, "inst-l1d-flush-ori30,30,0");
|
||||
if (np && of_property_read_bool(np, "enabled"))
|
||||
type = L1D_FLUSH_ORI;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
/* Enable unless firmware says NOT to */
|
||||
enable = 2;
|
||||
np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-hv-1-to-0");
|
||||
if (np && of_property_read_bool(np, "disabled"))
|
||||
enable--;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-pr-0-to-1");
|
||||
if (np && of_property_read_bool(np, "disabled"))
|
||||
enable--;
|
||||
|
||||
of_node_put(np);
|
||||
of_node_put(fw_features);
|
||||
}
|
||||
|
||||
setup_rfi_flush(type, enable > 0);
|
||||
}
|
||||
|
||||
static void __init pnv_setup_arch(void)
|
||||
{
|
||||
set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
|
||||
|
||||
pnv_setup_rfi_flush();
|
||||
|
||||
/* Initialize SMP */
|
||||
pnv_smp_init();
|
||||
|
||||
|
@ -574,11 +574,26 @@ static ssize_t dlpar_show(struct class *class, struct class_attribute *attr,
|
||||
|
||||
static CLASS_ATTR_RW(dlpar);
|
||||
|
||||
static int __init pseries_dlpar_init(void)
|
||||
int __init dlpar_workqueue_init(void)
|
||||
{
|
||||
if (pseries_hp_wq)
|
||||
return 0;
|
||||
|
||||
pseries_hp_wq = alloc_workqueue("pseries hotplug workqueue",
|
||||
WQ_UNBOUND, 1);
|
||||
WQ_UNBOUND, 1);
|
||||
|
||||
return pseries_hp_wq ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
static int __init dlpar_sysfs_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = dlpar_workqueue_init();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return sysfs_create_file(kernel_kobj, &class_attr_dlpar.attr);
|
||||
}
|
||||
machine_device_initcall(pseries, pseries_dlpar_init);
|
||||
machine_device_initcall(pseries, dlpar_sysfs_init);
|
||||
|
||||
|
@ -98,4 +98,6 @@ static inline unsigned long cmo_get_page_size(void)
|
||||
return CMO_PageSize;
|
||||
}
|
||||
|
||||
int dlpar_workqueue_init(void);
|
||||
|
||||
#endif /* _PSERIES_PSERIES_H */
|
||||
|
@ -69,7 +69,8 @@ static int __init init_ras_IRQ(void)
|
||||
/* Hotplug Events */
|
||||
np = of_find_node_by_path("/event-sources/hot-plug-events");
|
||||
if (np != NULL) {
|
||||
request_event_sources_irqs(np, ras_hotplug_interrupt,
|
||||
if (dlpar_workqueue_init() == 0)
|
||||
request_event_sources_irqs(np, ras_hotplug_interrupt,
|
||||
"RAS_HOTPLUG");
|
||||
of_node_put(np);
|
||||
}
|
||||
|
@ -459,6 +459,39 @@ static void __init find_and_init_phbs(void)
|
||||
of_pci_check_probe_only();
|
||||
}
|
||||
|
||||
static void pseries_setup_rfi_flush(void)
|
||||
{
|
||||
struct h_cpu_char_result result;
|
||||
enum l1d_flush_type types;
|
||||
bool enable;
|
||||
long rc;
|
||||
|
||||
/* Enable by default */
|
||||
enable = true;
|
||||
|
||||
rc = plpar_get_cpu_characteristics(&result);
|
||||
if (rc == H_SUCCESS) {
|
||||
types = L1D_FLUSH_NONE;
|
||||
|
||||
if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2)
|
||||
types |= L1D_FLUSH_MTTRIG;
|
||||
if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30)
|
||||
types |= L1D_FLUSH_ORI;
|
||||
|
||||
/* Use fallback if nothing set in hcall */
|
||||
if (types == L1D_FLUSH_NONE)
|
||||
types = L1D_FLUSH_FALLBACK;
|
||||
|
||||
if (!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR))
|
||||
enable = false;
|
||||
} else {
|
||||
/* Default to fallback if case hcall is not available */
|
||||
types = L1D_FLUSH_FALLBACK;
|
||||
}
|
||||
|
||||
setup_rfi_flush(types, enable);
|
||||
}
|
||||
|
||||
static void __init pSeries_setup_arch(void)
|
||||
{
|
||||
set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
|
||||
@ -476,6 +509,8 @@ static void __init pSeries_setup_arch(void)
|
||||
|
||||
fwnmi_init();
|
||||
|
||||
pseries_setup_rfi_flush();
|
||||
|
||||
/* By default, only probe PCI (can be overridden by rtas_pci) */
|
||||
pci_add_flags(PCI_PROBE_ONLY);
|
||||
|
||||
|
@ -2344,10 +2344,10 @@ static void dump_one_paca(int cpu)
|
||||
DUMP(p, kernel_toc, "lx");
|
||||
DUMP(p, kernelbase, "lx");
|
||||
DUMP(p, kernel_msr, "lx");
|
||||
DUMP(p, emergency_sp, "p");
|
||||
DUMP(p, emergency_sp, "px");
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
DUMP(p, nmi_emergency_sp, "p");
|
||||
DUMP(p, mc_emergency_sp, "p");
|
||||
DUMP(p, nmi_emergency_sp, "px");
|
||||
DUMP(p, mc_emergency_sp, "px");
|
||||
DUMP(p, in_nmi, "x");
|
||||
DUMP(p, in_mce, "x");
|
||||
DUMP(p, hmi_event_available, "x");
|
||||
@ -2375,17 +2375,21 @@ static void dump_one_paca(int cpu)
|
||||
DUMP(p, slb_cache_ptr, "x");
|
||||
for (i = 0; i < SLB_CACHE_ENTRIES; i++)
|
||||
printf(" slb_cache[%d]: = 0x%016lx\n", i, p->slb_cache[i]);
|
||||
|
||||
DUMP(p, rfi_flush_fallback_area, "px");
|
||||
DUMP(p, l1d_flush_congruence, "llx");
|
||||
DUMP(p, l1d_flush_sets, "llx");
|
||||
#endif
|
||||
DUMP(p, dscr_default, "llx");
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
DUMP(p, pgd, "p");
|
||||
DUMP(p, kernel_pgd, "p");
|
||||
DUMP(p, tcd_ptr, "p");
|
||||
DUMP(p, mc_kstack, "p");
|
||||
DUMP(p, crit_kstack, "p");
|
||||
DUMP(p, dbg_kstack, "p");
|
||||
DUMP(p, pgd, "px");
|
||||
DUMP(p, kernel_pgd, "px");
|
||||
DUMP(p, tcd_ptr, "px");
|
||||
DUMP(p, mc_kstack, "px");
|
||||
DUMP(p, crit_kstack, "px");
|
||||
DUMP(p, dbg_kstack, "px");
|
||||
#endif
|
||||
DUMP(p, __current, "p");
|
||||
DUMP(p, __current, "px");
|
||||
DUMP(p, kstack, "lx");
|
||||
printf(" kstack_base = 0x%016lx\n", p->kstack & ~(THREAD_SIZE - 1));
|
||||
DUMP(p, stab_rr, "lx");
|
||||
@ -2403,7 +2407,7 @@ static void dump_one_paca(int cpu)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
DUMP(p, core_idle_state_ptr, "p");
|
||||
DUMP(p, core_idle_state_ptr, "px");
|
||||
DUMP(p, thread_idle_state, "x");
|
||||
DUMP(p, thread_mask, "x");
|
||||
DUMP(p, subcore_sibling_mask, "x");
|
||||
|
@ -0,0 +1,75 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIE_XILINX=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_CFS_BANDWIDTH=y
|
||||
CONFIG_CGROUP_BPF=y
|
||||
CONFIG_NAMESPACES=y
|
||||
CONFIG_USER_NS=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_EXPERT=y
|
||||
CONFIG_CHECKPOINT_RESTORE=y
|
||||
CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_IP_PNP_RARP=y
|
||||
CONFIG_NETLINK_DIAG=y
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_VIRTIO_BLK=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
CONFIG_SATA_AHCI_PLATFORM=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_VIRTIO_NET=y
|
||||
CONFIG_MACB=y
|
||||
CONFIG_E1000E=y
|
||||
CONFIG_R8169=y
|
||||
CONFIG_MICROSEMI_PHY=y
|
||||
CONFIG_INPUT_MOUSEDEV=y
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
# CONFIG_PTP_1588_CLOCK is not set
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_RADEON=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_XHCI_PLATFORM=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_HCD_PLATFORM=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD_PLATFORM=y
|
||||
CONFIG_USB_STORAGE=y
|
||||
CONFIG_USB_UAS=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
CONFIG_RAS=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_AUTOFS4_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_TMPFS_POSIX_ACL=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_NFS_V4_1=y
|
||||
CONFIG_NFS_V4_2=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
# CONFIG_RCU_TRACE is not set
|
||||
CONFIG_CRYPTO_USER_API_HASH=y
|
@ -17,10 +17,10 @@
|
||||
#include <linux/const.h>
|
||||
|
||||
/* Status register flags */
|
||||
#define SR_IE _AC(0x00000002, UL) /* Interrupt Enable */
|
||||
#define SR_PIE _AC(0x00000020, UL) /* Previous IE */
|
||||
#define SR_PS _AC(0x00000100, UL) /* Previously Supervisor */
|
||||
#define SR_SUM _AC(0x00040000, UL) /* Supervisor may access User Memory */
|
||||
#define SR_SIE _AC(0x00000002, UL) /* Supervisor Interrupt Enable */
|
||||
#define SR_SPIE _AC(0x00000020, UL) /* Previous Supervisor IE */
|
||||
#define SR_SPP _AC(0x00000100, UL) /* Previously Supervisor */
|
||||
#define SR_SUM _AC(0x00040000, UL) /* Supervisor may access User Memory */
|
||||
|
||||
#define SR_FS _AC(0x00006000, UL) /* Floating-point Status */
|
||||
#define SR_FS_OFF _AC(0x00000000, UL)
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
extern void __iomem *ioremap(phys_addr_t offset, unsigned long size);
|
||||
|
||||
/*
|
||||
@ -36,8 +34,6 @@ extern void __iomem *ioremap(phys_addr_t offset, unsigned long size);
|
||||
|
||||
extern void iounmap(volatile void __iomem *addr);
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
/* Generic IO read/write. These perform native-endian accesses. */
|
||||
#define __raw_writeb __raw_writeb
|
||||
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
|
||||
|
@ -27,25 +27,25 @@ static inline unsigned long arch_local_save_flags(void)
|
||||
/* unconditionally enable interrupts */
|
||||
static inline void arch_local_irq_enable(void)
|
||||
{
|
||||
csr_set(sstatus, SR_IE);
|
||||
csr_set(sstatus, SR_SIE);
|
||||
}
|
||||
|
||||
/* unconditionally disable interrupts */
|
||||
static inline void arch_local_irq_disable(void)
|
||||
{
|
||||
csr_clear(sstatus, SR_IE);
|
||||
csr_clear(sstatus, SR_SIE);
|
||||
}
|
||||
|
||||
/* get status and disable interrupts */
|
||||
static inline unsigned long arch_local_irq_save(void)
|
||||
{
|
||||
return csr_read_clear(sstatus, SR_IE);
|
||||
return csr_read_clear(sstatus, SR_SIE);
|
||||
}
|
||||
|
||||
/* test flags */
|
||||
static inline int arch_irqs_disabled_flags(unsigned long flags)
|
||||
{
|
||||
return !(flags & SR_IE);
|
||||
return !(flags & SR_SIE);
|
||||
}
|
||||
|
||||
/* test hardware interrupt enable bit */
|
||||
@ -57,7 +57,7 @@ static inline int arch_irqs_disabled(void)
|
||||
/* set interrupt enabled status */
|
||||
static inline void arch_local_irq_restore(unsigned long flags)
|
||||
{
|
||||
csr_set(sstatus, flags & SR_IE);
|
||||
csr_set(sstatus, flags & SR_SIE);
|
||||
}
|
||||
|
||||
#endif /* _ASM_RISCV_IRQFLAGS_H */
|
||||
|
@ -20,8 +20,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
/* Page Upper Directory not used in RISC-V */
|
||||
#include <asm-generic/pgtable-nopud.h>
|
||||
#include <asm/page.h>
|
||||
@ -413,8 +411,6 @@ static inline void pgtable_cache_init(void)
|
||||
/* No page table caches to initialize */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
#define VMALLOC_SIZE (KERN_VIRT_SIZE >> 1)
|
||||
#define VMALLOC_END (PAGE_OFFSET - 1)
|
||||
#define VMALLOC_START (PAGE_OFFSET - VMALLOC_SIZE)
|
||||
|
@ -66,7 +66,7 @@ struct pt_regs {
|
||||
#define REG_FMT "%08lx"
|
||||
#endif
|
||||
|
||||
#define user_mode(regs) (((regs)->sstatus & SR_PS) == 0)
|
||||
#define user_mode(regs) (((regs)->sstatus & SR_SPP) == 0)
|
||||
|
||||
|
||||
/* Helpers for working with the instruction pointer */
|
||||
|
@ -15,8 +15,6 @@
|
||||
#ifndef _ASM_RISCV_TLBFLUSH_H
|
||||
#define _ASM_RISCV_TLBFLUSH_H
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
#include <linux/mm_types.h>
|
||||
|
||||
/*
|
||||
@ -64,6 +62,4 @@ static inline void flush_tlb_kernel_range(unsigned long start,
|
||||
flush_tlb_all();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
#endif /* _ASM_RISCV_TLBFLUSH_H */
|
||||
|
@ -127,7 +127,6 @@ extern int fixup_exception(struct pt_regs *state);
|
||||
* call.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#define __get_user_asm(insn, x, ptr, err) \
|
||||
do { \
|
||||
uintptr_t __tmp; \
|
||||
@ -153,13 +152,11 @@ do { \
|
||||
__disable_user_access(); \
|
||||
(x) = __x; \
|
||||
} while (0)
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define __get_user_8(x, ptr, err) \
|
||||
__get_user_asm("ld", x, ptr, err)
|
||||
#else /* !CONFIG_64BIT */
|
||||
#ifdef CONFIG_MMU
|
||||
#define __get_user_8(x, ptr, err) \
|
||||
do { \
|
||||
u32 __user *__ptr = (u32 __user *)(ptr); \
|
||||
@ -193,7 +190,6 @@ do { \
|
||||
(x) = (__typeof__(x))((__typeof__((x)-(x)))( \
|
||||
(((u64)__hi << 32) | __lo))); \
|
||||
} while (0)
|
||||
#endif /* CONFIG_MMU */
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
|
||||
@ -267,8 +263,6 @@ do { \
|
||||
((x) = 0, -EFAULT); \
|
||||
})
|
||||
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#define __put_user_asm(insn, x, ptr, err) \
|
||||
do { \
|
||||
uintptr_t __tmp; \
|
||||
@ -292,14 +286,11 @@ do { \
|
||||
: "rJ" (__x), "i" (-EFAULT)); \
|
||||
__disable_user_access(); \
|
||||
} while (0)
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define __put_user_8(x, ptr, err) \
|
||||
__put_user_asm("sd", x, ptr, err)
|
||||
#else /* !CONFIG_64BIT */
|
||||
#ifdef CONFIG_MMU
|
||||
#define __put_user_8(x, ptr, err) \
|
||||
do { \
|
||||
u32 __user *__ptr = (u32 __user *)(ptr); \
|
||||
@ -329,7 +320,6 @@ do { \
|
||||
: "rJ" (__x), "rJ" (__x >> 32), "i" (-EFAULT)); \
|
||||
__disable_user_access(); \
|
||||
} while (0)
|
||||
#endif /* CONFIG_MMU */
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
|
||||
@ -438,7 +428,6 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
|
||||
* will set "err" to -EFAULT, while successful accesses return the previous
|
||||
* value.
|
||||
*/
|
||||
#ifdef CONFIG_MMU
|
||||
#define __cmpxchg_user(ptr, old, new, err, size, lrb, scb) \
|
||||
({ \
|
||||
__typeof__(ptr) __ptr = (ptr); \
|
||||
@ -508,6 +497,5 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
|
||||
(err) = __err; \
|
||||
__ret; \
|
||||
})
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
#endif /* _ASM_RISCV_UACCESS_H */
|
||||
|
@ -14,3 +14,4 @@
|
||||
#define __ARCH_HAVE_MMU
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
#include <uapi/asm/unistd.h>
|
||||
#include <uapi/asm/syscalls.h>
|
||||
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 SiFive
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_RISCV_VDSO_SYSCALLS_H
|
||||
#define _ASM_RISCV_VDSO_SYSCALLS_H
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/* These syscalls are only used by the vDSO and are not in the uapi. */
|
||||
#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
|
||||
__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_RISCV_VDSO_H */
|
26
arch/riscv/include/uapi/asm/syscalls.h
Normal file
26
arch/riscv/include/uapi/asm/syscalls.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2017 SiFive
|
||||
*/
|
||||
|
||||
#ifndef _ASM__UAPI__SYSCALLS_H
|
||||
#define _ASM__UAPI__SYSCALLS_H
|
||||
|
||||
/*
|
||||
* Allows the instruction cache to be flushed from userspace. Despite RISC-V
|
||||
* having a direct 'fence.i' instruction available to userspace (which we
|
||||
* can't trap!), that's not actually viable when running on Linux because the
|
||||
* kernel might schedule a process on another hart. There is no way for
|
||||
* userspace to handle this without invoking the kernel (as it doesn't know the
|
||||
* thread->hart mappings), so we've defined a RISC-V specific system call to
|
||||
* flush the instruction cache.
|
||||
*
|
||||
* __NR_riscv_flush_icache is defined to flush the instruction cache over an
|
||||
* address range, with the flush applying to either all threads or just the
|
||||
* caller. We don't currently do anything with the address range, that's just
|
||||
* in there for forwards compatibility.
|
||||
*/
|
||||
#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
|
||||
__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
|
||||
|
||||
#endif
|
@ -196,7 +196,7 @@ handle_syscall:
|
||||
addi s2, s2, 0x4
|
||||
REG_S s2, PT_SEPC(sp)
|
||||
/* System calls run with interrupts enabled */
|
||||
csrs sstatus, SR_IE
|
||||
csrs sstatus, SR_SIE
|
||||
/* Trace syscalls, but only if requested by the user. */
|
||||
REG_L t0, TASK_TI_FLAGS(tp)
|
||||
andi t0, t0, _TIF_SYSCALL_TRACE
|
||||
@ -224,8 +224,8 @@ ret_from_syscall:
|
||||
|
||||
ret_from_exception:
|
||||
REG_L s0, PT_SSTATUS(sp)
|
||||
csrc sstatus, SR_IE
|
||||
andi s0, s0, SR_PS
|
||||
csrc sstatus, SR_SIE
|
||||
andi s0, s0, SR_SPP
|
||||
bnez s0, restore_all
|
||||
|
||||
resume_userspace:
|
||||
@ -255,7 +255,7 @@ work_pending:
|
||||
bnez s1, work_resched
|
||||
work_notifysig:
|
||||
/* Handle pending signals and notify-resume requests */
|
||||
csrs sstatus, SR_IE /* Enable interrupts for do_notify_resume() */
|
||||
csrs sstatus, SR_SIE /* Enable interrupts for do_notify_resume() */
|
||||
move a0, sp /* pt_regs */
|
||||
move a1, s0 /* current_thread_info->flags */
|
||||
tail do_notify_resume
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user