Merge 6cbf5b3105 ("Merge tag 'locking-core-2024-01-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip") into aosp-android-mainline
Steps on the way to 6.8-rc1 Change-Id: I0ca05e6dc9d65a7a65d2386805256ec19af3db5b Signed-off-by: Lee Jones <joneslee@google.com>:wq
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
Reliability, Availability and Serviceability features
|
||||
=====================================================
|
||||
|
||||
This documents different aspects of the RAS functionality present in the
|
||||
kernel.
|
||||
|
||||
Error decoding
|
||||
---------------
|
||||
|
||||
* x86
|
||||
|
||||
Error decoding on AMD systems should be done using the rasdaemon tool:
|
||||
https://github.com/mchehab/rasdaemon/
|
||||
|
||||
While the daemon is running, it would automatically log and decode
|
||||
errors. If not, one can still decode such errors by supplying the
|
||||
hardware information from the error::
|
||||
|
||||
$ rasdaemon -p --status <STATUS> --ipid <IPID> --smca
|
||||
|
||||
Also, the user can pass particular family and model to decode the error
|
||||
string::
|
||||
|
||||
$ rasdaemon -p --status <STATUS> --ipid <IPID> --smca --family <CPU Family> --model <CPU Model> --bank <BANK_NUM>
|
||||
@@ -0,0 +1,94 @@
|
||||
======================================================================
|
||||
Synopsys DesignWare Cores (DWC) PCIe Performance Monitoring Unit (PMU)
|
||||
======================================================================
|
||||
|
||||
DesignWare Cores (DWC) PCIe PMU
|
||||
===============================
|
||||
|
||||
The PMU is a PCIe configuration space register block provided by each PCIe Root
|
||||
Port in a Vendor-Specific Extended Capability named RAS D.E.S (Debug, Error
|
||||
injection, and Statistics).
|
||||
|
||||
As the name indicates, the RAS DES capability supports system level
|
||||
debugging, AER error injection, and collection of statistics. To facilitate
|
||||
collection of statistics, Synopsys DesignWare Cores PCIe controller
|
||||
provides the following two features:
|
||||
|
||||
- one 64-bit counter for Time Based Analysis (RX/TX data throughput and
|
||||
time spent in each low-power LTSSM state) and
|
||||
- one 32-bit counter for Event Counting (error and non-error events for
|
||||
a specified lane)
|
||||
|
||||
Note: There is no interrupt for counter overflow.
|
||||
|
||||
Time Based Analysis
|
||||
-------------------
|
||||
|
||||
Using this feature you can obtain information regarding RX/TX data
|
||||
throughput and time spent in each low-power LTSSM state by the controller.
|
||||
The PMU measures data in two categories:
|
||||
|
||||
- Group#0: Percentage of time the controller stays in LTSSM states.
|
||||
- Group#1: Amount of data processed (Units of 16 bytes).
|
||||
|
||||
Lane Event counters
|
||||
-------------------
|
||||
|
||||
Using this feature you can obtain Error and Non-Error information in
|
||||
specific lane by the controller. The PMU event is selected by all of:
|
||||
|
||||
- Group i
|
||||
- Event j within the Group i
|
||||
- Lane k
|
||||
|
||||
Some of the events only exist for specific configurations.
|
||||
|
||||
DesignWare Cores (DWC) PCIe PMU Driver
|
||||
=======================================
|
||||
|
||||
This driver adds PMU devices for each PCIe Root Port named based on the BDF of
|
||||
the Root Port. For example,
|
||||
|
||||
30:03.0 PCI bridge: Device 1ded:8000 (rev 01)
|
||||
|
||||
the PMU device name for this Root Port is dwc_rootport_3018.
|
||||
|
||||
The DWC PCIe PMU driver registers a perf PMU driver, which provides
|
||||
description of available events and configuration options in sysfs, see
|
||||
/sys/bus/event_source/devices/dwc_rootport_{bdf}.
|
||||
|
||||
The "format" directory describes format of the config fields of the
|
||||
perf_event_attr structure. The "events" directory provides configuration
|
||||
templates for all documented events. For example,
|
||||
"Rx_PCIe_TLP_Data_Payload" is an equivalent of "eventid=0x22,type=0x1".
|
||||
|
||||
The "perf list" command shall list the available events from sysfs, e.g.::
|
||||
|
||||
$# perf list | grep dwc_rootport
|
||||
<...>
|
||||
dwc_rootport_3018/Rx_PCIe_TLP_Data_Payload/ [Kernel PMU event]
|
||||
<...>
|
||||
dwc_rootport_3018/rx_memory_read,lane=?/ [Kernel PMU event]
|
||||
|
||||
Time Based Analysis Event Usage
|
||||
-------------------------------
|
||||
|
||||
Example usage of counting PCIe RX TLP data payload (Units of bytes)::
|
||||
|
||||
$# perf stat -a -e dwc_rootport_3018/Rx_PCIe_TLP_Data_Payload/
|
||||
|
||||
The average RX/TX bandwidth can be calculated using the following formula:
|
||||
|
||||
PCIe RX Bandwidth = Rx_PCIe_TLP_Data_Payload / Measure_Time_Window
|
||||
PCIe TX Bandwidth = Tx_PCIe_TLP_Data_Payload / Measure_Time_Window
|
||||
|
||||
Lane Event Usage
|
||||
-------------------------------
|
||||
|
||||
Each lane has the same event set and to avoid generating a list of hundreds
|
||||
of events, the user need to specify the lane ID explicitly, e.g.::
|
||||
|
||||
$# perf stat -a -e dwc_rootport_3018/rx_memory_read,lane=4/
|
||||
|
||||
The driver does not support sampling, therefore "perf record" will not
|
||||
work. Per-task (without "-a") perf sessions are not supported.
|
||||
@@ -13,8 +13,8 @@ is one register for each counter. Counter 0 is special in that it always counts
|
||||
interrupt is raised. If any other counter overflows, it continues counting, and
|
||||
no interrupt is raised.
|
||||
|
||||
The "format" directory describes format of the config (event ID) and config1
|
||||
(AXI filtering) fields of the perf_event_attr structure, see /sys/bus/event_source/
|
||||
The "format" directory describes format of the config (event ID) and config1/2
|
||||
(AXI filter setting) fields of the perf_event_attr structure, see /sys/bus/event_source/
|
||||
devices/imx8_ddr0/format/. The "events" directory describes the events types
|
||||
hardware supported that can be used with perf tool, see /sys/bus/event_source/
|
||||
devices/imx8_ddr0/events/. The "caps" directory describes filter features implemented
|
||||
@@ -28,12 +28,11 @@ in DDR PMU, see /sys/bus/events_source/devices/imx8_ddr0/caps/.
|
||||
AXI filtering is only used by CSV modes 0x41 (axid-read) and 0x42 (axid-write)
|
||||
to count reading or writing matches filter setting. Filter setting is various
|
||||
from different DRAM controller implementations, which is distinguished by quirks
|
||||
in the driver. You also can dump info from userspace, filter in "caps" directory
|
||||
indicates whether PMU supports AXI ID filter or not; enhanced_filter indicates
|
||||
whether PMU supports enhanced AXI ID filter or not. Value 0 for un-supported, and
|
||||
value 1 for supported.
|
||||
in the driver. You also can dump info from userspace, "caps" directory show the
|
||||
type of AXI filter (filter, enhanced_filter and super_filter). Value 0 for
|
||||
un-supported, and value 1 for supported.
|
||||
|
||||
* With DDR_CAP_AXI_ID_FILTER quirk(filter: 1, enhanced_filter: 0).
|
||||
* With DDR_CAP_AXI_ID_FILTER quirk(filter: 1, enhanced_filter: 0, super_filter: 0).
|
||||
Filter is defined with two configuration parts:
|
||||
--AXI_ID defines AxID matching value.
|
||||
--AXI_MASKING defines which bits of AxID are meaningful for the matching.
|
||||
@@ -65,7 +64,37 @@ value 1 for supported.
|
||||
|
||||
perf stat -a -e imx8_ddr0/axid-read,axi_id=0x12/ cmd, which will monitor ARID=0x12
|
||||
|
||||
* With DDR_CAP_AXI_ID_FILTER_ENHANCED quirk(filter: 1, enhanced_filter: 1).
|
||||
* With DDR_CAP_AXI_ID_FILTER_ENHANCED quirk(filter: 1, enhanced_filter: 1, super_filter: 0).
|
||||
This is an extension to the DDR_CAP_AXI_ID_FILTER quirk which permits
|
||||
counting the number of bytes (as opposed to the number of bursts) from DDR
|
||||
read and write transactions concurrently with another set of data counters.
|
||||
|
||||
* With DDR_CAP_AXI_ID_PORT_CHANNEL_FILTER quirk(filter: 0, enhanced_filter: 0, super_filter: 1).
|
||||
There is a limitation in previous AXI filter, it cannot filter different IDs
|
||||
at the same time as the filter is shared between counters. This quirk is the
|
||||
extension of AXI ID filter. One improvement is that counter 1-3 has their own
|
||||
filter, means that it supports concurrently filter various IDs. Another
|
||||
improvement is that counter 1-3 supports AXI PORT and CHANNEL selection. Support
|
||||
selecting address channel or data channel.
|
||||
|
||||
Filter is defined with 2 configuration registers per counter 1-3.
|
||||
--Counter N MASK COMP register - including AXI_ID and AXI_MASKING.
|
||||
--Counter N MUX CNTL register - including AXI CHANNEL and AXI PORT.
|
||||
|
||||
- 0: address channel
|
||||
- 1: data channel
|
||||
|
||||
PMU in DDR subsystem, only one single port0 exists, so axi_port is reserved
|
||||
which should be 0.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
perf stat -a -e imx8_ddr0/axid-read,axi_mask=0xMMMM,axi_id=0xDDDD,axi_channel=0xH/ cmd
|
||||
perf stat -a -e imx8_ddr0/axid-write,axi_mask=0xMMMM,axi_id=0xDDDD,axi_channel=0xH/ cmd
|
||||
|
||||
.. note::
|
||||
|
||||
axi_channel is inverted in userspace, and it will be reverted in driver
|
||||
automatically. So that users do not need specify axi_channel if want to
|
||||
monitor data channel from DDR transactions, since data channel is more
|
||||
meaningful.
|
||||
|
||||
@@ -19,6 +19,7 @@ Performance monitor support
|
||||
arm_dsu_pmu
|
||||
thunderx2-pmu
|
||||
alibaba_pmu
|
||||
dwc_pcie_pmu
|
||||
nvidia-pmu
|
||||
meson-ddr-pmu
|
||||
cxl
|
||||
|
||||
@@ -130,7 +130,7 @@ When an Arm system boots, it can either have DT information, ACPI tables,
|
||||
or in some very unusual cases, both. If no command line parameters are used,
|
||||
the kernel will try to use DT for device enumeration; if there is no DT
|
||||
present, the kernel will try to use ACPI tables, but only if they are present.
|
||||
In neither is available, the kernel will not boot. If acpi=force is used
|
||||
If neither is available, the kernel will not boot. If acpi=force is used
|
||||
on the command line, the kernel will attempt to use ACPI tables first, but
|
||||
fall back to DT if there are no ACPI tables present. The basic idea is that
|
||||
the kernel will not fail to boot unless it absolutely has no other choice.
|
||||
|
||||
@@ -164,3 +164,75 @@ and should be used to mask the upper bits as needed.
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf/arch/arm64/tests/user-events.c
|
||||
.. _tools/lib/perf/tests/test-evsel.c:
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/perf/tests/test-evsel.c
|
||||
|
||||
Event Counting Threshold
|
||||
==========================================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
FEAT_PMUv3_TH (Armv8.8) permits a PMU counter to increment only on
|
||||
events whose count meets a specified threshold condition. For example if
|
||||
threshold_compare is set to 2 ('Greater than or equal'), and the
|
||||
threshold is set to 2, then the PMU counter will now only increment by
|
||||
when an event would have previously incremented the PMU counter by 2 or
|
||||
more on a single processor cycle.
|
||||
|
||||
To increment by 1 after passing the threshold condition instead of the
|
||||
number of events on that cycle, add the 'threshold_count' option to the
|
||||
commandline.
|
||||
|
||||
How-to
|
||||
------
|
||||
|
||||
These are the parameters for controlling the feature:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Parameter
|
||||
- Description
|
||||
* - threshold
|
||||
- Value to threshold the event by. A value of 0 means that
|
||||
thresholding is disabled and the other parameters have no effect.
|
||||
* - threshold_compare
|
||||
- | Comparison function to use, with the following values supported:
|
||||
|
|
||||
| 0: Not-equal
|
||||
| 1: Equals
|
||||
| 2: Greater-than-or-equal
|
||||
| 3: Less-than
|
||||
* - threshold_count
|
||||
- If this is set, count by 1 after passing the threshold condition
|
||||
instead of the value of the event on this cycle.
|
||||
|
||||
The threshold, threshold_compare and threshold_count values can be
|
||||
provided per event, for example:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
perf stat -e stall_slot/threshold=2,threshold_compare=2/ \
|
||||
-e dtlb_walk/threshold=10,threshold_compare=3,threshold_count/
|
||||
|
||||
In this example the stall_slot event will count by 2 or more on every
|
||||
cycle where 2 or more stalls happen. And dtlb_walk will count by 1 on
|
||||
every cycle where the number of dtlb walks were less than 10.
|
||||
|
||||
The maximum supported threshold value can be read from the caps of each
|
||||
PMU, for example:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
cat /sys/bus/event_source/devices/armv8_pmuv3/caps/threshold_max
|
||||
|
||||
0x000000ff
|
||||
|
||||
If a value higher than this is given, then opening the event will result
|
||||
in an error. The highest possible maximum is 4095, as the config field
|
||||
for threshold is limited to 12 bits, and the Perf tool will refuse to
|
||||
parse higher values.
|
||||
|
||||
If the PMU doesn't support FEAT_PMUv3_TH, then threshold_max will read
|
||||
0, and attempting to set a threshold value will also result in an error.
|
||||
threshold_max will also read as 0 on aarch32 guests, even if the host
|
||||
is running on hardware with the feature.
|
||||
|
||||
@@ -7,27 +7,74 @@ x86 Feature Flags
|
||||
Introduction
|
||||
============
|
||||
|
||||
On x86, flags appearing in /proc/cpuinfo have an X86_FEATURE definition
|
||||
in arch/x86/include/asm/cpufeatures.h. If the kernel cares about a feature
|
||||
or KVM want to expose the feature to a KVM guest, it can and should have
|
||||
an X86_FEATURE_* defined. These flags represent hardware features as
|
||||
well as software features.
|
||||
The list of feature flags in /proc/cpuinfo is not complete and
|
||||
represents an ill-fated attempt from long time ago to put feature flags
|
||||
in an easy to find place for userspace.
|
||||
|
||||
If users want to know if a feature is available on a given system, they
|
||||
try to find the flag in /proc/cpuinfo. If a given flag is present, it
|
||||
means that the kernel supports it and is currently making it available.
|
||||
If such flag represents a hardware feature, it also means that the
|
||||
hardware supports it.
|
||||
However, the amount of feature flags is growing by the CPU generation,
|
||||
leading to unparseable and unwieldy /proc/cpuinfo.
|
||||
|
||||
What is more, those feature flags do not even need to be in that file
|
||||
because userspace doesn't care about them - glibc et al already use
|
||||
CPUID to find out what the target machine supports and what not.
|
||||
|
||||
And even if it doesn't show a particular feature flag - although the CPU
|
||||
still does have support for the respective hardware functionality and
|
||||
said CPU supports CPUID faulting - userspace can simply probe for the
|
||||
feature and figure out if it is supported or not, regardless of whether
|
||||
it is being advertised somewhere.
|
||||
|
||||
Furthermore, those flag strings become an ABI the moment they appear
|
||||
there and maintaining them forever when nothing even uses them is a lot
|
||||
of wasted effort.
|
||||
|
||||
So, the current use of /proc/cpuinfo is to show features which the
|
||||
kernel has *enabled* and *supports*. As in: the CPUID feature flag is
|
||||
there, there's an additional setup which the kernel has done while
|
||||
booting and the functionality is ready to use. A perfect example for
|
||||
that is "user_shstk" where additional code enablement is present in the
|
||||
kernel to support shadow stack for user programs.
|
||||
|
||||
So, if users want to know if a feature is available on a given system,
|
||||
they try to find the flag in /proc/cpuinfo. If a given flag is present,
|
||||
it means that
|
||||
|
||||
* the kernel knows about the feature enough to have an X86_FEATURE bit
|
||||
|
||||
* the kernel supports it and is currently making it available either to
|
||||
userspace or some other part of the kernel
|
||||
|
||||
* if the flag represents a hardware feature the hardware supports it.
|
||||
|
||||
The absence of a flag in /proc/cpuinfo by itself means almost nothing to
|
||||
an end user.
|
||||
|
||||
On the one hand, a feature like "vaes" might be fully available to user
|
||||
applications on a kernel that has not defined X86_FEATURE_VAES and thus
|
||||
there is no "vaes" in /proc/cpuinfo.
|
||||
|
||||
On the other hand, a new kernel running on non-VAES hardware would also
|
||||
have no "vaes" in /proc/cpuinfo. There's no way for an application or
|
||||
user to tell the difference.
|
||||
|
||||
The end result is that the flags field in /proc/cpuinfo is marginally
|
||||
useful for kernel debugging, but not really for anything else.
|
||||
Applications should instead use things like the glibc facilities for
|
||||
querying CPU support. Users should rely on tools like
|
||||
tools/arch/x86/kcpuid and cpuid(1).
|
||||
|
||||
Regarding implementation, flags appearing in /proc/cpuinfo have an
|
||||
X86_FEATURE definition in arch/x86/include/asm/cpufeatures.h. These flags
|
||||
represent hardware features as well as software features.
|
||||
|
||||
If the kernel cares about a feature or KVM want to expose the feature to
|
||||
a KVM guest, it should only then expose it to the guest when the guest
|
||||
needs to parse /proc/cpuinfo. Which, as mentioned above, is highly
|
||||
unlikely. KVM can synthesize the CPUID bit and the KVM guest can simply
|
||||
query CPUID and figure out what the hypervisor supports and what not. As
|
||||
already stated, /proc/cpuinfo is not a dumping ground for useless
|
||||
feature flags.
|
||||
|
||||
If the expected flag does not appear in /proc/cpuinfo, things are murkier.
|
||||
Users need to find out the reason why the flag is missing and find the way
|
||||
how to enable it, which is not always easy. There are several factors that
|
||||
can explain missing flags: the expected feature failed to enable, the feature
|
||||
is missing in hardware, platform firmware did not enable it, the feature is
|
||||
disabled at build or run time, an old kernel is in use, or the kernel does
|
||||
not support the feature and thus has not enabled it. In general, /proc/cpuinfo
|
||||
shows features which the kernel supports. For a full list of CPUID flags
|
||||
which the CPU supports, use tools/arch/x86/kcpuid.
|
||||
|
||||
How are feature flags created?
|
||||
==============================
|
||||
|
||||
@@ -81,11 +81,9 @@ this protection comes at a cost:
|
||||
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.
|
||||
b. Percpu TSS is mapped into the user page tables to allow SYSCALL64 path
|
||||
to work under PTI. This doesn't have a direct runtime cost but it can
|
||||
be argued it opens certain timing attack scenarios.
|
||||
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
|
||||
@@ -167,7 +165,7 @@ 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.
|
||||
in the 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.
|
||||
|
||||
@@ -27,6 +27,9 @@ properties:
|
||||
- fsl,imx8mq-ddr-pmu
|
||||
- fsl,imx8mp-ddr-pmu
|
||||
- const: fsl,imx8m-ddr-pmu
|
||||
- items:
|
||||
- const: fsl,imx8dxl-ddr-pmu
|
||||
- const: fsl,imx8-ddr-pmu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -113,6 +113,7 @@ to ReStructured Text format, or are simply too old.
|
||||
:maxdepth: 1
|
||||
|
||||
staging/index
|
||||
RAS/ras
|
||||
|
||||
|
||||
Translations
|
||||
|
||||
@@ -101,6 +101,24 @@ features that make lock debugging easier and faster:
|
||||
- Detects multi-task circular deadlocks and prints out all affected
|
||||
locks and tasks (and only those tasks).
|
||||
|
||||
Mutexes - and most other sleeping locks like rwsems - do not provide an
|
||||
implicit reference for the memory they occupy, which reference is released
|
||||
with mutex_unlock().
|
||||
|
||||
[ This is in contrast with spin_unlock() [or completion_done()], which
|
||||
APIs can be used to guarantee that the memory is not touched by the
|
||||
lock implementation after spin_unlock()/completion_done() releases
|
||||
the lock. ]
|
||||
|
||||
mutex_unlock() may access the mutex structure even after it has internally
|
||||
released the lock already - so it's not safe for another context to
|
||||
acquire the mutex and assume that the mutex_unlock() context is not using
|
||||
the structure anymore.
|
||||
|
||||
The mutex user must ensure that the mutex is not destroyed while a
|
||||
release operation is still in progress - in other words, callers of
|
||||
mutex_unlock() must ensure that the mutex stays alive until mutex_unlock()
|
||||
has returned.
|
||||
|
||||
Interfaces
|
||||
----------
|
||||
|
||||
@@ -349,6 +349,10 @@ Code Seq# Include File Comments
|
||||
<mailto:vgo@ratio.de>
|
||||
0xB1 00-1F PPPoX
|
||||
<mailto:mostrows@styx.uwaterloo.ca>
|
||||
0xB2 00 arch/powerpc/include/uapi/asm/papr-vpd.h powerpc/pseries VPD API
|
||||
<mailto:linuxppc-dev>
|
||||
0xB2 01-02 arch/powerpc/include/uapi/asm/papr-sysparm.h powerpc/pseries system parameter API
|
||||
<mailto:linuxppc-dev>
|
||||
0xB3 00 linux/mmc/ioctl.h
|
||||
0xB4 00-0F linux/gpio.h <mailto:linux-gpio@vger.kernel.org>
|
||||
0xB5 00-0F uapi/linux/rpmsg.h <mailto:linux-remoteproc@vger.kernel.org>
|
||||
|
||||
+11
-4
@@ -12259,21 +12259,21 @@ S: Orphan
|
||||
F: arch/powerpc/platforms/40x/
|
||||
F: arch/powerpc/platforms/44x/
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
|
||||
LINUX FOR POWERPC EMBEDDED PPC85XX
|
||||
M: Scott Wood <oss@buserror.net>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Odd fixes
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git
|
||||
F: Documentation/devicetree/bindings/cache/freescale-l2cache.txt
|
||||
F: Documentation/devicetree/bindings/powerpc/fsl/
|
||||
F: arch/powerpc/platforms/83xx/
|
||||
F: arch/powerpc/platforms/85xx/
|
||||
|
||||
LINUX FOR POWERPC EMBEDDED PPC8XX
|
||||
LINUX FOR POWERPC EMBEDDED PPC8XX AND PPC83XX
|
||||
M: Christophe Leroy <christophe.leroy@csgroup.eu>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Maintained
|
||||
F: arch/powerpc/platforms/8xx/
|
||||
F: arch/powerpc/platforms/83xx/
|
||||
|
||||
LINUX KERNEL DUMP TEST MODULE (LKDTM)
|
||||
M: Kees Cook <keescook@chromium.org>
|
||||
@@ -12431,7 +12431,7 @@ S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
|
||||
F: Documentation/locking/
|
||||
F: arch/*/include/asm/spinlock*.h
|
||||
F: include/linux/lockdep.h
|
||||
F: include/linux/lockdep*.h
|
||||
F: include/linux/mutex*.h
|
||||
F: include/linux/rwlock*.h
|
||||
F: include/linux/rwsem*.h
|
||||
@@ -21035,6 +21035,13 @@ L: linux-mmc@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/mmc/host/dw_mmc*
|
||||
|
||||
SYNOPSYS DESIGNWARE PCIE PMU DRIVER
|
||||
M: Shuai Xue <xueshuai@linux.alibaba.com>
|
||||
M: Jing Zhang <renyu.zj@linux.alibaba.com>
|
||||
S: Supported
|
||||
F: Documentation/admin-guide/perf/dwc_pcie_pmu.rst
|
||||
F: drivers/perf/dwc_pcie_pmu.c
|
||||
|
||||
SYNOPSYS HSDK RESET CONTROLLER DRIVER
|
||||
M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
|
||||
S: Supported
|
||||
|
||||
@@ -268,10 +268,8 @@ static inline void armv6pmu_write_counter(struct perf_event *event, u64 value)
|
||||
|
||||
static void armv6pmu_enable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long val, mask, evt, flags;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
unsigned long val, mask, evt;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
if (ARMV6_CYCLE_COUNTER == idx) {
|
||||
@@ -294,12 +292,10 @@ static void armv6pmu_enable_event(struct perf_event *event)
|
||||
* Mask out the current event and set the counter to count the event
|
||||
* that we're interested in.
|
||||
*/
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = armv6_pmcr_read();
|
||||
val &= ~mask;
|
||||
val |= evt;
|
||||
armv6_pmcr_write(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
@@ -362,26 +358,20 @@ armv6pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
|
||||
static void armv6pmu_start(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long flags, val;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
unsigned long val;
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = armv6_pmcr_read();
|
||||
val |= ARMV6_PMCR_ENABLE;
|
||||
armv6_pmcr_write(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void armv6pmu_stop(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long flags, val;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
unsigned long val;
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = armv6_pmcr_read();
|
||||
val &= ~ARMV6_PMCR_ENABLE;
|
||||
armv6_pmcr_write(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -419,10 +409,8 @@ static void armv6pmu_clear_event_idx(struct pmu_hw_events *cpuc,
|
||||
|
||||
static void armv6pmu_disable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long val, mask, evt, flags;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
unsigned long val, mask, evt;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
if (ARMV6_CYCLE_COUNTER == idx) {
|
||||
@@ -444,20 +432,16 @@ static void armv6pmu_disable_event(struct perf_event *event)
|
||||
* of ETM bus signal assertion cycles. The external reporting should
|
||||
* be disabled and so this should never increment.
|
||||
*/
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = armv6_pmcr_read();
|
||||
val &= ~mask;
|
||||
val |= evt;
|
||||
armv6_pmcr_write(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void armv6mpcore_pmu_disable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long val, mask, flags, evt = 0;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
unsigned long val, mask, evt = 0;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
if (ARMV6_CYCLE_COUNTER == idx) {
|
||||
@@ -475,12 +459,10 @@ static void armv6mpcore_pmu_disable_event(struct perf_event *event)
|
||||
* Unlike UP ARMv6, we don't have a way of stopping the counters. We
|
||||
* simply disable the interrupt reporting.
|
||||
*/
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = armv6_pmcr_read();
|
||||
val &= ~mask;
|
||||
val |= evt;
|
||||
armv6_pmcr_write(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static int armv6_map_event(struct perf_event *event)
|
||||
|
||||
@@ -870,10 +870,8 @@ static void armv7_pmnc_dump_regs(struct arm_pmu *cpu_pmu)
|
||||
|
||||
static void armv7pmu_enable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
|
||||
@@ -886,7 +884,6 @@ static void armv7pmu_enable_event(struct perf_event *event)
|
||||
* Enable counter and interrupt, and set the counter to count
|
||||
* the event that we're interested in.
|
||||
*/
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
|
||||
/*
|
||||
* Disable counter
|
||||
@@ -910,16 +907,12 @@ static void armv7pmu_enable_event(struct perf_event *event)
|
||||
* Enable counter
|
||||
*/
|
||||
armv7_pmnc_enable_counter(idx);
|
||||
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void armv7pmu_disable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
|
||||
@@ -931,7 +924,6 @@ static void armv7pmu_disable_event(struct perf_event *event)
|
||||
/*
|
||||
* Disable counter and interrupt
|
||||
*/
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
|
||||
/*
|
||||
* Disable counter
|
||||
@@ -942,8 +934,6 @@ static void armv7pmu_disable_event(struct perf_event *event)
|
||||
* Disable interrupt for this counter
|
||||
*/
|
||||
armv7_pmnc_disable_intens(idx);
|
||||
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t armv7pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
@@ -1009,24 +999,14 @@ static irqreturn_t armv7pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
|
||||
static void armv7pmu_start(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
/* Enable all counters */
|
||||
armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void armv7pmu_stop(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
/* Disable all counters */
|
||||
armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc,
|
||||
@@ -1072,8 +1052,10 @@ static int armv7pmu_set_event_filter(struct hw_perf_event *event,
|
||||
{
|
||||
unsigned long config_base = 0;
|
||||
|
||||
if (attr->exclude_idle)
|
||||
return -EPERM;
|
||||
if (attr->exclude_idle) {
|
||||
pr_debug("ARM performance counters do not support mode exclusion\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (attr->exclude_user)
|
||||
config_base |= ARMV7_EXCLUDE_USER;
|
||||
if (attr->exclude_kernel)
|
||||
@@ -1492,14 +1474,10 @@ static void krait_clearpmu(u32 config_base)
|
||||
|
||||
static void krait_pmu_disable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int idx = hwc->idx;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
|
||||
/* Disable counter and interrupt */
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
|
||||
/* Disable counter */
|
||||
armv7_pmnc_disable_counter(idx);
|
||||
@@ -1512,23 +1490,17 @@ static void krait_pmu_disable_event(struct perf_event *event)
|
||||
|
||||
/* Disable interrupt for this counter */
|
||||
armv7_pmnc_disable_intens(idx);
|
||||
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void krait_pmu_enable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int idx = hwc->idx;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
|
||||
/*
|
||||
* Enable counter and interrupt, and set the counter to count
|
||||
* the event that we're interested in.
|
||||
*/
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
|
||||
/* Disable counter */
|
||||
armv7_pmnc_disable_counter(idx);
|
||||
@@ -1548,8 +1520,6 @@ static void krait_pmu_enable_event(struct perf_event *event)
|
||||
|
||||
/* Enable counter */
|
||||
armv7_pmnc_enable_counter(idx);
|
||||
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void krait_pmu_reset(void *info)
|
||||
@@ -1825,14 +1795,10 @@ static void scorpion_clearpmu(u32 config_base)
|
||||
|
||||
static void scorpion_pmu_disable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int idx = hwc->idx;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
|
||||
/* Disable counter and interrupt */
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
|
||||
/* Disable counter */
|
||||
armv7_pmnc_disable_counter(idx);
|
||||
@@ -1845,23 +1811,17 @@ static void scorpion_pmu_disable_event(struct perf_event *event)
|
||||
|
||||
/* Disable interrupt for this counter */
|
||||
armv7_pmnc_disable_intens(idx);
|
||||
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void scorpion_pmu_enable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
int idx = hwc->idx;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
|
||||
/*
|
||||
* Enable counter and interrupt, and set the counter to count
|
||||
* the event that we're interested in.
|
||||
*/
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
|
||||
/* Disable counter */
|
||||
armv7_pmnc_disable_counter(idx);
|
||||
@@ -1881,8 +1841,6 @@ static void scorpion_pmu_enable_event(struct perf_event *event)
|
||||
|
||||
/* Enable counter */
|
||||
armv7_pmnc_enable_counter(idx);
|
||||
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void scorpion_pmu_reset(void *info)
|
||||
|
||||
@@ -203,10 +203,8 @@ xscale1pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
|
||||
static void xscale1pmu_enable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long val, mask, evt, flags;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
unsigned long val, mask, evt;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
switch (idx) {
|
||||
@@ -229,20 +227,16 @@ static void xscale1pmu_enable_event(struct perf_event *event)
|
||||
return;
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = xscale1pmu_read_pmnc();
|
||||
val &= ~mask;
|
||||
val |= evt;
|
||||
xscale1pmu_write_pmnc(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void xscale1pmu_disable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long val, mask, evt, flags;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
unsigned long val, mask, evt;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
switch (idx) {
|
||||
@@ -263,12 +257,10 @@ static void xscale1pmu_disable_event(struct perf_event *event)
|
||||
return;
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = xscale1pmu_read_pmnc();
|
||||
val &= ~mask;
|
||||
val |= evt;
|
||||
xscale1pmu_write_pmnc(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -300,26 +292,20 @@ static void xscalepmu_clear_event_idx(struct pmu_hw_events *cpuc,
|
||||
|
||||
static void xscale1pmu_start(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long flags, val;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
unsigned long val;
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = xscale1pmu_read_pmnc();
|
||||
val |= XSCALE_PMU_ENABLE;
|
||||
xscale1pmu_write_pmnc(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void xscale1pmu_stop(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long flags, val;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
unsigned long val;
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = xscale1pmu_read_pmnc();
|
||||
val &= ~XSCALE_PMU_ENABLE;
|
||||
xscale1pmu_write_pmnc(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static inline u64 xscale1pmu_read_counter(struct perf_event *event)
|
||||
@@ -549,10 +535,8 @@ xscale2pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
||||
|
||||
static void xscale2pmu_enable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags, ien, evtsel;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
unsigned long ien, evtsel;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
ien = xscale2pmu_read_int_enable();
|
||||
@@ -587,18 +571,14 @@ static void xscale2pmu_enable_event(struct perf_event *event)
|
||||
return;
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
xscale2pmu_write_event_select(evtsel);
|
||||
xscale2pmu_write_int_enable(ien);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void xscale2pmu_disable_event(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags, ien, evtsel, of_flags;
|
||||
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
|
||||
unsigned long ien, evtsel, of_flags;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
int idx = hwc->idx;
|
||||
|
||||
ien = xscale2pmu_read_int_enable();
|
||||
@@ -638,11 +618,9 @@ static void xscale2pmu_disable_event(struct perf_event *event)
|
||||
return;
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
xscale2pmu_write_event_select(evtsel);
|
||||
xscale2pmu_write_int_enable(ien);
|
||||
xscale2pmu_write_overflow_flags(of_flags);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -663,26 +641,20 @@ out:
|
||||
|
||||
static void xscale2pmu_start(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long flags, val;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
unsigned long val;
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
|
||||
val |= XSCALE_PMU_ENABLE;
|
||||
xscale2pmu_write_pmnc(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static void xscale2pmu_stop(struct arm_pmu *cpu_pmu)
|
||||
{
|
||||
unsigned long flags, val;
|
||||
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
||||
unsigned long val;
|
||||
|
||||
raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
||||
val = xscale2pmu_read_pmnc();
|
||||
val &= ~XSCALE_PMU_ENABLE;
|
||||
xscale2pmu_write_pmnc(val);
|
||||
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
||||
}
|
||||
|
||||
static inline u64 xscale2pmu_read_counter(struct perf_event *event)
|
||||
|
||||
+1
-1
@@ -1549,7 +1549,7 @@ config ARCH_FORCE_MAX_ORDER
|
||||
Don't change if unsure.
|
||||
|
||||
config UNMAP_KERNEL_AT_EL0
|
||||
bool "Unmap kernel when running in userspace (aka \"KAISER\")" if EXPERT
|
||||
bool "Unmap kernel when running in userspace (KPTI)" if EXPERT
|
||||
default y
|
||||
help
|
||||
Speculation attacks against some high-performance processors can
|
||||
|
||||
+1
-1
@@ -207,7 +207,7 @@ endif
|
||||
endif
|
||||
|
||||
vdso-install-y += arch/arm64/kernel/vdso/vdso.so.dbg
|
||||
vdso-install-$(CONFIG_COMPAT_VDSO) += arch/arm64/kernel/vdso32/vdso.so.dbg:vdso32.so
|
||||
vdso-install-$(CONFIG_COMPAT_VDSO) += arch/arm64/kernel/vdso32/vdso32.so.dbg
|
||||
|
||||
include $(srctree)/scripts/Makefile.defconf
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ EFI_ZBOOT_BFD_TARGET := elf64-littleaarch64
|
||||
EFI_ZBOOT_MACH_TYPE := ARM64
|
||||
EFI_ZBOOT_FORWARD_CFI := $(CONFIG_ARM64_BTI_KERNEL)
|
||||
|
||||
EFI_ZBOOT_OBJCOPY_FLAGS = --add-symbol zboot_code_size=0x$(shell \
|
||||
EFI_ZBOOT_OBJCOPY_FLAGS = --add-symbol zboot_code_size=0x$$( \
|
||||
$(NM) vmlinux|grep _kernel_codesize|cut -d' ' -f1)
|
||||
|
||||
include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
# $3 - kernel map file
|
||||
# $4 - default install path (blank if root directory)
|
||||
|
||||
if [ "$(basename $2)" = "Image.gz" ]; then
|
||||
if [ "$(basename $2)" = "Image.gz" ] || [ "$(basename $2)" = "vmlinuz.efi" ]
|
||||
then
|
||||
# Compressed install
|
||||
echo "Installing compressed kernel"
|
||||
base=vmlinuz
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#ifndef __ASM_ASSEMBLER_H
|
||||
#define __ASM_ASSEMBLER_H
|
||||
|
||||
#include <asm-generic/export.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/asm-bug.h>
|
||||
|
||||
@@ -58,7 +58,6 @@ static inline unsigned int arch_slab_minalign(void)
|
||||
#define CTR_L1IP(ctr) SYS_FIELD_GET(CTR_EL0, L1Ip, ctr)
|
||||
|
||||
#define ICACHEF_ALIASING 0
|
||||
#define ICACHEF_VPIPT 1
|
||||
extern unsigned long __icache_flags;
|
||||
|
||||
/*
|
||||
@@ -70,11 +69,6 @@ static inline int icache_is_aliasing(void)
|
||||
return test_bit(ICACHEF_ALIASING, &__icache_flags);
|
||||
}
|
||||
|
||||
static __always_inline int icache_is_vpipt(void)
|
||||
{
|
||||
return test_bit(ICACHEF_VPIPT, &__icache_flags);
|
||||
}
|
||||
|
||||
static inline u32 cache_type_cwg(void)
|
||||
{
|
||||
return SYS_FIELD_GET(CTR_EL0, CWG, read_cpuid_cachetype());
|
||||
|
||||
@@ -617,6 +617,7 @@ static inline bool id_aa64pfr1_mte(u64 pfr1)
|
||||
return val >= ID_AA64PFR1_EL1_MTE_MTE2;
|
||||
}
|
||||
|
||||
void __init setup_boot_cpu_features(void);
|
||||
void __init setup_system_features(void);
|
||||
void __init setup_user_features(void);
|
||||
|
||||
@@ -819,6 +820,11 @@ static inline bool system_supports_tlb_range(void)
|
||||
return alternative_has_cap_unlikely(ARM64_HAS_TLB_RANGE);
|
||||
}
|
||||
|
||||
static inline bool system_supports_lpa2(void)
|
||||
{
|
||||
return cpus_have_final_cap(ARM64_HAS_LPA2);
|
||||
}
|
||||
|
||||
int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
|
||||
bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
|
||||
|
||||
|
||||
@@ -242,14 +242,6 @@
|
||||
| (\nx << 5)
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Zero the entire ZA array
|
||||
* ZERO ZA
|
||||
*/
|
||||
.macro zero_za
|
||||
.inst 0xc00800ff
|
||||
.endm
|
||||
|
||||
.macro __for from:req, to:req
|
||||
.if (\from) == (\to)
|
||||
_for__body %\from
|
||||
|
||||
@@ -37,27 +37,12 @@
|
||||
|
||||
|
||||
/*
|
||||
* If KASLR is enabled, then an offset K is added to the kernel address
|
||||
* space. The bottom 21 bits of this offset are zero to guarantee 2MB
|
||||
* alignment for PA and VA.
|
||||
*
|
||||
* For each pagetable level of the swapper, we know that the shift will
|
||||
* be larger than 21 (for the 4KB granule case we use section maps thus
|
||||
* the smallest shift is actually 30) thus there is the possibility that
|
||||
* KASLR can increase the number of pagetable entries by 1, so we make
|
||||
* room for this extra entry.
|
||||
*
|
||||
* Note KASLR cannot increase the number of required entries for a level
|
||||
* by more than one because it increments both the virtual start and end
|
||||
* addresses equally (the extra entry comes from the case where the end
|
||||
* address is just pushed over a boundary and the start address isn't).
|
||||
* A relocatable kernel may execute from an address that differs from the one at
|
||||
* which it was linked. In the worst case, its runtime placement may intersect
|
||||
* with two adjacent PGDIR entries, which means that an additional page table
|
||||
* may be needed at each subordinate level.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_RANDOMIZE_BASE
|
||||
#define EARLY_KASLR (1)
|
||||
#else
|
||||
#define EARLY_KASLR (0)
|
||||
#endif
|
||||
#define EXTRA_PAGE __is_defined(CONFIG_RELOCATABLE)
|
||||
|
||||
#define SPAN_NR_ENTRIES(vstart, vend, shift) \
|
||||
((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1)
|
||||
@@ -83,7 +68,7 @@
|
||||
+ EARLY_PGDS((vstart), (vend), add) /* each PGDIR needs a next level page table */ \
|
||||
+ EARLY_PUDS((vstart), (vend), add) /* each PUD needs a next level page table */ \
|
||||
+ EARLY_PMDS((vstart), (vend), add)) /* each PMD needs a next level page table */
|
||||
#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end, EARLY_KASLR))
|
||||
#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end, EXTRA_PAGE))
|
||||
|
||||
/* the initial ID map may need two extra pages if it needs to be extended */
|
||||
#if VA_BITS < 48
|
||||
|
||||
@@ -243,13 +243,6 @@ static inline size_t __invalidate_icache_max_range(void)
|
||||
|
||||
static inline void __invalidate_icache_guest_page(void *va, size_t size)
|
||||
{
|
||||
/*
|
||||
* VPIPT I-cache maintenance must be done from EL2. See comment in the
|
||||
* nVHE flavor of __kvm_tlb_flush_vmid_ipa().
|
||||
*/
|
||||
if (icache_is_vpipt() && read_sysreg(CurrentEL) != CurrentEL_EL2)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Blow the whole I-cache if it is aliasing (i.e. VIPT) or the
|
||||
* invalidation range exceeds our arbitrary limit on invadations by
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#define KVM_PGTABLE_MIN_BLOCK_LEVEL 2U
|
||||
#endif
|
||||
|
||||
#define kvm_lpa2_is_enabled() false
|
||||
|
||||
static inline u64 kvm_get_parange(u64 mmfr0)
|
||||
{
|
||||
u64 parange = cpuid_feature_extract_unsigned_field(mmfr0,
|
||||
|
||||
@@ -182,6 +182,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <asm/boot.h>
|
||||
#include <asm/bug.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
#if VA_BITS > 48
|
||||
extern u64 vabits_actual;
|
||||
@@ -193,15 +194,12 @@ extern s64 memstart_addr;
|
||||
/* PHYS_OFFSET - the physical address of the start of memory. */
|
||||
#define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; })
|
||||
|
||||
/* the virtual base of the kernel image */
|
||||
extern u64 kimage_vaddr;
|
||||
|
||||
/* the offset between the kernel virtual and physical mappings */
|
||||
extern u64 kimage_voffset;
|
||||
|
||||
static inline unsigned long kaslr_offset(void)
|
||||
{
|
||||
return kimage_vaddr - KIMAGE_VADDR;
|
||||
return (u64)&_text - KIMAGE_VADDR;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RANDOMIZE_BASE
|
||||
@@ -407,6 +405,5 @@ void dump_mem_limit(void);
|
||||
#define INIT_MEMBLOCK_MEMORY_REGIONS (INIT_MEMBLOCK_REGIONS * 8)
|
||||
#endif
|
||||
|
||||
#include <asm-generic/memory_model.h>
|
||||
|
||||
#endif /* __ASM_MEMORY_H */
|
||||
|
||||
@@ -71,6 +71,8 @@ extern bool arm64_use_ng_mappings;
|
||||
#define PTE_MAYBE_NG (arm64_use_ng_mappings ? PTE_NG : 0)
|
||||
#define PMD_MAYBE_NG (arm64_use_ng_mappings ? PMD_SECT_NG : 0)
|
||||
|
||||
#define lpa2_is_enabled() false
|
||||
|
||||
/*
|
||||
* If we have userspace only BTI we don't want to mark kernel pages
|
||||
* guarded even if the system does support BTI.
|
||||
|
||||
@@ -167,6 +167,9 @@ struct thread_struct {
|
||||
unsigned long fault_address; /* fault info */
|
||||
unsigned long fault_code; /* ESR_EL1 value */
|
||||
struct debug_info debug; /* debugging */
|
||||
|
||||
struct user_fpsimd_state kernel_fpsimd_state;
|
||||
unsigned int kernel_fpsimd_cpu;
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||
struct ptrauth_keys_user keys_user;
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
DECLARE_PER_CPU(bool, fpsimd_context_busy);
|
||||
|
||||
#ifdef CONFIG_KERNEL_MODE_NEON
|
||||
|
||||
/*
|
||||
@@ -28,17 +26,10 @@ static __must_check inline bool may_use_simd(void)
|
||||
/*
|
||||
* We must make sure that the SVE has been initialized properly
|
||||
* before using the SIMD in kernel.
|
||||
* fpsimd_context_busy is only set while preemption is disabled,
|
||||
* and is clear whenever preemption is enabled. Since
|
||||
* this_cpu_read() is atomic w.r.t. preemption, fpsimd_context_busy
|
||||
* cannot change under our feet -- if it's set we cannot be
|
||||
* migrated, and if it's clear we cannot be migrated to a CPU
|
||||
* where it is set.
|
||||
*/
|
||||
return !WARN_ON(!system_capabilities_finalized()) &&
|
||||
system_supports_fpsimd() &&
|
||||
!in_hardirq() && !irqs_disabled() && !in_nmi() &&
|
||||
!this_cpu_read(fpsimd_context_busy);
|
||||
!in_hardirq() && !irqs_disabled() && !in_nmi();
|
||||
}
|
||||
|
||||
#else /* ! CONFIG_KERNEL_MODE_NEON */
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#ifndef __ASM_STACKTRACE_COMMON_H
|
||||
#define __ASM_STACKTRACE_COMMON_H
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct stack_info {
|
||||
@@ -23,12 +22,6 @@ struct stack_info {
|
||||
* @fp: The fp value in the frame record (or the real fp)
|
||||
* @pc: The lr value in the frame record (or the real lr)
|
||||
*
|
||||
* @kr_cur: When KRETPROBES is selected, holds the kretprobe instance
|
||||
* associated with the most recently encountered replacement lr
|
||||
* value.
|
||||
*
|
||||
* @task: The task being unwound.
|
||||
*
|
||||
* @stack: The stack currently being unwound.
|
||||
* @stacks: An array of stacks which can be unwound.
|
||||
* @nr_stacks: The number of stacks in @stacks.
|
||||
@@ -36,10 +29,6 @@ struct stack_info {
|
||||
struct unwind_state {
|
||||
unsigned long fp;
|
||||
unsigned long pc;
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
struct llist_node *kr_cur;
|
||||
#endif
|
||||
struct task_struct *task;
|
||||
|
||||
struct stack_info stack;
|
||||
struct stack_info *stacks;
|
||||
@@ -66,14 +55,8 @@ static inline bool stackinfo_on_stack(const struct stack_info *info,
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void unwind_init_common(struct unwind_state *state,
|
||||
struct task_struct *task)
|
||||
static inline void unwind_init_common(struct unwind_state *state)
|
||||
{
|
||||
state->task = task;
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
state->kr_cur = NULL;
|
||||
#endif
|
||||
|
||||
state->stack = stackinfo_get_unknown();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ static inline void kvm_nvhe_unwind_init(struct unwind_state *state,
|
||||
unsigned long fp,
|
||||
unsigned long pc)
|
||||
{
|
||||
unwind_init_common(state, NULL);
|
||||
unwind_init_common(state);
|
||||
|
||||
state->fp = fp;
|
||||
state->pc = pc;
|
||||
|
||||
@@ -645,6 +645,7 @@
|
||||
#define OP_AT_S1E0W sys_insn(AT_Op0, 0, AT_CRn, 8, 3)
|
||||
#define OP_AT_S1E1RP sys_insn(AT_Op0, 0, AT_CRn, 9, 0)
|
||||
#define OP_AT_S1E1WP sys_insn(AT_Op0, 0, AT_CRn, 9, 1)
|
||||
#define OP_AT_S1E1A sys_insn(AT_Op0, 0, AT_CRn, 9, 2)
|
||||
#define OP_AT_S1E2R sys_insn(AT_Op0, 4, AT_CRn, 8, 0)
|
||||
#define OP_AT_S1E2W sys_insn(AT_Op0, 4, AT_CRn, 8, 1)
|
||||
#define OP_AT_S12E1R sys_insn(AT_Op0, 4, AT_CRn, 8, 4)
|
||||
@@ -781,10 +782,16 @@
|
||||
#define OP_TLBI_VMALLS12E1NXS sys_insn(1, 4, 9, 7, 6)
|
||||
|
||||
/* Misc instructions */
|
||||
#define OP_GCSPUSHX sys_insn(1, 0, 7, 7, 4)
|
||||
#define OP_GCSPOPCX sys_insn(1, 0, 7, 7, 5)
|
||||
#define OP_GCSPOPX sys_insn(1, 0, 7, 7, 6)
|
||||
#define OP_GCSPUSHM sys_insn(1, 3, 7, 7, 0)
|
||||
|
||||
#define OP_BRB_IALL sys_insn(1, 1, 7, 2, 4)
|
||||
#define OP_BRB_INJ sys_insn(1, 1, 7, 2, 5)
|
||||
#define OP_CFP_RCTX sys_insn(1, 3, 7, 3, 4)
|
||||
#define OP_DVP_RCTX sys_insn(1, 3, 7, 3, 5)
|
||||
#define OP_COSP_RCTX sys_insn(1, 3, 7, 3, 6)
|
||||
#define OP_CPP_RCTX sys_insn(1, 3, 7, 3, 7)
|
||||
|
||||
/* Common SCTLR_ELx flags. */
|
||||
@@ -871,10 +878,12 @@
|
||||
|
||||
/* id_aa64mmfr0 */
|
||||
#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN 0x0
|
||||
#define ID_AA64MMFR0_EL1_TGRAN4_LPA2 ID_AA64MMFR0_EL1_TGRAN4_52_BIT
|
||||
#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MAX 0x7
|
||||
#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED_MIN 0x0
|
||||
#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED_MAX 0x7
|
||||
#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MIN 0x1
|
||||
#define ID_AA64MMFR0_EL1_TGRAN16_LPA2 ID_AA64MMFR0_EL1_TGRAN16_52_BIT
|
||||
#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MAX 0xf
|
||||
|
||||
#define ARM64_MIN_PARANGE_BITS 32
|
||||
@@ -882,6 +891,7 @@
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_DEFAULT 0x0
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_NONE 0x1
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MIN 0x2
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2 0x3
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_MAX 0x7
|
||||
|
||||
#ifdef CONFIG_ARM64_PA_BITS_52
|
||||
@@ -892,11 +902,13 @@
|
||||
|
||||
#if defined(CONFIG_ARM64_4K_PAGES)
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_SHIFT ID_AA64MMFR0_EL1_TGRAN4_SHIFT
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_LPA2 ID_AA64MMFR0_EL1_TGRAN4_52_BIT
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MAX
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_2_SHIFT ID_AA64MMFR0_EL1_TGRAN4_2_SHIFT
|
||||
#elif defined(CONFIG_ARM64_16K_PAGES)
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_SHIFT ID_AA64MMFR0_EL1_TGRAN16_SHIFT
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_LPA2 ID_AA64MMFR0_EL1_TGRAN16_52_BIT
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MIN
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED_MAX
|
||||
#define ID_AA64MMFR0_EL1_TGRAN_2_SHIFT ID_AA64MMFR0_EL1_TGRAN16_2_SHIFT
|
||||
@@ -1039,6 +1051,19 @@
|
||||
|
||||
#define PIRx_ELx_PERM(idx, perm) ((perm) << ((idx) * 4))
|
||||
|
||||
/*
|
||||
* Permission Overlay Extension (POE) permission encodings.
|
||||
*/
|
||||
#define POE_NONE UL(0x0)
|
||||
#define POE_R UL(0x1)
|
||||
#define POE_X UL(0x2)
|
||||
#define POE_RX UL(0x3)
|
||||
#define POE_W UL(0x4)
|
||||
#define POE_RW UL(0x5)
|
||||
#define POE_XW UL(0x6)
|
||||
#define POE_RXW UL(0x7)
|
||||
#define POE_MASK UL(0xf)
|
||||
|
||||
#define ARM64_FEATURE_FIELD_BITS 4
|
||||
|
||||
/* Defined for compatibility only, do not add new users. */
|
||||
|
||||
@@ -80,6 +80,7 @@ void arch_setup_new_exec(void);
|
||||
#define TIF_TAGGED_ADDR 26 /* Allow tagged user addresses */
|
||||
#define TIF_SME 27 /* SME in use */
|
||||
#define TIF_SME_VL_INHERIT 28 /* Inherit SME vl_onexec across exec */
|
||||
#define TIF_KERNEL_FPSTATE 29 /* Task is in a kernel mode FPSIMD section */
|
||||
|
||||
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||
|
||||
@@ -22,15 +22,15 @@ static void tlb_flush(struct mmu_gather *tlb);
|
||||
#include <asm-generic/tlb.h>
|
||||
|
||||
/*
|
||||
* get the tlbi levels in arm64. Default value is 0 if more than one
|
||||
* of cleared_* is set or neither is set.
|
||||
* Arm64 doesn't support p4ds now.
|
||||
* get the tlbi levels in arm64. Default value is TLBI_TTL_UNKNOWN if more than
|
||||
* one of cleared_* is set or neither is set - this elides the level hinting to
|
||||
* the hardware.
|
||||
*/
|
||||
static inline int tlb_get_level(struct mmu_gather *tlb)
|
||||
{
|
||||
/* The TTL field is only valid for the leaf entry. */
|
||||
if (tlb->freed_tables)
|
||||
return 0;
|
||||
return TLBI_TTL_UNKNOWN;
|
||||
|
||||
if (tlb->cleared_ptes && !(tlb->cleared_pmds ||
|
||||
tlb->cleared_puds ||
|
||||
@@ -47,7 +47,12 @@ static inline int tlb_get_level(struct mmu_gather *tlb)
|
||||
tlb->cleared_p4ds))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
if (tlb->cleared_p4ds && !(tlb->cleared_ptes ||
|
||||
tlb->cleared_pmds ||
|
||||
tlb->cleared_puds))
|
||||
return 0;
|
||||
|
||||
return TLBI_TTL_UNKNOWN;
|
||||
}
|
||||
|
||||
static inline void tlb_flush(struct mmu_gather *tlb)
|
||||
|
||||
@@ -94,19 +94,22 @@ static inline unsigned long get_trans_granule(void)
|
||||
* When ARMv8.4-TTL exists, TLBI operations take an additional hint for
|
||||
* the level at which the invalidation must take place. If the level is
|
||||
* wrong, no invalidation may take place. In the case where the level
|
||||
* cannot be easily determined, a 0 value for the level parameter will
|
||||
* perform a non-hinted invalidation.
|
||||
* cannot be easily determined, the value TLBI_TTL_UNKNOWN will perform
|
||||
* a non-hinted invalidation. Any provided level outside the hint range
|
||||
* will also cause fall-back to non-hinted invalidation.
|
||||
*
|
||||
* For Stage-2 invalidation, use the level values provided to that effect
|
||||
* in asm/stage2_pgtable.h.
|
||||
*/
|
||||
#define TLBI_TTL_MASK GENMASK_ULL(47, 44)
|
||||
|
||||
#define TLBI_TTL_UNKNOWN INT_MAX
|
||||
|
||||
#define __tlbi_level(op, addr, level) do { \
|
||||
u64 arg = addr; \
|
||||
\
|
||||
if (alternative_has_cap_unlikely(ARM64_HAS_ARMv8_4_TTL) && \
|
||||
level) { \
|
||||
level >= 0 && level <= 3) { \
|
||||
u64 ttl = level & 3; \
|
||||
ttl |= get_trans_granule() << 2; \
|
||||
arg &= ~TLBI_TTL_MASK; \
|
||||
@@ -122,28 +125,34 @@ static inline unsigned long get_trans_granule(void)
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This macro creates a properly formatted VA operand for the TLB RANGE.
|
||||
* The value bit assignments are:
|
||||
* This macro creates a properly formatted VA operand for the TLB RANGE. The
|
||||
* value bit assignments are:
|
||||
*
|
||||
* +----------+------+-------+-------+-------+----------------------+
|
||||
* | ASID | TG | SCALE | NUM | TTL | BADDR |
|
||||
* +-----------------+-------+-------+-------+----------------------+
|
||||
* |63 48|47 46|45 44|43 39|38 37|36 0|
|
||||
*
|
||||
* The address range is determined by below formula:
|
||||
* [BADDR, BADDR + (NUM + 1) * 2^(5*SCALE + 1) * PAGESIZE)
|
||||
* The address range is determined by below formula: [BADDR, BADDR + (NUM + 1) *
|
||||
* 2^(5*SCALE + 1) * PAGESIZE)
|
||||
*
|
||||
* Note that the first argument, baddr, is pre-shifted; If LPA2 is in use, BADDR
|
||||
* holds addr[52:16]. Else BADDR holds page number. See for example ARM DDI
|
||||
* 0487J.a section C5.5.60 "TLBI VAE1IS, TLBI VAE1ISNXS, TLB Invalidate by VA,
|
||||
* EL1, Inner Shareable".
|
||||
*
|
||||
*/
|
||||
#define __TLBI_VADDR_RANGE(addr, asid, scale, num, ttl) \
|
||||
({ \
|
||||
unsigned long __ta = (addr) >> PAGE_SHIFT; \
|
||||
__ta &= GENMASK_ULL(36, 0); \
|
||||
__ta |= (unsigned long)(ttl) << 37; \
|
||||
__ta |= (unsigned long)(num) << 39; \
|
||||
__ta |= (unsigned long)(scale) << 44; \
|
||||
__ta |= get_trans_granule() << 46; \
|
||||
__ta |= (unsigned long)(asid) << 48; \
|
||||
__ta; \
|
||||
#define __TLBI_VADDR_RANGE(baddr, asid, scale, num, ttl) \
|
||||
({ \
|
||||
unsigned long __ta = (baddr); \
|
||||
unsigned long __ttl = (ttl >= 1 && ttl <= 3) ? ttl : 0; \
|
||||
__ta &= GENMASK_ULL(36, 0); \
|
||||
__ta |= __ttl << 37; \
|
||||
__ta |= (unsigned long)(num) << 39; \
|
||||
__ta |= (unsigned long)(scale) << 44; \
|
||||
__ta |= get_trans_granule() << 46; \
|
||||
__ta |= (unsigned long)(asid) << 48; \
|
||||
__ta; \
|
||||
})
|
||||
|
||||
/* These macros are used by the TLBI RANGE feature. */
|
||||
@@ -216,12 +225,16 @@ static inline unsigned long get_trans_granule(void)
|
||||
* CPUs, ensuring that any walk-cache entries associated with the
|
||||
* translation are also invalidated.
|
||||
*
|
||||
* __flush_tlb_range(vma, start, end, stride, last_level)
|
||||
* __flush_tlb_range(vma, start, end, stride, last_level, tlb_level)
|
||||
* Invalidate the virtual-address range '[start, end)' on all
|
||||
* CPUs for the user address space corresponding to 'vma->mm'.
|
||||
* The invalidation operations are issued at a granularity
|
||||
* determined by 'stride' and only affect any walk-cache entries
|
||||
* if 'last_level' is equal to false.
|
||||
* if 'last_level' is equal to false. tlb_level is the level at
|
||||
* which the invalidation must take place. If the level is wrong,
|
||||
* no invalidation may take place. In the case where the level
|
||||
* cannot be easily determined, the value TLBI_TTL_UNKNOWN will
|
||||
* perform a non-hinted invalidation.
|
||||
*
|
||||
*
|
||||
* Finally, take a look at asm/tlb.h to see how tlb_flush() is implemented
|
||||
@@ -345,34 +358,44 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
|
||||
* @tlb_level: Translation Table level hint, if known
|
||||
* @tlbi_user: If 'true', call an additional __tlbi_user()
|
||||
* (typically for user ASIDs). 'flase' for IPA instructions
|
||||
* @lpa2: If 'true', the lpa2 scheme is used as set out below
|
||||
*
|
||||
* When the CPU does not support TLB range operations, flush the TLB
|
||||
* entries one by one at the granularity of 'stride'. If the TLB
|
||||
* range ops are supported, then:
|
||||
*
|
||||
* 1. If 'pages' is odd, flush the first page through non-range
|
||||
* operations;
|
||||
* 1. If FEAT_LPA2 is in use, the start address of a range operation must be
|
||||
* 64KB aligned, so flush pages one by one until the alignment is reached
|
||||
* using the non-range operations. This step is skipped if LPA2 is not in
|
||||
* use.
|
||||
*
|
||||
* 2. For remaining pages: the minimum range granularity is decided
|
||||
* by 'scale', so multiple range TLBI operations may be required.
|
||||
* Start from scale = 0, flush the corresponding number of pages
|
||||
* ((num+1)*2^(5*scale+1) starting from 'addr'), then increase it
|
||||
* until no pages left.
|
||||
* 2. The minimum range granularity is decided by 'scale', so multiple range
|
||||
* TLBI operations may be required. Start from scale = 3, flush the largest
|
||||
* possible number of pages ((num+1)*2^(5*scale+1)) that fit into the
|
||||
* requested range, then decrement scale and continue until one or zero pages
|
||||
* are left. We must start from highest scale to ensure 64KB start alignment
|
||||
* is maintained in the LPA2 case.
|
||||
*
|
||||
* 3. If there is 1 page remaining, flush it through non-range operations. Range
|
||||
* operations can only span an even number of pages. We save this for last to
|
||||
* ensure 64KB start alignment is maintained for the LPA2 case.
|
||||
*
|
||||
* Note that certain ranges can be represented by either num = 31 and
|
||||
* scale or num = 0 and scale + 1. The loop below favours the latter
|
||||
* since num is limited to 30 by the __TLBI_RANGE_NUM() macro.
|
||||
*/
|
||||
#define __flush_tlb_range_op(op, start, pages, stride, \
|
||||
asid, tlb_level, tlbi_user) \
|
||||
asid, tlb_level, tlbi_user, lpa2) \
|
||||
do { \
|
||||
int num = 0; \
|
||||
int scale = 0; \
|
||||
int scale = 3; \
|
||||
int shift = lpa2 ? 16 : PAGE_SHIFT; \
|
||||
unsigned long addr; \
|
||||
\
|
||||
while (pages > 0) { \
|
||||
if (!system_supports_tlb_range() || \
|
||||
pages % 2 == 1) { \
|
||||
pages == 1 || \
|
||||
(lpa2 && start != ALIGN(start, SZ_64K))) { \
|
||||
addr = __TLBI_VADDR(start, asid); \
|
||||
__tlbi_level(op, addr, tlb_level); \
|
||||
if (tlbi_user) \
|
||||
@@ -384,20 +407,20 @@ do { \
|
||||
\
|
||||
num = __TLBI_RANGE_NUM(pages, scale); \
|
||||
if (num >= 0) { \
|
||||
addr = __TLBI_VADDR_RANGE(start, asid, scale, \
|
||||
num, tlb_level); \
|
||||
addr = __TLBI_VADDR_RANGE(start >> shift, asid, \
|
||||
scale, num, tlb_level); \
|
||||
__tlbi(r##op, addr); \
|
||||
if (tlbi_user) \
|
||||
__tlbi_user(r##op, addr); \
|
||||
start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
|
||||
pages -= __TLBI_RANGE_PAGES(num, scale); \
|
||||
} \
|
||||
scale++; \
|
||||
scale--; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __flush_s2_tlb_range_op(op, start, pages, stride, tlb_level) \
|
||||
__flush_tlb_range_op(op, start, pages, stride, 0, tlb_level, false)
|
||||
__flush_tlb_range_op(op, start, pages, stride, 0, tlb_level, false, kvm_lpa2_is_enabled());
|
||||
|
||||
static inline void __flush_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end,
|
||||
@@ -427,9 +450,11 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
|
||||
asid = ASID(vma->vm_mm);
|
||||
|
||||
if (last_level)
|
||||
__flush_tlb_range_op(vale1is, start, pages, stride, asid, tlb_level, true);
|
||||
__flush_tlb_range_op(vale1is, start, pages, stride, asid,
|
||||
tlb_level, true, lpa2_is_enabled());
|
||||
else
|
||||
__flush_tlb_range_op(vae1is, start, pages, stride, asid, tlb_level, true);
|
||||
__flush_tlb_range_op(vae1is, start, pages, stride, asid,
|
||||
tlb_level, true, lpa2_is_enabled());
|
||||
|
||||
dsb(ish);
|
||||
mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, start, end);
|
||||
@@ -441,9 +466,10 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
|
||||
/*
|
||||
* We cannot use leaf-only invalidation here, since we may be invalidating
|
||||
* table entries as part of collapsing hugepages or moving page tables.
|
||||
* Set the tlb_level to 0 because we can not get enough information here.
|
||||
* Set the tlb_level to TLBI_TTL_UNKNOWN because we can not get enough
|
||||
* information here.
|
||||
*/
|
||||
__flush_tlb_range(vma, start, end, PAGE_SIZE, false, 0);
|
||||
__flush_tlb_range(vma, start, end, PAGE_SIZE, false, TLBI_TTL_UNKNOWN);
|
||||
}
|
||||
|
||||
static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
||||
|
||||
@@ -1081,25 +1081,6 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
|
||||
|
||||
if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
|
||||
init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
|
||||
|
||||
/*
|
||||
* Initialize the indirect array of CPU capabilities pointers before we
|
||||
* handle the boot CPU below.
|
||||
*/
|
||||
init_cpucap_indirect_list();
|
||||
|
||||
/*
|
||||
* Detect broken pseudo-NMI. Must be called _before_ the call to
|
||||
* setup_boot_cpu_capabilities() since it interacts with
|
||||
* can_use_gic_priorities().
|
||||
*/
|
||||
detect_system_supports_pseudo_nmi();
|
||||
|
||||
/*
|
||||
* Detect and enable early CPU capabilities based on the boot CPU,
|
||||
* after we have initialised the CPU feature infrastructure.
|
||||
*/
|
||||
setup_boot_cpu_capabilities();
|
||||
}
|
||||
|
||||
static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
|
||||
@@ -1585,16 +1566,6 @@ static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry,
|
||||
return has_sre;
|
||||
}
|
||||
|
||||
static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int __unused)
|
||||
{
|
||||
u32 midr = read_cpuid_id();
|
||||
|
||||
/* Cavium ThunderX pass 1.x and 2.x */
|
||||
return midr_is_cpu_model_range(midr, MIDR_THUNDERX,
|
||||
MIDR_CPU_VAR_REV(0, 0),
|
||||
MIDR_CPU_VAR_REV(1, MIDR_REVISION_MASK));
|
||||
}
|
||||
|
||||
static bool has_cache_idc(const struct arm64_cpu_capabilities *entry,
|
||||
int scope)
|
||||
{
|
||||
@@ -1769,6 +1740,39 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
|
||||
return !meltdown_safe;
|
||||
}
|
||||
|
||||
#if defined(ID_AA64MMFR0_EL1_TGRAN_LPA2) && defined(ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2)
|
||||
static bool has_lpa2_at_stage1(u64 mmfr0)
|
||||
{
|
||||
unsigned int tgran;
|
||||
|
||||
tgran = cpuid_feature_extract_unsigned_field(mmfr0,
|
||||
ID_AA64MMFR0_EL1_TGRAN_SHIFT);
|
||||
return tgran == ID_AA64MMFR0_EL1_TGRAN_LPA2;
|
||||
}
|
||||
|
||||
static bool has_lpa2_at_stage2(u64 mmfr0)
|
||||
{
|
||||
unsigned int tgran;
|
||||
|
||||
tgran = cpuid_feature_extract_unsigned_field(mmfr0,
|
||||
ID_AA64MMFR0_EL1_TGRAN_2_SHIFT);
|
||||
return tgran == ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2;
|
||||
}
|
||||
|
||||
static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
{
|
||||
u64 mmfr0;
|
||||
|
||||
mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
|
||||
return has_lpa2_at_stage1(mmfr0) && has_lpa2_at_stage2(mmfr0);
|
||||
}
|
||||
#else
|
||||
static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
||||
#define KPTI_NG_TEMP_VA (-(1UL << PMD_SHIFT))
|
||||
|
||||
@@ -1841,7 +1845,7 @@ static int __init __kpti_install_ng_mappings(void *__unused)
|
||||
static void __init kpti_install_ng_mappings(void)
|
||||
{
|
||||
/* Check whether KPTI is going to be used */
|
||||
if (!cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0))
|
||||
if (!arm64_kernel_unmapped_at_el0())
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -2326,12 +2330,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
ARM64_CPUID_FIELDS(ID_AA64ISAR0_EL1, ATOMIC, IMP)
|
||||
},
|
||||
#endif /* CONFIG_ARM64_LSE_ATOMICS */
|
||||
{
|
||||
.desc = "Software prefetching using PRFM",
|
||||
.capability = ARM64_HAS_NO_HW_PREFETCH,
|
||||
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
|
||||
.matches = has_no_hw_prefetch,
|
||||
},
|
||||
{
|
||||
.desc = "Virtualization Host Extensions",
|
||||
.capability = ARM64_HAS_VIRT_HOST_EXTN,
|
||||
@@ -2736,6 +2734,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
.matches = has_cpuid_feature,
|
||||
ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
|
||||
},
|
||||
{
|
||||
.desc = "52-bit Virtual Addressing for KVM (LPA2)",
|
||||
.capability = ARM64_HAS_LPA2,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_lpa2,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -3276,14 +3280,6 @@ void check_local_cpu_capabilities(void)
|
||||
verify_local_cpu_capabilities();
|
||||
}
|
||||
|
||||
static void __init setup_boot_cpu_capabilities(void)
|
||||
{
|
||||
/* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
|
||||
update_cpu_capabilities(SCOPE_BOOT_CPU | SCOPE_LOCAL_CPU);
|
||||
/* Enable the SCOPE_BOOT_CPU capabilities alone right away */
|
||||
enable_cpu_capabilities(SCOPE_BOOT_CPU);
|
||||
}
|
||||
|
||||
bool this_cpu_has_cap(unsigned int n)
|
||||
{
|
||||
if (!WARN_ON(preemptible()) && n < ARM64_NCAPS) {
|
||||
@@ -3339,23 +3335,70 @@ unsigned long cpu_get_elf_hwcap2(void)
|
||||
return elf_hwcap[1];
|
||||
}
|
||||
|
||||
void __init setup_system_features(void)
|
||||
static void __init setup_boot_cpu_capabilities(void)
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
* The system-wide safe feature feature register values have been
|
||||
* finalized. Finalize and log the available system capabilities.
|
||||
* The boot CPU's feature register values have been recorded. Detect
|
||||
* boot cpucaps and local cpucaps for the boot CPU, then enable and
|
||||
* patch alternatives for the available boot cpucaps.
|
||||
*/
|
||||
update_cpu_capabilities(SCOPE_SYSTEM);
|
||||
if (IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
|
||||
!cpus_have_cap(ARM64_HAS_PAN))
|
||||
pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
|
||||
update_cpu_capabilities(SCOPE_BOOT_CPU | SCOPE_LOCAL_CPU);
|
||||
enable_cpu_capabilities(SCOPE_BOOT_CPU);
|
||||
apply_boot_alternatives();
|
||||
}
|
||||
|
||||
void __init setup_boot_cpu_features(void)
|
||||
{
|
||||
/*
|
||||
* Initialize the indirect array of CPU capabilities pointers before we
|
||||
* handle the boot CPU.
|
||||
*/
|
||||
init_cpucap_indirect_list();
|
||||
|
||||
/*
|
||||
* Enable all the available capabilities which have not been enabled
|
||||
* already.
|
||||
* Detect broken pseudo-NMI. Must be called _before_ the call to
|
||||
* setup_boot_cpu_capabilities() since it interacts with
|
||||
* can_use_gic_priorities().
|
||||
*/
|
||||
detect_system_supports_pseudo_nmi();
|
||||
|
||||
setup_boot_cpu_capabilities();
|
||||
}
|
||||
|
||||
static void __init setup_system_capabilities(void)
|
||||
{
|
||||
/*
|
||||
* The system-wide safe feature register values have been finalized.
|
||||
* Detect, enable, and patch alternatives for the available system
|
||||
* cpucaps.
|
||||
*/
|
||||
update_cpu_capabilities(SCOPE_SYSTEM);
|
||||
enable_cpu_capabilities(SCOPE_ALL & ~SCOPE_BOOT_CPU);
|
||||
apply_alternatives_all();
|
||||
|
||||
/*
|
||||
* Log any cpucaps with a cpumask as these aren't logged by
|
||||
* update_cpu_capabilities().
|
||||
*/
|
||||
for (int i = 0; i < ARM64_NCAPS; i++) {
|
||||
const struct arm64_cpu_capabilities *caps = cpucap_ptrs[i];
|
||||
|
||||
if (caps && caps->cpus && caps->desc &&
|
||||
cpumask_any(caps->cpus) < nr_cpu_ids)
|
||||
pr_info("detected: %s on CPU%*pbl\n",
|
||||
caps->desc, cpumask_pr_args(caps->cpus));
|
||||
}
|
||||
|
||||
/*
|
||||
* TTBR0 PAN doesn't have its own cpucap, so log it manually.
|
||||
*/
|
||||
if (system_uses_ttbr0_pan())
|
||||
pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
|
||||
}
|
||||
|
||||
void __init setup_system_features(void)
|
||||
{
|
||||
setup_system_capabilities();
|
||||
|
||||
kpti_install_ng_mappings();
|
||||
|
||||
@@ -3368,15 +3411,6 @@ void __init setup_system_features(void)
|
||||
if (!cache_type_cwg())
|
||||
pr_warn("No Cache Writeback Granule information, assuming %d\n",
|
||||
ARCH_DMA_MINALIGN);
|
||||
|
||||
for (i = 0; i < ARM64_NCAPS; i++) {
|
||||
const struct arm64_cpu_capabilities *caps = cpucap_ptrs[i];
|
||||
|
||||
if (caps && caps->cpus && caps->desc &&
|
||||
cpumask_any(caps->cpus) < nr_cpu_ids)
|
||||
pr_info("detected: %s on CPU%*pbl\n",
|
||||
caps->desc, cpumask_pr_args(caps->cpus));
|
||||
}
|
||||
}
|
||||
|
||||
void __init setup_user_features(void)
|
||||
|
||||
@@ -36,8 +36,6 @@ static struct cpuinfo_arm64 boot_cpu_data;
|
||||
static inline const char *icache_policy_str(int l1ip)
|
||||
{
|
||||
switch (l1ip) {
|
||||
case CTR_EL0_L1Ip_VPIPT:
|
||||
return "VPIPT";
|
||||
case CTR_EL0_L1Ip_VIPT:
|
||||
return "VIPT";
|
||||
case CTR_EL0_L1Ip_PIPT:
|
||||
@@ -388,9 +386,6 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
|
||||
switch (l1ip) {
|
||||
case CTR_EL0_L1Ip_PIPT:
|
||||
break;
|
||||
case CTR_EL0_L1Ip_VPIPT:
|
||||
set_bit(ICACHEF_VPIPT, &__icache_flags);
|
||||
break;
|
||||
case CTR_EL0_L1Ip_VIPT:
|
||||
default:
|
||||
/* Assume aliasing */
|
||||
|
||||
+108
-61
@@ -85,13 +85,13 @@
|
||||
* softirq kicks in. Upon vcpu_put(), KVM will save the vcpu FP state and
|
||||
* flag the register state as invalid.
|
||||
*
|
||||
* In order to allow softirq handlers to use FPSIMD, kernel_neon_begin() may
|
||||
* save the task's FPSIMD context back to task_struct from softirq context.
|
||||
* To prevent this from racing with the manipulation of the task's FPSIMD state
|
||||
* from task context and thereby corrupting the state, it is necessary to
|
||||
* protect any manipulation of a task's fpsimd_state or TIF_FOREIGN_FPSTATE
|
||||
* flag with {, __}get_cpu_fpsimd_context(). This will still allow softirqs to
|
||||
* run but prevent them to use FPSIMD.
|
||||
* In order to allow softirq handlers to use FPSIMD, kernel_neon_begin() may be
|
||||
* called from softirq context, which will save the task's FPSIMD context back
|
||||
* to task_struct. To prevent this from racing with the manipulation of the
|
||||
* task's FPSIMD state from task context and thereby corrupting the state, it
|
||||
* is necessary to protect any manipulation of a task's fpsimd_state or
|
||||
* TIF_FOREIGN_FPSTATE flag with get_cpu_fpsimd_context(), which will suspend
|
||||
* softirq servicing entirely until put_cpu_fpsimd_context() is called.
|
||||
*
|
||||
* For a certain task, the sequence may look something like this:
|
||||
* - the task gets scheduled in; if both the task's fpsimd_cpu field
|
||||
@@ -209,27 +209,14 @@ static inline void sme_free(struct task_struct *t) { }
|
||||
|
||||
#endif
|
||||
|
||||
DEFINE_PER_CPU(bool, fpsimd_context_busy);
|
||||
EXPORT_PER_CPU_SYMBOL(fpsimd_context_busy);
|
||||
|
||||
static void fpsimd_bind_task_to_cpu(void);
|
||||
|
||||
static void __get_cpu_fpsimd_context(void)
|
||||
{
|
||||
bool busy = __this_cpu_xchg(fpsimd_context_busy, true);
|
||||
|
||||
WARN_ON(busy);
|
||||
}
|
||||
|
||||
/*
|
||||
* Claim ownership of the CPU FPSIMD context for use by the calling context.
|
||||
*
|
||||
* The caller may freely manipulate the FPSIMD context metadata until
|
||||
* put_cpu_fpsimd_context() is called.
|
||||
*
|
||||
* The double-underscore version must only be called if you know the task
|
||||
* can't be preempted.
|
||||
*
|
||||
* On RT kernels local_bh_disable() is not sufficient because it only
|
||||
* serializes soft interrupt related sections via a local lock, but stays
|
||||
* preemptible. Disabling preemption is the right choice here as bottom
|
||||
@@ -242,14 +229,6 @@ static void get_cpu_fpsimd_context(void)
|
||||
local_bh_disable();
|
||||
else
|
||||
preempt_disable();
|
||||
__get_cpu_fpsimd_context();
|
||||
}
|
||||
|
||||
static void __put_cpu_fpsimd_context(void)
|
||||
{
|
||||
bool busy = __this_cpu_xchg(fpsimd_context_busy, false);
|
||||
|
||||
WARN_ON(!busy); /* No matching get_cpu_fpsimd_context()? */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -261,18 +240,12 @@ static void __put_cpu_fpsimd_context(void)
|
||||
*/
|
||||
static void put_cpu_fpsimd_context(void)
|
||||
{
|
||||
__put_cpu_fpsimd_context();
|
||||
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
local_bh_enable();
|
||||
else
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static bool have_cpu_fpsimd_context(void)
|
||||
{
|
||||
return !preemptible() && __this_cpu_read(fpsimd_context_busy);
|
||||
}
|
||||
|
||||
unsigned int task_get_vl(const struct task_struct *task, enum vec_type type)
|
||||
{
|
||||
return task->thread.vl[type];
|
||||
@@ -383,7 +356,8 @@ static void task_fpsimd_load(void)
|
||||
bool restore_ffr;
|
||||
|
||||
WARN_ON(!system_supports_fpsimd());
|
||||
WARN_ON(!have_cpu_fpsimd_context());
|
||||
WARN_ON(preemptible());
|
||||
WARN_ON(test_thread_flag(TIF_KERNEL_FPSTATE));
|
||||
|
||||
if (system_supports_sve() || system_supports_sme()) {
|
||||
switch (current->thread.fp_type) {
|
||||
@@ -406,7 +380,7 @@ static void task_fpsimd_load(void)
|
||||
default:
|
||||
/*
|
||||
* This indicates either a bug in
|
||||
* fpsimd_save() or memory corruption, we
|
||||
* fpsimd_save_user_state() or memory corruption, we
|
||||
* should always record an explicit format
|
||||
* when we save. We always at least have the
|
||||
* memory allocated for FPSMID registers so
|
||||
@@ -457,7 +431,7 @@ static void task_fpsimd_load(void)
|
||||
* than via current, if we are saving KVM state then it will have
|
||||
* ensured that the type of registers to save is set in last->to_save.
|
||||
*/
|
||||
static void fpsimd_save(void)
|
||||
static void fpsimd_save_user_state(void)
|
||||
{
|
||||
struct cpu_fp_state const *last =
|
||||
this_cpu_ptr(&fpsimd_last_state);
|
||||
@@ -467,7 +441,7 @@ static void fpsimd_save(void)
|
||||
unsigned int vl;
|
||||
|
||||
WARN_ON(!system_supports_fpsimd());
|
||||
WARN_ON(!have_cpu_fpsimd_context());
|
||||
WARN_ON(preemptible());
|
||||
|
||||
if (test_thread_flag(TIF_FOREIGN_FPSTATE))
|
||||
return;
|
||||
@@ -888,7 +862,7 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
|
||||
if (task == current) {
|
||||
get_cpu_fpsimd_context();
|
||||
|
||||
fpsimd_save();
|
||||
fpsimd_save_user_state();
|
||||
}
|
||||
|
||||
fpsimd_flush_task_state(task);
|
||||
@@ -1171,7 +1145,7 @@ void __init sve_setup(void)
|
||||
unsigned long b;
|
||||
int max_bit;
|
||||
|
||||
if (!cpus_have_cap(ARM64_SVE))
|
||||
if (!system_supports_sve())
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -1301,7 +1275,7 @@ void __init sme_setup(void)
|
||||
struct vl_info *info = &vl_info[ARM64_VEC_SME];
|
||||
int min_bit, max_bit;
|
||||
|
||||
if (!cpus_have_cap(ARM64_SME))
|
||||
if (!system_supports_sme())
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -1500,6 +1474,34 @@ void do_fpsimd_exc(unsigned long esr, struct pt_regs *regs)
|
||||
current);
|
||||
}
|
||||
|
||||
static void fpsimd_load_kernel_state(struct task_struct *task)
|
||||
{
|
||||
struct cpu_fp_state *last = this_cpu_ptr(&fpsimd_last_state);
|
||||
|
||||
/*
|
||||
* Elide the load if this CPU holds the most recent kernel mode
|
||||
* FPSIMD context of the current task.
|
||||
*/
|
||||
if (last->st == &task->thread.kernel_fpsimd_state &&
|
||||
task->thread.kernel_fpsimd_cpu == smp_processor_id())
|
||||
return;
|
||||
|
||||
fpsimd_load_state(&task->thread.kernel_fpsimd_state);
|
||||
}
|
||||
|
||||
static void fpsimd_save_kernel_state(struct task_struct *task)
|
||||
{
|
||||
struct cpu_fp_state cpu_fp_state = {
|
||||
.st = &task->thread.kernel_fpsimd_state,
|
||||
.to_save = FP_STATE_FPSIMD,
|
||||
};
|
||||
|
||||
fpsimd_save_state(&task->thread.kernel_fpsimd_state);
|
||||
fpsimd_bind_state_to_cpu(&cpu_fp_state);
|
||||
|
||||
task->thread.kernel_fpsimd_cpu = smp_processor_id();
|
||||
}
|
||||
|
||||
void fpsimd_thread_switch(struct task_struct *next)
|
||||
{
|
||||
bool wrong_task, wrong_cpu;
|
||||
@@ -1507,24 +1509,31 @@ void fpsimd_thread_switch(struct task_struct *next)
|
||||
if (!system_supports_fpsimd())
|
||||
return;
|
||||
|
||||
__get_cpu_fpsimd_context();
|
||||
WARN_ON_ONCE(!irqs_disabled());
|
||||
|
||||
/* Save unsaved fpsimd state, if any: */
|
||||
fpsimd_save();
|
||||
if (test_thread_flag(TIF_KERNEL_FPSTATE))
|
||||
fpsimd_save_kernel_state(current);
|
||||
else
|
||||
fpsimd_save_user_state();
|
||||
|
||||
/*
|
||||
* Fix up TIF_FOREIGN_FPSTATE to correctly describe next's
|
||||
* state. For kernel threads, FPSIMD registers are never loaded
|
||||
* and wrong_task and wrong_cpu will always be true.
|
||||
*/
|
||||
wrong_task = __this_cpu_read(fpsimd_last_state.st) !=
|
||||
&next->thread.uw.fpsimd_state;
|
||||
wrong_cpu = next->thread.fpsimd_cpu != smp_processor_id();
|
||||
if (test_tsk_thread_flag(next, TIF_KERNEL_FPSTATE)) {
|
||||
fpsimd_load_kernel_state(next);
|
||||
set_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE);
|
||||
} else {
|
||||
/*
|
||||
* Fix up TIF_FOREIGN_FPSTATE to correctly describe next's
|
||||
* state. For kernel threads, FPSIMD registers are never
|
||||
* loaded with user mode FPSIMD state and so wrong_task and
|
||||
* wrong_cpu will always be true.
|
||||
*/
|
||||
wrong_task = __this_cpu_read(fpsimd_last_state.st) !=
|
||||
&next->thread.uw.fpsimd_state;
|
||||
wrong_cpu = next->thread.fpsimd_cpu != smp_processor_id();
|
||||
|
||||
update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
|
||||
wrong_task || wrong_cpu);
|
||||
|
||||
__put_cpu_fpsimd_context();
|
||||
update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
|
||||
wrong_task || wrong_cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static void fpsimd_flush_thread_vl(enum vec_type type)
|
||||
@@ -1614,7 +1623,7 @@ void fpsimd_preserve_current_state(void)
|
||||
return;
|
||||
|
||||
get_cpu_fpsimd_context();
|
||||
fpsimd_save();
|
||||
fpsimd_save_user_state();
|
||||
put_cpu_fpsimd_context();
|
||||
}
|
||||
|
||||
@@ -1826,13 +1835,15 @@ static void fpsimd_flush_cpu_state(void)
|
||||
*/
|
||||
void fpsimd_save_and_flush_cpu_state(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!system_supports_fpsimd())
|
||||
return;
|
||||
WARN_ON(preemptible());
|
||||
__get_cpu_fpsimd_context();
|
||||
fpsimd_save();
|
||||
local_irq_save(flags);
|
||||
fpsimd_save_user_state();
|
||||
fpsimd_flush_cpu_state();
|
||||
__put_cpu_fpsimd_context();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KERNEL_MODE_NEON
|
||||
@@ -1864,10 +1875,37 @@ void kernel_neon_begin(void)
|
||||
get_cpu_fpsimd_context();
|
||||
|
||||
/* Save unsaved fpsimd state, if any: */
|
||||
fpsimd_save();
|
||||
if (test_thread_flag(TIF_KERNEL_FPSTATE)) {
|
||||
BUG_ON(IS_ENABLED(CONFIG_PREEMPT_RT) || !in_serving_softirq());
|
||||
fpsimd_save_kernel_state(current);
|
||||
} else {
|
||||
fpsimd_save_user_state();
|
||||
|
||||
/*
|
||||
* Set the thread flag so that the kernel mode FPSIMD state
|
||||
* will be context switched along with the rest of the task
|
||||
* state.
|
||||
*
|
||||
* On non-PREEMPT_RT, softirqs may interrupt task level kernel
|
||||
* mode FPSIMD, but the task will not be preemptible so setting
|
||||
* TIF_KERNEL_FPSTATE for those would be both wrong (as it
|
||||
* would mark the task context FPSIMD state as requiring a
|
||||
* context switch) and unnecessary.
|
||||
*
|
||||
* On PREEMPT_RT, softirqs are serviced from a separate thread,
|
||||
* which is scheduled as usual, and this guarantees that these
|
||||
* softirqs are not interrupting use of the FPSIMD in kernel
|
||||
* mode in task context. So in this case, setting the flag here
|
||||
* is always appropriate.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT) || !in_serving_softirq())
|
||||
set_thread_flag(TIF_KERNEL_FPSTATE);
|
||||
}
|
||||
|
||||
/* Invalidate any task state remaining in the fpsimd regs: */
|
||||
fpsimd_flush_cpu_state();
|
||||
|
||||
put_cpu_fpsimd_context();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kernel_neon_begin);
|
||||
|
||||
@@ -1885,7 +1923,16 @@ void kernel_neon_end(void)
|
||||
if (!system_supports_fpsimd())
|
||||
return;
|
||||
|
||||
put_cpu_fpsimd_context();
|
||||
/*
|
||||
* If we are returning from a nested use of kernel mode FPSIMD, restore
|
||||
* the task context kernel mode FPSIMD state. This can only happen when
|
||||
* running in softirq context on non-PREEMPT_RT.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_PREEMPT_RT) && in_serving_softirq() &&
|
||||
test_thread_flag(TIF_KERNEL_FPSTATE))
|
||||
fpsimd_load_kernel_state(current);
|
||||
else
|
||||
clear_thread_flag(TIF_KERNEL_FPSTATE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kernel_neon_end);
|
||||
|
||||
|
||||
@@ -482,7 +482,7 @@ SYM_FUNC_START_LOCAL(__primary_switched)
|
||||
|
||||
str_l x21, __fdt_pointer, x5 // Save FDT pointer
|
||||
|
||||
ldr_l x4, kimage_vaddr // Save the offset between
|
||||
adrp x4, _text // Save the offset between
|
||||
sub x4, x4, x0 // the kernel virtual and
|
||||
str_l x4, kimage_voffset, x5 // physical mappings
|
||||
|
||||
|
||||
@@ -21,14 +21,25 @@
|
||||
|
||||
static u64 __boot_status __initdata;
|
||||
|
||||
// temporary __prel64 related definitions
|
||||
// to be removed when this code is moved under pi/
|
||||
|
||||
#define __prel64_initconst __initconst
|
||||
|
||||
#define PREL64(type, name) union { type *name; }
|
||||
|
||||
#define prel64_pointer(__d) (__d)
|
||||
|
||||
typedef bool filter_t(u64 val);
|
||||
|
||||
struct ftr_set_desc {
|
||||
char name[FTR_DESC_NAME_LEN];
|
||||
struct arm64_ftr_override *override;
|
||||
PREL64(struct arm64_ftr_override, override);
|
||||
struct {
|
||||
char name[FTR_DESC_FIELD_LEN];
|
||||
u8 shift;
|
||||
u8 width;
|
||||
bool (*filter)(u64 val);
|
||||
PREL64(filter_t, filter);
|
||||
} fields[];
|
||||
};
|
||||
|
||||
@@ -46,7 +57,7 @@ static bool __init mmfr1_vh_filter(u64 val)
|
||||
val == 0);
|
||||
}
|
||||
|
||||
static const struct ftr_set_desc mmfr1 __initconst = {
|
||||
static const struct ftr_set_desc mmfr1 __prel64_initconst = {
|
||||
.name = "id_aa64mmfr1",
|
||||
.override = &id_aa64mmfr1_override,
|
||||
.fields = {
|
||||
@@ -70,7 +81,7 @@ static bool __init pfr0_sve_filter(u64 val)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct ftr_set_desc pfr0 __initconst = {
|
||||
static const struct ftr_set_desc pfr0 __prel64_initconst = {
|
||||
.name = "id_aa64pfr0",
|
||||
.override = &id_aa64pfr0_override,
|
||||
.fields = {
|
||||
@@ -94,7 +105,7 @@ static bool __init pfr1_sme_filter(u64 val)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct ftr_set_desc pfr1 __initconst = {
|
||||
static const struct ftr_set_desc pfr1 __prel64_initconst = {
|
||||
.name = "id_aa64pfr1",
|
||||
.override = &id_aa64pfr1_override,
|
||||
.fields = {
|
||||
@@ -105,7 +116,7 @@ static const struct ftr_set_desc pfr1 __initconst = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ftr_set_desc isar1 __initconst = {
|
||||
static const struct ftr_set_desc isar1 __prel64_initconst = {
|
||||
.name = "id_aa64isar1",
|
||||
.override = &id_aa64isar1_override,
|
||||
.fields = {
|
||||
@@ -117,7 +128,7 @@ static const struct ftr_set_desc isar1 __initconst = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ftr_set_desc isar2 __initconst = {
|
||||
static const struct ftr_set_desc isar2 __prel64_initconst = {
|
||||
.name = "id_aa64isar2",
|
||||
.override = &id_aa64isar2_override,
|
||||
.fields = {
|
||||
@@ -128,7 +139,7 @@ static const struct ftr_set_desc isar2 __initconst = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ftr_set_desc smfr0 __initconst = {
|
||||
static const struct ftr_set_desc smfr0 __prel64_initconst = {
|
||||
.name = "id_aa64smfr0",
|
||||
.override = &id_aa64smfr0_override,
|
||||
.fields = {
|
||||
@@ -149,7 +160,7 @@ static bool __init hvhe_filter(u64 val)
|
||||
ID_AA64MMFR1_EL1_VH_SHIFT));
|
||||
}
|
||||
|
||||
static const struct ftr_set_desc sw_features __initconst = {
|
||||
static const struct ftr_set_desc sw_features __prel64_initconst = {
|
||||
.name = "arm64_sw",
|
||||
.override = &arm64_sw_feature_override,
|
||||
.fields = {
|
||||
@@ -159,22 +170,23 @@ static const struct ftr_set_desc sw_features __initconst = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ftr_set_desc * const regs[] __initconst = {
|
||||
&mmfr1,
|
||||
&pfr0,
|
||||
&pfr1,
|
||||
&isar1,
|
||||
&isar2,
|
||||
&smfr0,
|
||||
&sw_features,
|
||||
static const
|
||||
PREL64(const struct ftr_set_desc, reg) regs[] __prel64_initconst = {
|
||||
{ &mmfr1 },
|
||||
{ &pfr0 },
|
||||
{ &pfr1 },
|
||||
{ &isar1 },
|
||||
{ &isar2 },
|
||||
{ &smfr0 },
|
||||
{ &sw_features },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char alias[FTR_ALIAS_NAME_LEN];
|
||||
char feature[FTR_ALIAS_OPTION_LEN];
|
||||
} aliases[] __initconst = {
|
||||
{ "kvm-arm.mode=nvhe", "id_aa64mmfr1.vh=0" },
|
||||
{ "kvm-arm.mode=protected", "id_aa64mmfr1.vh=0" },
|
||||
{ "kvm_arm.mode=nvhe", "id_aa64mmfr1.vh=0" },
|
||||
{ "kvm_arm.mode=protected", "id_aa64mmfr1.vh=0" },
|
||||
{ "arm64.nosve", "id_aa64pfr0.sve=0" },
|
||||
{ "arm64.nosme", "id_aa64pfr1.sme=0" },
|
||||
{ "arm64.nobti", "id_aa64pfr1.bt=0" },
|
||||
@@ -187,45 +199,61 @@ static const struct {
|
||||
{ "nokaslr", "arm64_sw.nokaslr=1" },
|
||||
};
|
||||
|
||||
static int __init parse_nokaslr(char *unused)
|
||||
static int __init parse_hexdigit(const char *p, u64 *v)
|
||||
{
|
||||
/* nokaslr param handling is done by early cpufeature code */
|
||||
// skip "0x" if it comes next
|
||||
if (p[0] == '0' && tolower(p[1]) == 'x')
|
||||
p += 2;
|
||||
|
||||
// check whether the RHS is a single hex digit
|
||||
if (!isxdigit(p[0]) || (p[1] && !isspace(p[1])))
|
||||
return -EINVAL;
|
||||
|
||||
*v = tolower(*p) - (isdigit(*p) ? '0' : 'a' - 10);
|
||||
return 0;
|
||||
}
|
||||
early_param("nokaslr", parse_nokaslr);
|
||||
|
||||
static int __init find_field(const char *cmdline,
|
||||
static int __init find_field(const char *cmdline, char *opt, int len,
|
||||
const struct ftr_set_desc *reg, int f, u64 *v)
|
||||
{
|
||||
char opt[FTR_DESC_NAME_LEN + FTR_DESC_FIELD_LEN + 2];
|
||||
int len;
|
||||
int flen = strlen(reg->fields[f].name);
|
||||
|
||||
len = snprintf(opt, ARRAY_SIZE(opt), "%s.%s=",
|
||||
reg->name, reg->fields[f].name);
|
||||
// append '<fieldname>=' to obtain '<name>.<fieldname>='
|
||||
memcpy(opt + len, reg->fields[f].name, flen);
|
||||
len += flen;
|
||||
opt[len++] = '=';
|
||||
|
||||
if (!parameqn(cmdline, opt, len))
|
||||
if (memcmp(cmdline, opt, len))
|
||||
return -1;
|
||||
|
||||
return kstrtou64(cmdline + len, 0, v);
|
||||
return parse_hexdigit(cmdline + len, v);
|
||||
}
|
||||
|
||||
static void __init match_options(const char *cmdline)
|
||||
{
|
||||
char opt[FTR_DESC_NAME_LEN + FTR_DESC_FIELD_LEN + 2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||
const struct ftr_set_desc *reg = prel64_pointer(regs[i].reg);
|
||||
struct arm64_ftr_override *override;
|
||||
int len = strlen(reg->name);
|
||||
int f;
|
||||
|
||||
if (!regs[i]->override)
|
||||
continue;
|
||||
override = prel64_pointer(reg->override);
|
||||
|
||||
for (f = 0; strlen(regs[i]->fields[f].name); f++) {
|
||||
u64 shift = regs[i]->fields[f].shift;
|
||||
u64 width = regs[i]->fields[f].width ?: 4;
|
||||
// set opt[] to '<name>.'
|
||||
memcpy(opt, reg->name, len);
|
||||
opt[len++] = '.';
|
||||
|
||||
for (f = 0; reg->fields[f].name[0] != '\0'; f++) {
|
||||
u64 shift = reg->fields[f].shift;
|
||||
u64 width = reg->fields[f].width ?: 4;
|
||||
u64 mask = GENMASK_ULL(shift + width - 1, shift);
|
||||
bool (*filter)(u64 val);
|
||||
u64 v;
|
||||
|
||||
if (find_field(cmdline, regs[i], f, &v))
|
||||
if (find_field(cmdline, opt, len, reg, f, &v))
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -233,16 +261,16 @@ static void __init match_options(const char *cmdline)
|
||||
* it by setting the value to the all-ones while
|
||||
* clearing the mask... Yes, this is fragile.
|
||||
*/
|
||||
if (regs[i]->fields[f].filter &&
|
||||
!regs[i]->fields[f].filter(v)) {
|
||||
regs[i]->override->val |= mask;
|
||||
regs[i]->override->mask &= ~mask;
|
||||
filter = prel64_pointer(reg->fields[f].filter);
|
||||
if (filter && !filter(v)) {
|
||||
override->val |= mask;
|
||||
override->mask &= ~mask;
|
||||
continue;
|
||||
}
|
||||
|
||||
regs[i]->override->val &= ~mask;
|
||||
regs[i]->override->val |= (v << shift) & mask;
|
||||
regs[i]->override->mask |= mask;
|
||||
override->val &= ~mask;
|
||||
override->val |= (v << shift) & mask;
|
||||
override->mask |= mask;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -258,23 +286,29 @@ static __init void __parse_cmdline(const char *cmdline, bool parse_aliases)
|
||||
|
||||
cmdline = skip_spaces(cmdline);
|
||||
|
||||
for (len = 0; cmdline[len] && !isspace(cmdline[len]); len++);
|
||||
/* terminate on "--" appearing on the command line by itself */
|
||||
if (cmdline[0] == '-' && cmdline[1] == '-' && isspace(cmdline[2]))
|
||||
return;
|
||||
|
||||
for (len = 0; cmdline[len] && !isspace(cmdline[len]); len++) {
|
||||
if (len >= sizeof(buf) - 1)
|
||||
break;
|
||||
if (cmdline[len] == '-')
|
||||
buf[len] = '_';
|
||||
else
|
||||
buf[len] = cmdline[len];
|
||||
}
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
len = min(len, ARRAY_SIZE(buf) - 1);
|
||||
memcpy(buf, cmdline, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
if (strcmp(buf, "--") == 0)
|
||||
return;
|
||||
buf[len] = 0;
|
||||
|
||||
cmdline += len;
|
||||
|
||||
match_options(buf);
|
||||
|
||||
for (i = 0; parse_aliases && i < ARRAY_SIZE(aliases); i++)
|
||||
if (parameq(buf, aliases[i].alias))
|
||||
if (!memcmp(buf, aliases[i].alias, len + 1))
|
||||
__parse_cmdline(aliases[i].feature, false);
|
||||
} while (1);
|
||||
}
|
||||
@@ -316,13 +350,16 @@ void init_feature_override(u64 boot_status);
|
||||
|
||||
asmlinkage void __init init_feature_override(u64 boot_status)
|
||||
{
|
||||
struct arm64_ftr_override *override;
|
||||
const struct ftr_set_desc *reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||
if (regs[i]->override) {
|
||||
regs[i]->override->val = 0;
|
||||
regs[i]->override->mask = 0;
|
||||
}
|
||||
reg = prel64_pointer(regs[i].reg);
|
||||
override = prel64_pointer(reg->override);
|
||||
|
||||
override->val = 0;
|
||||
override->mask = 0;
|
||||
}
|
||||
|
||||
__boot_status = boot_status;
|
||||
@@ -330,9 +367,9 @@ asmlinkage void __init init_feature_override(u64 boot_status)
|
||||
parse_cmdline();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||
if (regs[i]->override)
|
||||
dcache_clean_inval_poc((unsigned long)regs[i]->override,
|
||||
(unsigned long)regs[i]->override +
|
||||
sizeof(*regs[i]->override));
|
||||
reg = prel64_pointer(regs[i].reg);
|
||||
override = prel64_pointer(reg->override);
|
||||
dcache_clean_inval_poc((unsigned long)override,
|
||||
(unsigned long)(override + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/daifflags.h>
|
||||
#include <asm/exception.h>
|
||||
#include <asm/numa.h>
|
||||
#include <asm/softirq_stack.h>
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/vmap_stack.h>
|
||||
@@ -47,17 +48,17 @@ static void init_irq_scs(void)
|
||||
|
||||
for_each_possible_cpu(cpu)
|
||||
per_cpu(irq_shadow_call_stack_ptr, cpu) =
|
||||
scs_alloc(cpu_to_node(cpu));
|
||||
scs_alloc(early_cpu_to_node(cpu));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
static void init_irq_stacks(void)
|
||||
static void __init init_irq_stacks(void)
|
||||
{
|
||||
int cpu;
|
||||
unsigned long *p;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
p = arch_alloc_vmap_stack(IRQ_STACK_SIZE, cpu_to_node(cpu));
|
||||
p = arch_alloc_vmap_stack(IRQ_STACK_SIZE, early_cpu_to_node(cpu));
|
||||
per_cpu(irq_stack_ptr, cpu) = p;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,3 +36,10 @@ void __init kaslr_init(void)
|
||||
pr_info("KASLR enabled\n");
|
||||
__kaslr_is_enabled = true;
|
||||
}
|
||||
|
||||
static int __init parse_nokaslr(char *unused)
|
||||
{
|
||||
/* nokaslr param handling is done by early cpufeature code */
|
||||
return 0;
|
||||
}
|
||||
early_param("nokaslr", parse_nokaslr);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
KBUILD_CFLAGS := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) -fpie \
|
||||
-Os -DDISABLE_BRANCH_PROFILING $(DISABLE_STACKLEAK_PLUGIN) \
|
||||
$(DISABLE_LATENT_ENTROPY_PLUGIN) \
|
||||
$(call cc-option,-mbranch-protection=none) \
|
||||
-I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \
|
||||
-include $(srctree)/include/linux/hidden.h \
|
||||
|
||||
@@ -444,9 +444,8 @@ static void __init hyp_mode_check(void)
|
||||
void __init smp_cpus_done(unsigned int max_cpus)
|
||||
{
|
||||
pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());
|
||||
setup_system_features();
|
||||
hyp_mode_check();
|
||||
apply_alternatives_all();
|
||||
setup_system_features();
|
||||
setup_user_features();
|
||||
mark_linear_text_alias_ro();
|
||||
}
|
||||
@@ -459,14 +458,9 @@ void __init smp_prepare_boot_cpu(void)
|
||||
* freed shortly, so we must move over to the runtime per-cpu area.
|
||||
*/
|
||||
set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
|
||||
cpuinfo_store_boot_cpu();
|
||||
|
||||
/*
|
||||
* We now know enough about the boot CPU to apply the
|
||||
* alternatives that cannot wait until interrupt handling
|
||||
* and/or scheduling is enabled.
|
||||
*/
|
||||
apply_boot_alternatives();
|
||||
cpuinfo_store_boot_cpu();
|
||||
setup_boot_cpu_features();
|
||||
|
||||
/* Conditionally switch to GIC PMR for interrupt masking */
|
||||
if (system_uses_irq_prio_masking())
|
||||
|
||||
+102
-44
@@ -8,6 +8,7 @@
|
||||
#include <linux/efi.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/debug.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
@@ -18,6 +19,31 @@
|
||||
#include <asm/stack_pointer.h>
|
||||
#include <asm/stacktrace.h>
|
||||
|
||||
/*
|
||||
* Kernel unwind state
|
||||
*
|
||||
* @common: Common unwind state.
|
||||
* @task: The task being unwound.
|
||||
* @kr_cur: When KRETPROBES is selected, holds the kretprobe instance
|
||||
* associated with the most recently encountered replacement lr
|
||||
* value.
|
||||
*/
|
||||
struct kunwind_state {
|
||||
struct unwind_state common;
|
||||
struct task_struct *task;
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
struct llist_node *kr_cur;
|
||||
#endif
|
||||
};
|
||||
|
||||
static __always_inline void
|
||||
kunwind_init(struct kunwind_state *state,
|
||||
struct task_struct *task)
|
||||
{
|
||||
unwind_init_common(&state->common);
|
||||
state->task = task;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start an unwind from a pt_regs.
|
||||
*
|
||||
@@ -26,13 +52,13 @@
|
||||
* The regs must be on a stack currently owned by the calling task.
|
||||
*/
|
||||
static __always_inline void
|
||||
unwind_init_from_regs(struct unwind_state *state,
|
||||
struct pt_regs *regs)
|
||||
kunwind_init_from_regs(struct kunwind_state *state,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unwind_init_common(state, current);
|
||||
kunwind_init(state, current);
|
||||
|
||||
state->fp = regs->regs[29];
|
||||
state->pc = regs->pc;
|
||||
state->common.fp = regs->regs[29];
|
||||
state->common.pc = regs->pc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -44,12 +70,12 @@ unwind_init_from_regs(struct unwind_state *state,
|
||||
* The function which invokes this must be noinline.
|
||||
*/
|
||||
static __always_inline void
|
||||
unwind_init_from_caller(struct unwind_state *state)
|
||||
kunwind_init_from_caller(struct kunwind_state *state)
|
||||
{
|
||||
unwind_init_common(state, current);
|
||||
kunwind_init(state, current);
|
||||
|
||||
state->fp = (unsigned long)__builtin_frame_address(1);
|
||||
state->pc = (unsigned long)__builtin_return_address(0);
|
||||
state->common.fp = (unsigned long)__builtin_frame_address(1);
|
||||
state->common.pc = (unsigned long)__builtin_return_address(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -63,35 +89,38 @@ unwind_init_from_caller(struct unwind_state *state)
|
||||
* call this for the current task.
|
||||
*/
|
||||
static __always_inline void
|
||||
unwind_init_from_task(struct unwind_state *state,
|
||||
struct task_struct *task)
|
||||
kunwind_init_from_task(struct kunwind_state *state,
|
||||
struct task_struct *task)
|
||||
{
|
||||
unwind_init_common(state, task);
|
||||
kunwind_init(state, task);
|
||||
|
||||
state->fp = thread_saved_fp(task);
|
||||
state->pc = thread_saved_pc(task);
|
||||
state->common.fp = thread_saved_fp(task);
|
||||
state->common.pc = thread_saved_pc(task);
|
||||
}
|
||||
|
||||
static __always_inline int
|
||||
unwind_recover_return_address(struct unwind_state *state)
|
||||
kunwind_recover_return_address(struct kunwind_state *state)
|
||||
{
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
if (state->task->ret_stack &&
|
||||
(state->pc == (unsigned long)return_to_handler)) {
|
||||
(state->common.pc == (unsigned long)return_to_handler)) {
|
||||
unsigned long orig_pc;
|
||||
orig_pc = ftrace_graph_ret_addr(state->task, NULL, state->pc,
|
||||
(void *)state->fp);
|
||||
if (WARN_ON_ONCE(state->pc == orig_pc))
|
||||
orig_pc = ftrace_graph_ret_addr(state->task, NULL,
|
||||
state->common.pc,
|
||||
(void *)state->common.fp);
|
||||
if (WARN_ON_ONCE(state->common.pc == orig_pc))
|
||||
return -EINVAL;
|
||||
state->pc = orig_pc;
|
||||
state->common.pc = orig_pc;
|
||||
}
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
if (is_kretprobe_trampoline(state->pc)) {
|
||||
state->pc = kretprobe_find_ret_addr(state->task,
|
||||
(void *)state->fp,
|
||||
&state->kr_cur);
|
||||
if (is_kretprobe_trampoline(state->common.pc)) {
|
||||
unsigned long orig_pc;
|
||||
orig_pc = kretprobe_find_ret_addr(state->task,
|
||||
(void *)state->common.fp,
|
||||
&state->kr_cur);
|
||||
state->common.pc = orig_pc;
|
||||
}
|
||||
#endif /* CONFIG_KRETPROBES */
|
||||
|
||||
@@ -106,38 +135,40 @@ unwind_recover_return_address(struct unwind_state *state)
|
||||
* and the location (but not the fp value) of B.
|
||||
*/
|
||||
static __always_inline int
|
||||
unwind_next(struct unwind_state *state)
|
||||
kunwind_next(struct kunwind_state *state)
|
||||
{
|
||||
struct task_struct *tsk = state->task;
|
||||
unsigned long fp = state->fp;
|
||||
unsigned long fp = state->common.fp;
|
||||
int err;
|
||||
|
||||
/* Final frame; nothing to unwind */
|
||||
if (fp == (unsigned long)task_pt_regs(tsk)->stackframe)
|
||||
return -ENOENT;
|
||||
|
||||
err = unwind_next_frame_record(state);
|
||||
err = unwind_next_frame_record(&state->common);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
state->pc = ptrauth_strip_kernel_insn_pac(state->pc);
|
||||
state->common.pc = ptrauth_strip_kernel_insn_pac(state->common.pc);
|
||||
|
||||
return unwind_recover_return_address(state);
|
||||
return kunwind_recover_return_address(state);
|
||||
}
|
||||
|
||||
typedef bool (*kunwind_consume_fn)(const struct kunwind_state *state, void *cookie);
|
||||
|
||||
static __always_inline void
|
||||
unwind(struct unwind_state *state, stack_trace_consume_fn consume_entry,
|
||||
void *cookie)
|
||||
do_kunwind(struct kunwind_state *state, kunwind_consume_fn consume_state,
|
||||
void *cookie)
|
||||
{
|
||||
if (unwind_recover_return_address(state))
|
||||
if (kunwind_recover_return_address(state))
|
||||
return;
|
||||
|
||||
while (1) {
|
||||
int ret;
|
||||
|
||||
if (!consume_entry(cookie, state->pc))
|
||||
if (!consume_state(state, cookie))
|
||||
break;
|
||||
ret = unwind_next(state);
|
||||
ret = kunwind_next(state);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
@@ -172,9 +203,10 @@ unwind(struct unwind_state *state, stack_trace_consume_fn consume_entry,
|
||||
: stackinfo_get_unknown(); \
|
||||
})
|
||||
|
||||
noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
|
||||
void *cookie, struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
static __always_inline void
|
||||
kunwind_stack_walk(kunwind_consume_fn consume_state,
|
||||
void *cookie, struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct stack_info stacks[] = {
|
||||
stackinfo_get_task(task),
|
||||
@@ -190,22 +222,48 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
|
||||
STACKINFO_EFI,
|
||||
#endif
|
||||
};
|
||||
struct unwind_state state = {
|
||||
.stacks = stacks,
|
||||
.nr_stacks = ARRAY_SIZE(stacks),
|
||||
struct kunwind_state state = {
|
||||
.common = {
|
||||
.stacks = stacks,
|
||||
.nr_stacks = ARRAY_SIZE(stacks),
|
||||
},
|
||||
};
|
||||
|
||||
if (regs) {
|
||||
if (task != current)
|
||||
return;
|
||||
unwind_init_from_regs(&state, regs);
|
||||
kunwind_init_from_regs(&state, regs);
|
||||
} else if (task == current) {
|
||||
unwind_init_from_caller(&state);
|
||||
kunwind_init_from_caller(&state);
|
||||
} else {
|
||||
unwind_init_from_task(&state, task);
|
||||
kunwind_init_from_task(&state, task);
|
||||
}
|
||||
|
||||
unwind(&state, consume_entry, cookie);
|
||||
do_kunwind(&state, consume_state, cookie);
|
||||
}
|
||||
|
||||
struct kunwind_consume_entry_data {
|
||||
stack_trace_consume_fn consume_entry;
|
||||
void *cookie;
|
||||
};
|
||||
|
||||
static bool
|
||||
arch_kunwind_consume_entry(const struct kunwind_state *state, void *cookie)
|
||||
{
|
||||
struct kunwind_consume_entry_data *data = cookie;
|
||||
return data->consume_entry(data->cookie, state->common.pc);
|
||||
}
|
||||
|
||||
noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
|
||||
void *cookie, struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct kunwind_consume_entry_data data = {
|
||||
.consume_entry = consume_entry,
|
||||
.cookie = cookie,
|
||||
};
|
||||
|
||||
kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs);
|
||||
}
|
||||
|
||||
static bool dump_backtrace_entry(void *arg, unsigned long where)
|
||||
|
||||
@@ -118,7 +118,7 @@ endif
|
||||
VDSO_CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os
|
||||
|
||||
# Build rules
|
||||
targets := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso) vdso.so vdso.so.dbg vdso.so.raw
|
||||
targets := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso) vdso.so vdso32.so.dbg vdso.so.raw
|
||||
c-obj-vdso := $(addprefix $(obj)/, $(c-obj-vdso))
|
||||
c-obj-vdso-gettimeofday := $(addprefix $(obj)/, $(c-obj-vdso-gettimeofday))
|
||||
asm-obj-vdso := $(addprefix $(obj)/, $(asm-obj-vdso))
|
||||
@@ -127,15 +127,15 @@ obj-vdso := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso)
|
||||
targets += vdso.lds
|
||||
CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
|
||||
|
||||
include/generated/vdso32-offsets.h: $(obj)/vdso.so.dbg FORCE
|
||||
include/generated/vdso32-offsets.h: $(obj)/vdso32.so.dbg FORCE
|
||||
$(call if_changed,vdsosym)
|
||||
|
||||
# Strip rule for vdso.so
|
||||
$(obj)/vdso.so: OBJCOPYFLAGS := -S
|
||||
$(obj)/vdso.so: $(obj)/vdso.so.dbg FORCE
|
||||
$(obj)/vdso.so: $(obj)/vdso32.so.dbg FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
$(obj)/vdso.so.dbg: $(obj)/vdso.so.raw $(obj)/$(munge) FORCE
|
||||
$(obj)/vdso32.so.dbg: $(obj)/vdso.so.raw $(obj)/$(munge) FORCE
|
||||
$(call if_changed,vdsomunge)
|
||||
|
||||
# Link rule for the .so file, .lds has to be first
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <nvhe/pkvm.h>
|
||||
#include <nvhe/trap_handler.h>
|
||||
|
||||
/* Used by icache_is_vpipt(). */
|
||||
/* Used by icache_is_aliasing(). */
|
||||
unsigned long __icache_flags;
|
||||
|
||||
/* Used by kvm_get_vttbr(). */
|
||||
|
||||
@@ -105,28 +105,6 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
|
||||
dsb(ish);
|
||||
isb();
|
||||
|
||||
/*
|
||||
* If the host is running at EL1 and we have a VPIPT I-cache,
|
||||
* then we must perform I-cache maintenance at EL2 in order for
|
||||
* it to have an effect on the guest. Since the guest cannot hit
|
||||
* I-cache lines allocated with a different VMID, we don't need
|
||||
* to worry about junk out of guest reset (we nuke the I-cache on
|
||||
* VMID rollover), but we do need to be careful when remapping
|
||||
* executable pages for the same guest. This can happen when KSM
|
||||
* takes a CoW fault on an executable page, copies the page into
|
||||
* a page that was previously mapped in the guest and then needs
|
||||
* to invalidate the guest view of the I-cache for that page
|
||||
* from EL1. To solve this, we invalidate the entire I-cache when
|
||||
* unmapping a page from a guest if we have a VPIPT I-cache but
|
||||
* the host is running at EL1. As above, we could do better if
|
||||
* we had the VA.
|
||||
*
|
||||
* The moral of this story is: if you have a VPIPT I-cache, then
|
||||
* you should be running with VHE enabled.
|
||||
*/
|
||||
if (icache_is_vpipt())
|
||||
icache_inval_all_pou();
|
||||
|
||||
__tlb_switch_to_host(&cxt);
|
||||
}
|
||||
|
||||
@@ -157,28 +135,6 @@ void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu,
|
||||
dsb(nsh);
|
||||
isb();
|
||||
|
||||
/*
|
||||
* If the host is running at EL1 and we have a VPIPT I-cache,
|
||||
* then we must perform I-cache maintenance at EL2 in order for
|
||||
* it to have an effect on the guest. Since the guest cannot hit
|
||||
* I-cache lines allocated with a different VMID, we don't need
|
||||
* to worry about junk out of guest reset (we nuke the I-cache on
|
||||
* VMID rollover), but we do need to be careful when remapping
|
||||
* executable pages for the same guest. This can happen when KSM
|
||||
* takes a CoW fault on an executable page, copies the page into
|
||||
* a page that was previously mapped in the guest and then needs
|
||||
* to invalidate the guest view of the I-cache for that page
|
||||
* from EL1. To solve this, we invalidate the entire I-cache when
|
||||
* unmapping a page from a guest if we have a VPIPT I-cache but
|
||||
* the host is running at EL1. As above, we could do better if
|
||||
* we had the VA.
|
||||
*
|
||||
* The moral of this story is: if you have a VPIPT I-cache, then
|
||||
* you should be running with VHE enabled.
|
||||
*/
|
||||
if (icache_is_vpipt())
|
||||
icache_inval_all_pou();
|
||||
|
||||
__tlb_switch_to_host(&cxt);
|
||||
}
|
||||
|
||||
@@ -205,10 +161,6 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
|
||||
dsb(ish);
|
||||
isb();
|
||||
|
||||
/* See the comment in __kvm_tlb_flush_vmid_ipa() */
|
||||
if (icache_is_vpipt())
|
||||
icache_inval_all_pou();
|
||||
|
||||
__tlb_switch_to_host(&cxt);
|
||||
}
|
||||
|
||||
@@ -246,18 +198,5 @@ void __kvm_flush_vm_context(void)
|
||||
/* Same remark as in __tlb_switch_to_guest() */
|
||||
dsb(ish);
|
||||
__tlbi(alle1is);
|
||||
|
||||
/*
|
||||
* VIPT and PIPT caches are not affected by VMID, so no maintenance
|
||||
* is necessary across a VMID rollover.
|
||||
*
|
||||
* VPIPT caches constrain lookup and maintenance to the active VMID,
|
||||
* so we need to invalidate lines with a stale VMID to avoid an ABA
|
||||
* race after multiple rollovers.
|
||||
*
|
||||
*/
|
||||
if (icache_is_vpipt())
|
||||
asm volatile("ic ialluis");
|
||||
|
||||
dsb(ish);
|
||||
}
|
||||
|
||||
@@ -216,18 +216,5 @@ void __kvm_flush_vm_context(void)
|
||||
{
|
||||
dsb(ishst);
|
||||
__tlbi(alle1is);
|
||||
|
||||
/*
|
||||
* VIPT and PIPT caches are not affected by VMID, so no maintenance
|
||||
* is necessary across a VMID rollover.
|
||||
*
|
||||
* VPIPT caches constrain lookup and maintenance to the active VMID,
|
||||
* so we need to invalidate lines with a stale VMID to avoid an ABA
|
||||
* race after multiple rollovers.
|
||||
*
|
||||
*/
|
||||
if (icache_is_vpipt())
|
||||
asm volatile("ic ialluis");
|
||||
|
||||
dsb(ish);
|
||||
}
|
||||
|
||||
@@ -267,9 +267,8 @@ void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu)
|
||||
|
||||
u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 val = kvm_vcpu_read_pmcr(vcpu) >> ARMV8_PMU_PMCR_N_SHIFT;
|
||||
u64 val = FIELD_GET(ARMV8_PMU_PMCR_N, kvm_vcpu_read_pmcr(vcpu));
|
||||
|
||||
val &= ARMV8_PMU_PMCR_N_MASK;
|
||||
if (val == 0)
|
||||
return BIT(ARMV8_PMU_CYCLE_IDX);
|
||||
else
|
||||
@@ -1136,8 +1135,7 @@ u8 kvm_arm_pmu_get_pmuver_limit(void)
|
||||
*/
|
||||
u64 kvm_vcpu_read_pmcr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 pmcr = __vcpu_sys_reg(vcpu, PMCR_EL0) &
|
||||
~(ARMV8_PMU_PMCR_N_MASK << ARMV8_PMU_PMCR_N_SHIFT);
|
||||
u64 pmcr = __vcpu_sys_reg(vcpu, PMCR_EL0);
|
||||
|
||||
return pmcr | ((u64)vcpu->kvm->arch.pmcr_n << ARMV8_PMU_PMCR_N_SHIFT);
|
||||
return u64_replace_bits(pmcr, vcpu->kvm->arch.pmcr_n, ARMV8_PMU_PMCR_N);
|
||||
}
|
||||
|
||||
@@ -877,7 +877,7 @@ static bool pmu_counter_idx_valid(struct kvm_vcpu *vcpu, u64 idx)
|
||||
u64 pmcr, val;
|
||||
|
||||
pmcr = kvm_vcpu_read_pmcr(vcpu);
|
||||
val = (pmcr >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK;
|
||||
val = FIELD_GET(ARMV8_PMU_PMCR_N, pmcr);
|
||||
if (idx >= val && idx != ARMV8_PMU_CYCLE_IDX) {
|
||||
kvm_inject_undefined(vcpu);
|
||||
return false;
|
||||
@@ -1143,7 +1143,7 @@ static int get_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
|
||||
static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
|
||||
u64 val)
|
||||
{
|
||||
u8 new_n = (val >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK;
|
||||
u8 new_n = FIELD_GET(ARMV8_PMU_PMCR_N, val);
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
|
||||
mutex_lock(&kvm->arch.config_lock);
|
||||
|
||||
@@ -18,13 +18,6 @@
|
||||
* x1 - src
|
||||
*/
|
||||
SYM_FUNC_START(__pi_copy_page)
|
||||
alternative_if ARM64_HAS_NO_HW_PREFETCH
|
||||
// Prefetch three cache lines ahead.
|
||||
prfm pldl1strm, [x1, #128]
|
||||
prfm pldl1strm, [x1, #256]
|
||||
prfm pldl1strm, [x1, #384]
|
||||
alternative_else_nop_endif
|
||||
|
||||
ldp x2, x3, [x1]
|
||||
ldp x4, x5, [x1, #16]
|
||||
ldp x6, x7, [x1, #32]
|
||||
@@ -39,10 +32,6 @@ alternative_else_nop_endif
|
||||
1:
|
||||
tst x0, #(PAGE_SIZE - 1)
|
||||
|
||||
alternative_if ARM64_HAS_NO_HW_PREFETCH
|
||||
prfm pldl1strm, [x1, #384]
|
||||
alternative_else_nop_endif
|
||||
|
||||
stnp x2, x3, [x0, #-256]
|
||||
ldp x2, x3, [x1]
|
||||
stnp x4, x5, [x0, #16 - 256]
|
||||
|
||||
+3
-3
@@ -52,9 +52,6 @@ u64 vabits_actual __ro_after_init = VA_BITS_MIN;
|
||||
EXPORT_SYMBOL(vabits_actual);
|
||||
#endif
|
||||
|
||||
u64 kimage_vaddr __ro_after_init = (u64)&_text;
|
||||
EXPORT_SYMBOL(kimage_vaddr);
|
||||
|
||||
u64 kimage_voffset __ro_after_init;
|
||||
EXPORT_SYMBOL(kimage_voffset);
|
||||
|
||||
@@ -674,6 +671,9 @@ static int __init map_entry_trampoline(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!arm64_kernel_unmapped_at_el0())
|
||||
return 0;
|
||||
|
||||
pgprot_t prot = kernel_exec_prot();
|
||||
phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start);
|
||||
|
||||
|
||||
@@ -37,10 +37,10 @@ HAS_GIC_PRIO_MASKING
|
||||
HAS_GIC_PRIO_RELAXED_SYNC
|
||||
HAS_HCX
|
||||
HAS_LDAPR
|
||||
HAS_LPA2
|
||||
HAS_LSE_ATOMICS
|
||||
HAS_MOPS
|
||||
HAS_NESTED_VIRT
|
||||
HAS_NO_HW_PREFETCH
|
||||
HAS_PAN
|
||||
HAS_S1PIE
|
||||
HAS_RAS_EXTN
|
||||
|
||||
+312
-13
@@ -1002,6 +1002,27 @@ UnsignedEnum 3:0 BT
|
||||
EndEnum
|
||||
EndSysreg
|
||||
|
||||
Sysreg ID_AA64PFR2_EL1 3 0 0 4 2
|
||||
Res0 63:36
|
||||
UnsignedEnum 35:32 FPMR
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
Res0 31:12
|
||||
UnsignedEnum 11:8 MTEFAR
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 7:4 MTESTOREONLY
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 3:0 MTEPERM
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
EndSysreg
|
||||
|
||||
Sysreg ID_AA64ZFR0_EL1 3 0 0 4 4
|
||||
Res0 63:60
|
||||
UnsignedEnum 59:56 F64MM
|
||||
@@ -1058,7 +1079,11 @@ UnsignedEnum 63 FA64
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
Res0 62:60
|
||||
Res0 62:61
|
||||
UnsignedEnum 60 LUTv2
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 59:56 SMEver
|
||||
0b0000 SME
|
||||
0b0001 SME2
|
||||
@@ -1086,7 +1111,14 @@ UnsignedEnum 42 F16F16
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
Res0 41:40
|
||||
UnsignedEnum 41 F8F16
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 40 F8F32
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 39:36 I8I32
|
||||
0b0000 NI
|
||||
0b1111 IMP
|
||||
@@ -1107,7 +1139,49 @@ UnsignedEnum 32 F32F32
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
Res0 31:0
|
||||
Res0 31
|
||||
UnsignedEnum 30 SF8FMA
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 29 SF8DP4
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 28 SF8DP2
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
Res0 27:0
|
||||
EndSysreg
|
||||
|
||||
Sysreg ID_AA64FPFR0_EL1 3 0 0 4 7
|
||||
Res0 63:32
|
||||
UnsignedEnum 31 F8CVT
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 30 F8FMA
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 29 F8DP4
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 28 F8DP2
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
Res0 27:2
|
||||
UnsignedEnum 1 F8E4M3
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 0 F8E5M2
|
||||
0b0 NI
|
||||
0b1 IMP
|
||||
EndEnum
|
||||
EndSysreg
|
||||
|
||||
Sysreg ID_AA64DFR0_EL1 3 0 0 5 0
|
||||
@@ -1115,7 +1189,10 @@ Enum 63:60 HPMN0
|
||||
0b0000 UNPREDICTABLE
|
||||
0b0001 DEF
|
||||
EndEnum
|
||||
Res0 59:56
|
||||
UnsignedEnum 59:56 ExtTrcBuff
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 55:52 BRBE
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
@@ -1327,6 +1404,7 @@ UnsignedEnum 11:8 API
|
||||
0b0011 PAuth2
|
||||
0b0100 FPAC
|
||||
0b0101 FPACCOMBINE
|
||||
0b0110 PAuth_LR
|
||||
EndEnum
|
||||
UnsignedEnum 7:4 APA
|
||||
0b0000 NI
|
||||
@@ -1335,6 +1413,7 @@ UnsignedEnum 7:4 APA
|
||||
0b0011 PAuth2
|
||||
0b0100 FPAC
|
||||
0b0101 FPACCOMBINE
|
||||
0b0110 PAuth_LR
|
||||
EndEnum
|
||||
UnsignedEnum 3:0 DPB
|
||||
0b0000 NI
|
||||
@@ -1344,7 +1423,14 @@ EndEnum
|
||||
EndSysreg
|
||||
|
||||
Sysreg ID_AA64ISAR2_EL1 3 0 0 6 2
|
||||
Res0 63:56
|
||||
UnsignedEnum 63:60 ATS1A
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 59:56 LUT
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 55:52 CSSC
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
@@ -1353,7 +1439,19 @@ UnsignedEnum 51:48 RPRFM
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
Res0 47:32
|
||||
Res0 47:44
|
||||
UnsignedEnum 43:40 PRFMSLC
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 39:36 SYSINSTR_128
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 35:32 SYSREG_128
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 31:28 CLRBHB
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
@@ -1377,6 +1475,7 @@ UnsignedEnum 15:12 APA3
|
||||
0b0011 PAuth2
|
||||
0b0100 FPAC
|
||||
0b0101 FPACCOMBINE
|
||||
0b0110 PAuth_LR
|
||||
EndEnum
|
||||
UnsignedEnum 11:8 GPA3
|
||||
0b0000 NI
|
||||
@@ -1392,6 +1491,23 @@ UnsignedEnum 3:0 WFxT
|
||||
EndEnum
|
||||
EndSysreg
|
||||
|
||||
Sysreg ID_AA64ISAR3_EL1 3 0 0 6 3
|
||||
Res0 63:12
|
||||
UnsignedEnum 11:8 TLBIW
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 7:4 FAMINMAX
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
EndEnum
|
||||
UnsignedEnum 3:0 CPA
|
||||
0b0000 NI
|
||||
0b0001 IMP
|
||||
0b0010 CPA2
|
||||
EndEnum
|
||||
EndSysreg
|
||||
|
||||
Sysreg ID_AA64MMFR0_EL1 3 0 0 7 0
|
||||
UnsignedEnum 63:60 ECV
|
||||
0b0000 NI
|
||||
@@ -1680,7 +1796,8 @@ Field 63 TIDCP
|
||||
Field 62 SPINTMASK
|
||||
Field 61 NMI
|
||||
Field 60 EnTP2
|
||||
Res0 59:58
|
||||
Field 59 TCSO
|
||||
Field 58 TCSO0
|
||||
Field 57 EPAN
|
||||
Field 56 EnALS
|
||||
Field 55 EnAS0
|
||||
@@ -1709,7 +1826,7 @@ EndEnum
|
||||
Field 37 ITFSB
|
||||
Field 36 BT1
|
||||
Field 35 BT0
|
||||
Res0 34
|
||||
Field 34 EnFPM
|
||||
Field 33 MSCEn
|
||||
Field 32 CMOW
|
||||
Field 31 EnIA
|
||||
@@ -1747,7 +1864,8 @@ Field 0 M
|
||||
EndSysreg
|
||||
|
||||
SysregFields CPACR_ELx
|
||||
Res0 63:29
|
||||
Res0 63:30
|
||||
Field 29 E0POE
|
||||
Field 28 TTA
|
||||
Res0 27:26
|
||||
Field 25:24 SMEN
|
||||
@@ -1790,6 +1908,41 @@ Sysreg SMCR_EL1 3 0 1 2 6
|
||||
Fields SMCR_ELx
|
||||
EndSysreg
|
||||
|
||||
SysregFields GCSCR_ELx
|
||||
Res0 63:10
|
||||
Field 9 STREn
|
||||
Field 8 PUSHMEn
|
||||
Res0 7
|
||||
Field 6 EXLOCKEN
|
||||
Field 5 RVCHKEN
|
||||
Res0 4:1
|
||||
Field 0 PCRSEL
|
||||
EndSysregFields
|
||||
|
||||
Sysreg GCSCR_EL1 3 0 2 5 0
|
||||
Fields GCSCR_ELx
|
||||
EndSysreg
|
||||
|
||||
SysregFields GCSPR_ELx
|
||||
Field 63:3 PTR
|
||||
Res0 2:0
|
||||
EndSysregFields
|
||||
|
||||
Sysreg GCSPR_EL1 3 0 2 5 1
|
||||
Fields GCSPR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg GCSCRE0_EL1 3 0 2 5 2
|
||||
Res0 63:11
|
||||
Field 10 nTR
|
||||
Field 9 STREn
|
||||
Field 8 PUSHMEn
|
||||
Res0 7:6
|
||||
Field 5 RVCHKEN
|
||||
Res0 4:1
|
||||
Field 0 PCRSEL
|
||||
EndSysreg
|
||||
|
||||
Sysreg ALLINT 3 0 4 3 0
|
||||
Res0 63:14
|
||||
Field 13 ALLINT
|
||||
@@ -1933,10 +2086,18 @@ Sysreg CONTEXTIDR_EL1 3 0 13 0 1
|
||||
Fields CONTEXTIDR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg RCWSMASK_EL1 3 0 13 0 3
|
||||
Field 63:0 RCWSMASK
|
||||
EndSysreg
|
||||
|
||||
Sysreg TPIDR_EL1 3 0 13 0 4
|
||||
Field 63:0 ThreadID
|
||||
EndSysreg
|
||||
|
||||
Sysreg RCWMASK_EL1 3 0 13 0 6
|
||||
Field 63:0 RCWMASK
|
||||
EndSysreg
|
||||
|
||||
Sysreg SCXTNUM_EL1 3 0 13 0 7
|
||||
Field 63:0 SoftwareContextNumber
|
||||
EndSysreg
|
||||
@@ -2004,9 +2165,10 @@ Field 27:24 CWG
|
||||
Field 23:20 ERG
|
||||
Field 19:16 DminLine
|
||||
Enum 15:14 L1Ip
|
||||
0b00 VPIPT
|
||||
# This was named as VPIPT in the ARM but now documented as reserved
|
||||
0b00 RESERVED_VPIPT
|
||||
# This is named as AIVIVT in the ARM but documented as reserved
|
||||
0b01 RESERVED
|
||||
0b01 RESERVED_AIVIVT
|
||||
0b10 VIPT
|
||||
0b11 PIPT
|
||||
EndEnum
|
||||
@@ -2020,12 +2182,39 @@ Field 4 DZP
|
||||
Field 3:0 BS
|
||||
EndSysreg
|
||||
|
||||
Sysreg GCSPR_EL0 3 3 2 5 1
|
||||
Fields GCSPR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg SVCR 3 3 4 2 2
|
||||
Res0 63:2
|
||||
Field 1 ZA
|
||||
Field 0 SM
|
||||
EndSysreg
|
||||
|
||||
Sysreg FPMR 3 3 4 4 2
|
||||
Res0 63:38
|
||||
Field 37:32 LSCALE2
|
||||
Field 31:24 NSCALE
|
||||
Res0 23
|
||||
Field 22:16 LSCALE
|
||||
Field 15 OSC
|
||||
Field 14 OSM
|
||||
Res0 13:9
|
||||
UnsignedEnum 8:6 F8D
|
||||
0b000 E5M2
|
||||
0b001 E4M3
|
||||
EndEnum
|
||||
UnsignedEnum 5:3 F8S2
|
||||
0b000 E5M2
|
||||
0b001 E4M3
|
||||
EndEnum
|
||||
UnsignedEnum 2:0 F8S1
|
||||
0b000 E5M2
|
||||
0b001 E4M3
|
||||
EndEnum
|
||||
EndSysreg
|
||||
|
||||
SysregFields HFGxTR_EL2
|
||||
Field 63 nAMAIR2_EL1
|
||||
Field 62 nMAIR2_EL1
|
||||
@@ -2102,7 +2291,9 @@ Fields HFGxTR_EL2
|
||||
EndSysreg
|
||||
|
||||
Sysreg HFGITR_EL2 3 4 1 1 6
|
||||
Res0 63:61
|
||||
Res0 63
|
||||
Field 62 ATS1E1A
|
||||
Res0 61
|
||||
Field 60 COSPRCTX
|
||||
Field 59 nGCSEPP
|
||||
Field 58 nGCSSTR_EL1
|
||||
@@ -2295,12 +2486,57 @@ Field 1 DBGBVRn_EL1
|
||||
Field 0 DBGBCRn_EL1
|
||||
EndSysreg
|
||||
|
||||
Sysreg HAFGRTR_EL2 3 4 3 1 6
|
||||
Res0 63:50
|
||||
Field 49 AMEVTYPER115_EL0
|
||||
Field 48 AMEVCNTR115_EL0
|
||||
Field 47 AMEVTYPER114_EL0
|
||||
Field 46 AMEVCNTR114_EL0
|
||||
Field 45 AMEVTYPER113_EL0
|
||||
Field 44 AMEVCNTR113_EL0
|
||||
Field 43 AMEVTYPER112_EL0
|
||||
Field 42 AMEVCNTR112_EL0
|
||||
Field 41 AMEVTYPER111_EL0
|
||||
Field 40 AMEVCNTR111_EL0
|
||||
Field 39 AMEVTYPER110_EL0
|
||||
Field 38 AMEVCNTR110_EL0
|
||||
Field 37 AMEVTYPER19_EL0
|
||||
Field 36 AMEVCNTR19_EL0
|
||||
Field 35 AMEVTYPER18_EL0
|
||||
Field 34 AMEVCNTR18_EL0
|
||||
Field 33 AMEVTYPER17_EL0
|
||||
Field 32 AMEVCNTR17_EL0
|
||||
Field 31 AMEVTYPER16_EL0
|
||||
Field 30 AMEVCNTR16_EL0
|
||||
Field 29 AMEVTYPER15_EL0
|
||||
Field 28 AMEVCNTR15_EL0
|
||||
Field 27 AMEVTYPER14_EL0
|
||||
Field 26 AMEVCNTR14_EL0
|
||||
Field 25 AMEVTYPER13_EL0
|
||||
Field 24 AMEVCNTR13_EL0
|
||||
Field 23 AMEVTYPER12_EL0
|
||||
Field 22 AMEVCNTR12_EL0
|
||||
Field 21 AMEVTYPER11_EL0
|
||||
Field 20 AMEVCNTR11_EL0
|
||||
Field 19 AMEVTYPER10_EL0
|
||||
Field 18 AMEVCNTR10_EL0
|
||||
Field 17 AMCNTEN1
|
||||
Res0 16:5
|
||||
Field 4 AMEVCNTR03_EL0
|
||||
Field 3 AMEVCNTR02_EL0
|
||||
Field 2 AMEVCNTR01_EL0
|
||||
Field 1 AMEVCNTR00_EL0
|
||||
Field 0 AMCNTEN0
|
||||
EndSysreg
|
||||
|
||||
Sysreg ZCR_EL2 3 4 1 2 0
|
||||
Fields ZCR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg HCRX_EL2 3 4 1 2 2
|
||||
Res0 63:23
|
||||
Res0 63:25
|
||||
Field 24 PACMEn
|
||||
Field 23 EnFPM
|
||||
Field 22 GCSEn
|
||||
Field 21 EnIDCP128
|
||||
Field 20 EnSDERR
|
||||
@@ -2348,6 +2584,14 @@ Sysreg SMCR_EL2 3 4 1 2 6
|
||||
Fields SMCR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg GCSCR_EL2 3 4 2 5 0
|
||||
Fields GCSCR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg GCSPR_EL2 3 4 2 5 1
|
||||
Fields GCSPR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg DACR32_EL2 3 4 3 0 0
|
||||
Res0 63:32
|
||||
Field 31:30 D15
|
||||
@@ -2407,6 +2651,14 @@ Sysreg SMCR_EL12 3 5 1 2 6
|
||||
Fields SMCR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg GCSCR_EL12 3 5 2 5 0
|
||||
Fields GCSCR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg GCSPR_EL12 3 5 2 5 1
|
||||
Fields GCSPR_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg FAR_EL12 3 5 6 0 0
|
||||
Field 63:0 ADDR
|
||||
EndSysreg
|
||||
@@ -2471,6 +2723,33 @@ Field 1 PIE
|
||||
Field 0 PnCH
|
||||
EndSysreg
|
||||
|
||||
SysregFields MAIR2_ELx
|
||||
Field 63:56 Attr7
|
||||
Field 55:48 Attr6
|
||||
Field 47:40 Attr5
|
||||
Field 39:32 Attr4
|
||||
Field 31:24 Attr3
|
||||
Field 23:16 Attr2
|
||||
Field 15:8 Attr1
|
||||
Field 7:0 Attr0
|
||||
EndSysregFields
|
||||
|
||||
Sysreg MAIR2_EL1 3 0 10 2 1
|
||||
Fields MAIR2_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg MAIR2_EL2 3 4 10 1 1
|
||||
Fields MAIR2_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg AMAIR2_EL1 3 0 10 3 1
|
||||
Field 63:0 ImpDef
|
||||
EndSysreg
|
||||
|
||||
Sysreg AMAIR2_EL2 3 4 10 3 1
|
||||
Field 63:0 ImpDef
|
||||
EndSysreg
|
||||
|
||||
SysregFields PIRx_ELx
|
||||
Field 63:60 Perm15
|
||||
Field 59:56 Perm14
|
||||
@@ -2510,6 +2789,26 @@ Sysreg PIR_EL2 3 4 10 2 3
|
||||
Fields PIRx_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg POR_EL0 3 3 10 2 4
|
||||
Fields PIRx_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg POR_EL1 3 0 10 2 4
|
||||
Fields PIRx_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg POR_EL12 3 5 10 2 4
|
||||
Fields PIRx_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg S2POR_EL1 3 0 10 2 5
|
||||
Fields PIRx_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg S2PIR_EL2 3 4 10 2 5
|
||||
Fields PIRx_ELx
|
||||
EndSysreg
|
||||
|
||||
Sysreg LORSA_EL1 3 0 10 4 0
|
||||
Res0 63:52
|
||||
Field 51:16 SA
|
||||
|
||||
@@ -453,6 +453,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -550,7 +551,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -410,6 +410,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -507,7 +508,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -430,6 +430,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -527,7 +528,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -402,6 +402,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -499,7 +500,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -412,6 +412,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -509,7 +510,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -269,9 +269,6 @@ CONFIG_RDS_TCP=m
|
||||
CONFIG_L2TP=m
|
||||
CONFIG_BRIDGE=m
|
||||
CONFIG_ATALK=m
|
||||
CONFIG_DEV_APPLETALK=m
|
||||
CONFIG_IPDDP=m
|
||||
CONFIG_IPDDP_ENCAP=y
|
||||
CONFIG_6LOWPAN=m
|
||||
CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
|
||||
CONFIG_6LOWPAN_GHC_UDP=m
|
||||
@@ -432,6 +429,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -529,7 +527,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -289,9 +289,6 @@ CONFIG_RDS_TCP=m
|
||||
CONFIG_L2TP=m
|
||||
CONFIG_BRIDGE=m
|
||||
CONFIG_ATALK=m
|
||||
CONFIG_DEV_APPLETALK=m
|
||||
CONFIG_IPDDP=m
|
||||
CONFIG_IPDDP_ENCAP=y
|
||||
CONFIG_6LOWPAN=m
|
||||
CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
|
||||
CONFIG_6LOWPAN_GHC_UDP=m
|
||||
@@ -518,6 +515,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -615,7 +613,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -401,6 +401,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -498,7 +499,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -402,6 +402,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -499,7 +500,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -419,6 +419,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -516,7 +517,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -400,6 +400,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -497,7 +498,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -400,6 +400,7 @@ CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
CONFIG_BCACHEFS_FS=m
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
@@ -497,7 +498,6 @@ CONFIG_NLS_MAC_TURKISH=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_ENCRYPTED_KEYS=m
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
|
||||
@@ -189,6 +189,7 @@ config PPC
|
||||
select EDAC_ATOMIC_SCRUB
|
||||
select EDAC_SUPPORT
|
||||
select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY if ARCH_USING_PATCHABLE_FUNCTION_ENTRY
|
||||
select FUNCTION_ALIGNMENT_4B
|
||||
select GENERIC_ATOMIC64 if PPC32
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
|
||||
select GENERIC_CMOS_UPDATE
|
||||
|
||||
@@ -271,7 +271,6 @@ config PPC_EARLY_DEBUG_USBGECKO
|
||||
config PPC_EARLY_DEBUG_PS3GELIC
|
||||
bool "Early debugging through the PS3 Ethernet port"
|
||||
depends on PPC_PS3
|
||||
select PS3GELIC_UDBG
|
||||
help
|
||||
Select this to enable early debugging for the PlayStation3 via
|
||||
UDP broadcasts sent out through the Ethernet port.
|
||||
|
||||
+18
-7
@@ -10,15 +10,26 @@
|
||||
# Rewritten by Cort Dougan and Paul Mackerras
|
||||
#
|
||||
|
||||
ifdef cross_compiling
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
# Auto detect cross compiler prefix.
|
||||
# Look for: (powerpc(64(le)?)?)(-unknown)?-linux(-gnu)?-
|
||||
CC_ARCHES := powerpc powerpc64 powerpc64le
|
||||
CC_SUFFIXES := linux linux-gnu unknown-linux-gnu
|
||||
CROSS_COMPILE := $(call cc-cross-prefix, $(foreach a,$(CC_ARCHES), \
|
||||
$(foreach s,$(CC_SUFFIXES),$(a)-$(s)-)))
|
||||
endif
|
||||
endif
|
||||
|
||||
HAS_BIARCH := $(call cc-option-yn, -m32)
|
||||
|
||||
# Set default 32 bits cross compilers for vdso and boot wrapper
|
||||
CROSS32_COMPILE ?=
|
||||
|
||||
# If we're on a ppc/ppc64/ppc64le machine use that defconfig, otherwise just use
|
||||
# ppc64_defconfig because we have nothing better to go on.
|
||||
# ppc64le_defconfig because we have nothing better to go on.
|
||||
uname := $(shell uname -m)
|
||||
KBUILD_DEFCONFIG := $(if $(filter ppc%,$(uname)),$(uname),ppc64)_defconfig
|
||||
KBUILD_DEFCONFIG := $(if $(filter ppc%,$(uname)),$(uname),ppc64le)_defconfig
|
||||
|
||||
new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
|
||||
|
||||
@@ -161,7 +172,7 @@ CFLAGS-y += $(CONFIG_TUNE_CPU)
|
||||
|
||||
asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1)
|
||||
|
||||
KBUILD_CPPFLAGS += -I $(srctree)/arch/$(ARCH) $(asinstr)
|
||||
KBUILD_CPPFLAGS += -I $(srctree)/arch/powerpc $(asinstr)
|
||||
KBUILD_AFLAGS += $(AFLAGS-y)
|
||||
KBUILD_CFLAGS += $(call cc-option,-msoft-float)
|
||||
KBUILD_CFLAGS += $(CFLAGS-y)
|
||||
@@ -232,7 +243,7 @@ BOOT_TARGETS2 := zImage% dtbImage% treeImage.% cuImage.% simpleImage.% uImage.%
|
||||
|
||||
PHONY += $(BOOT_TARGETS1) $(BOOT_TARGETS2)
|
||||
|
||||
boot := arch/$(ARCH)/boot
|
||||
boot := arch/powerpc/boot
|
||||
|
||||
$(BOOT_TARGETS1): vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
|
||||
@@ -336,7 +347,7 @@ PHONY += $(generated_configs)
|
||||
|
||||
define archhelp
|
||||
echo '* zImage - Build default images selected by kernel config'
|
||||
echo ' zImage.* - Compressed kernel image (arch/$(ARCH)/boot/zImage.*)'
|
||||
echo ' zImage.* - Compressed kernel image (arch/powerpc/boot/zImage.*)'
|
||||
echo ' uImage - U-Boot native image format'
|
||||
echo ' cuImage.<dt> - Backwards compatible U-Boot image for older'
|
||||
echo ' versions which do not support device trees'
|
||||
@@ -347,12 +358,12 @@ define archhelp
|
||||
echo ' (your) ~/bin/$(INSTALLKERNEL) or'
|
||||
echo ' (distribution) /sbin/$(INSTALLKERNEL) or'
|
||||
echo ' install to $$(INSTALL_PATH) and run lilo'
|
||||
echo ' *_defconfig - Select default config from arch/$(ARCH)/configs'
|
||||
echo ' *_defconfig - Select default config from arch/powerpc/configs'
|
||||
echo ''
|
||||
echo ' Targets with <dt> embed a device tree blob inside the image'
|
||||
echo ' These targets support board with firmware that does not'
|
||||
echo ' support passing a device tree directly. Replace <dt> with the'
|
||||
echo ' name of a dts file from the arch/$(ARCH)/boot/dts/ directory'
|
||||
echo ' name of a dts file from the arch/powerpc/boot/dts/ directory'
|
||||
echo ' (minus the .dts extension).'
|
||||
echo
|
||||
$(foreach cfg,$(generated_configs),
|
||||
|
||||
@@ -367,45 +367,46 @@
|
||||
reg = <0xf0000 0x1000>;
|
||||
interrupts = <18 2 0 0>;
|
||||
fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x30061>;
|
||||
fsl,tmu-calibration = <0x00000000 0x0000000f
|
||||
0x00000001 0x00000017
|
||||
0x00000002 0x0000001e
|
||||
0x00000003 0x00000026
|
||||
0x00000004 0x0000002e
|
||||
0x00000005 0x00000035
|
||||
0x00000006 0x0000003d
|
||||
0x00000007 0x00000044
|
||||
0x00000008 0x0000004c
|
||||
0x00000009 0x00000053
|
||||
0x0000000a 0x0000005b
|
||||
0x0000000b 0x00000064
|
||||
fsl,tmu-calibration =
|
||||
<0x00000000 0x0000000f>,
|
||||
<0x00000001 0x00000017>,
|
||||
<0x00000002 0x0000001e>,
|
||||
<0x00000003 0x00000026>,
|
||||
<0x00000004 0x0000002e>,
|
||||
<0x00000005 0x00000035>,
|
||||
<0x00000006 0x0000003d>,
|
||||
<0x00000007 0x00000044>,
|
||||
<0x00000008 0x0000004c>,
|
||||
<0x00000009 0x00000053>,
|
||||
<0x0000000a 0x0000005b>,
|
||||
<0x0000000b 0x00000064>,
|
||||
|
||||
0x00010000 0x00000011
|
||||
0x00010001 0x0000001c
|
||||
0x00010002 0x00000024
|
||||
0x00010003 0x0000002b
|
||||
0x00010004 0x00000034
|
||||
0x00010005 0x00000039
|
||||
0x00010006 0x00000042
|
||||
0x00010007 0x0000004c
|
||||
0x00010008 0x00000051
|
||||
0x00010009 0x0000005a
|
||||
0x0001000a 0x00000063
|
||||
<0x00010000 0x00000011>,
|
||||
<0x00010001 0x0000001c>,
|
||||
<0x00010002 0x00000024>,
|
||||
<0x00010003 0x0000002b>,
|
||||
<0x00010004 0x00000034>,
|
||||
<0x00010005 0x00000039>,
|
||||
<0x00010006 0x00000042>,
|
||||
<0x00010007 0x0000004c>,
|
||||
<0x00010008 0x00000051>,
|
||||
<0x00010009 0x0000005a>,
|
||||
<0x0001000a 0x00000063>,
|
||||
|
||||
0x00020000 0x00000013
|
||||
0x00020001 0x00000019
|
||||
0x00020002 0x00000024
|
||||
0x00020003 0x0000002c
|
||||
0x00020004 0x00000035
|
||||
0x00020005 0x0000003d
|
||||
0x00020006 0x00000046
|
||||
0x00020007 0x00000050
|
||||
0x00020008 0x00000059
|
||||
<0x00020000 0x00000013>,
|
||||
<0x00020001 0x00000019>,
|
||||
<0x00020002 0x00000024>,
|
||||
<0x00020003 0x0000002c>,
|
||||
<0x00020004 0x00000035>,
|
||||
<0x00020005 0x0000003d>,
|
||||
<0x00020006 0x00000046>,
|
||||
<0x00020007 0x00000050>,
|
||||
<0x00020008 0x00000059>,
|
||||
|
||||
0x00030000 0x00000002
|
||||
0x00030001 0x0000000d
|
||||
0x00030002 0x00000019
|
||||
0x00030003 0x00000024>;
|
||||
<0x00030000 0x00000002>,
|
||||
<0x00030001 0x0000000d>,
|
||||
<0x00030002 0x00000019>,
|
||||
<0x00030003 0x00000024>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
||||
|
||||
@@ -447,41 +447,42 @@
|
||||
reg = <0xf0000 0x1000>;
|
||||
interrupts = <18 2 0 0>;
|
||||
fsl,tmu-range = <0xa0000 0x90026 0x8004a 0x1006a>;
|
||||
fsl,tmu-calibration = <0x00000000 0x00000025
|
||||
0x00000001 0x00000028
|
||||
0x00000002 0x0000002d
|
||||
0x00000003 0x00000031
|
||||
0x00000004 0x00000036
|
||||
0x00000005 0x0000003a
|
||||
0x00000006 0x00000040
|
||||
0x00000007 0x00000044
|
||||
0x00000008 0x0000004a
|
||||
0x00000009 0x0000004f
|
||||
0x0000000a 0x00000054
|
||||
fsl,tmu-calibration =
|
||||
<0x00000000 0x00000025>,
|
||||
<0x00000001 0x00000028>,
|
||||
<0x00000002 0x0000002d>,
|
||||
<0x00000003 0x00000031>,
|
||||
<0x00000004 0x00000036>,
|
||||
<0x00000005 0x0000003a>,
|
||||
<0x00000006 0x00000040>,
|
||||
<0x00000007 0x00000044>,
|
||||
<0x00000008 0x0000004a>,
|
||||
<0x00000009 0x0000004f>,
|
||||
<0x0000000a 0x00000054>,
|
||||
|
||||
0x00010000 0x0000000d
|
||||
0x00010001 0x00000013
|
||||
0x00010002 0x00000019
|
||||
0x00010003 0x0000001f
|
||||
0x00010004 0x00000025
|
||||
0x00010005 0x0000002d
|
||||
0x00010006 0x00000033
|
||||
0x00010007 0x00000043
|
||||
0x00010008 0x0000004b
|
||||
0x00010009 0x00000053
|
||||
<0x00010000 0x0000000d>,
|
||||
<0x00010001 0x00000013>,
|
||||
<0x00010002 0x00000019>,
|
||||
<0x00010003 0x0000001f>,
|
||||
<0x00010004 0x00000025>,
|
||||
<0x00010005 0x0000002d>,
|
||||
<0x00010006 0x00000033>,
|
||||
<0x00010007 0x00000043>,
|
||||
<0x00010008 0x0000004b>,
|
||||
<0x00010009 0x00000053>,
|
||||
|
||||
0x00020000 0x00000010
|
||||
0x00020001 0x00000017
|
||||
0x00020002 0x0000001f
|
||||
0x00020003 0x00000029
|
||||
0x00020004 0x00000031
|
||||
0x00020005 0x0000003c
|
||||
0x00020006 0x00000042
|
||||
0x00020007 0x0000004d
|
||||
0x00020008 0x00000056
|
||||
<0x00020000 0x00000010>,
|
||||
<0x00020001 0x00000017>,
|
||||
<0x00020002 0x0000001f>,
|
||||
<0x00020003 0x00000029>,
|
||||
<0x00020004 0x00000031>,
|
||||
<0x00020005 0x0000003c>,
|
||||
<0x00020006 0x00000042>,
|
||||
<0x00020007 0x0000004d>,
|
||||
<0x00020008 0x00000056>,
|
||||
|
||||
0x00030000 0x00000012
|
||||
0x00030001 0x0000001d>;
|
||||
<0x00030000 0x00000012>,
|
||||
<0x00030001 0x0000001d>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_MEM_SOFT_DIRTY=y
|
||||
CONFIG_ZONE_DEVICE=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
|
||||
@@ -24,6 +24,7 @@ CONFIG_PS3_VRAM=m
|
||||
CONFIG_PS3_LPM=m
|
||||
# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
|
||||
CONFIG_KEXEC=y
|
||||
# CONFIG_PPC64_BIG_ENDIAN_ELF_ABI_V2 is not set
|
||||
CONFIG_PPC_4K_PAGES=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_PM=y
|
||||
|
||||
@@ -17,12 +17,6 @@
|
||||
#define _PAGE_EXEC 0x00001 /* execute permission */
|
||||
#define _PAGE_WRITE 0x00002 /* write access allowed */
|
||||
#define _PAGE_READ 0x00004 /* read access allowed */
|
||||
#define _PAGE_NA _PAGE_PRIVILEGED
|
||||
#define _PAGE_NAX _PAGE_EXEC
|
||||
#define _PAGE_RO _PAGE_READ
|
||||
#define _PAGE_ROX (_PAGE_READ | _PAGE_EXEC)
|
||||
#define _PAGE_RW (_PAGE_READ | _PAGE_WRITE)
|
||||
#define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)
|
||||
#define _PAGE_PRIVILEGED 0x00008 /* kernel access only */
|
||||
#define _PAGE_SAO 0x00010 /* Strong access order */
|
||||
#define _PAGE_NON_IDEMPOTENT 0x00020 /* non idempotent memory */
|
||||
@@ -532,8 +526,8 @@ static inline bool pte_user(pte_t pte)
|
||||
static inline bool pte_access_permitted(pte_t pte, bool write)
|
||||
{
|
||||
/*
|
||||
* _PAGE_READ is needed for any access and will be
|
||||
* cleared for PROT_NONE
|
||||
* _PAGE_READ is needed for any access and will be cleared for
|
||||
* PROT_NONE. Execute-only mapping via PROT_EXEC also returns false.
|
||||
*/
|
||||
if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte))
|
||||
return false;
|
||||
|
||||
@@ -158,11 +158,6 @@ static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma,
|
||||
*/
|
||||
}
|
||||
|
||||
static inline bool __pte_protnone(unsigned long pte)
|
||||
{
|
||||
return (pte & (pgprot_val(PAGE_NONE) | _PAGE_RWX)) == pgprot_val(PAGE_NONE);
|
||||
}
|
||||
|
||||
static inline bool __pte_flags_need_flush(unsigned long oldval,
|
||||
unsigned long newval)
|
||||
{
|
||||
@@ -179,8 +174,8 @@ static inline bool __pte_flags_need_flush(unsigned long oldval,
|
||||
/*
|
||||
* We do not expect kernel mappings or non-PTEs or not-present PTEs.
|
||||
*/
|
||||
VM_WARN_ON_ONCE(!__pte_protnone(oldval) && oldval & _PAGE_PRIVILEGED);
|
||||
VM_WARN_ON_ONCE(!__pte_protnone(newval) && newval & _PAGE_PRIVILEGED);
|
||||
VM_WARN_ON_ONCE(oldval & _PAGE_PRIVILEGED);
|
||||
VM_WARN_ON_ONCE(newval & _PAGE_PRIVILEGED);
|
||||
VM_WARN_ON_ONCE(!(oldval & _PAGE_PTE));
|
||||
VM_WARN_ON_ONCE(!(newval & _PAGE_PTE));
|
||||
VM_WARN_ON_ONCE(!(oldval & _PAGE_PRESENT));
|
||||
|
||||
@@ -25,7 +25,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY))
|
||||
addr += MCOUNT_INSN_SIZE;
|
||||
|
||||
return addr;
|
||||
return addr;
|
||||
}
|
||||
|
||||
unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
|
||||
|
||||
@@ -349,7 +349,16 @@
|
||||
#define H_GET_ENERGY_SCALE_INFO 0x450
|
||||
#define H_PKS_SIGNED_UPDATE 0x454
|
||||
#define H_WATCHDOG 0x45C
|
||||
#define MAX_HCALL_OPCODE H_WATCHDOG
|
||||
#define H_GUEST_GET_CAPABILITIES 0x460
|
||||
#define H_GUEST_SET_CAPABILITIES 0x464
|
||||
#define H_GUEST_CREATE 0x470
|
||||
#define H_GUEST_CREATE_VCPU 0x474
|
||||
#define H_GUEST_GET_STATE 0x478
|
||||
#define H_GUEST_SET_STATE 0x47C
|
||||
#define H_GUEST_RUN_VCPU 0x480
|
||||
#define H_GUEST_COPY_MEMORY 0x484
|
||||
#define H_GUEST_DELETE 0x488
|
||||
#define MAX_HCALL_OPCODE H_GUEST_DELETE
|
||||
|
||||
/* Scope args for H_SCM_UNBIND_ALL */
|
||||
#define H_UNBIND_SCOPE_ALL (0x1)
|
||||
@@ -393,15 +402,6 @@
|
||||
#define H_ENTER_NESTED 0xF804
|
||||
#define H_TLB_INVALIDATE 0xF808
|
||||
#define H_COPY_TOFROM_GUEST 0xF80C
|
||||
#define H_GUEST_GET_CAPABILITIES 0x460
|
||||
#define H_GUEST_SET_CAPABILITIES 0x464
|
||||
#define H_GUEST_CREATE 0x470
|
||||
#define H_GUEST_CREATE_VCPU 0x474
|
||||
#define H_GUEST_GET_STATE 0x478
|
||||
#define H_GUEST_SET_STATE 0x47C
|
||||
#define H_GUEST_RUN_VCPU 0x480
|
||||
#define H_GUEST_COPY_MEMORY 0x484
|
||||
#define H_GUEST_DELETE 0x488
|
||||
|
||||
/* Flags for H_SVM_PAGE_IN */
|
||||
#define H_PAGE_IN_SHARED 0x1
|
||||
|
||||
@@ -302,6 +302,7 @@ void kvmhv_nested_exit(void);
|
||||
void kvmhv_vm_nested_init(struct kvm *kvm);
|
||||
long kvmhv_set_partition_table(struct kvm_vcpu *vcpu);
|
||||
long kvmhv_copy_tofrom_guest_nested(struct kvm_vcpu *vcpu);
|
||||
void kvmhv_flush_lpid(u64 lpid);
|
||||
void kvmhv_set_ptbl_entry(u64 lpid, u64 dw0, u64 dw1);
|
||||
void kvmhv_release_all_nested(struct kvm *kvm);
|
||||
long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu);
|
||||
@@ -593,13 +594,17 @@ static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
|
||||
|
||||
|
||||
KVMPPC_BOOK3S_VCORE_ACCESSOR(vtb, 64, KVMPPC_GSID_VTB)
|
||||
KVMPPC_BOOK3S_VCORE_ACCESSOR(tb_offset, 64, KVMPPC_GSID_TB_OFFSET)
|
||||
KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(arch_compat, 32, KVMPPC_GSID_LOGICAL_PVR)
|
||||
KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(lpcr, 64, KVMPPC_GSID_LPCR)
|
||||
KVMPPC_BOOK3S_VCORE_ACCESSOR_SET(tb_offset, 64, KVMPPC_GSID_TB_OFFSET)
|
||||
|
||||
static inline u64 kvmppc_get_tb_offset(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return vcpu->arch.vcore->tb_offset;
|
||||
}
|
||||
|
||||
static inline u64 kvmppc_get_dec_expires(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_TB_OFFSET) < 0);
|
||||
WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_DEC_EXPIRY_TB) < 0);
|
||||
return vcpu->arch.dec_expires;
|
||||
}
|
||||
@@ -607,7 +612,6 @@ static inline u64 kvmppc_get_dec_expires(struct kvm_vcpu *vcpu)
|
||||
static inline void kvmppc_set_dec_expires(struct kvm_vcpu *vcpu, u64 val)
|
||||
{
|
||||
vcpu->arch.dec_expires = val;
|
||||
WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_TB_OFFSET) < 0);
|
||||
kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_DEC_EXPIRY_TB);
|
||||
}
|
||||
|
||||
|
||||
@@ -682,6 +682,7 @@ void kvmhv_nestedv2_vcpu_free(struct kvm_vcpu *vcpu, struct kvmhv_nestedv2_io *i
|
||||
int kvmhv_nestedv2_flush_vcpu(struct kvm_vcpu *vcpu, u64 time_limit);
|
||||
int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1);
|
||||
int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu);
|
||||
int kvmhv_nestedv2_set_vpa(struct kvm_vcpu *vcpu, unsigned long vpa);
|
||||
|
||||
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
|
||||
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
#define __ALIGN .align 2
|
||||
#define __ALIGN_STR ".align 2"
|
||||
|
||||
#ifdef CONFIG_PPC64_ELF_ABI_V1
|
||||
#define cond_syscall(x) \
|
||||
asm ("\t.weak " #x "\n\t.set " #x ", sys_ni_syscall\n" \
|
||||
|
||||
@@ -412,5 +412,9 @@ extern void *abatron_pteptrs[2];
|
||||
#include <asm/nohash/mmu.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FA_DUMP) || defined(CONFIG_PRESERVE_FA_DUMP)
|
||||
#define __HAVE_ARCH_RESERVED_KERNEL_PAGES
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_MMU_H_ */
|
||||
|
||||
@@ -42,14 +42,6 @@ u64 memory_hotplug_max(void);
|
||||
#else
|
||||
#define memory_hotplug_max() memblock_end_of_DRAM()
|
||||
#endif /* CONFIG_NUMA */
|
||||
#ifdef CONFIG_FA_DUMP
|
||||
#define __HAVE_ARCH_RESERVED_KERNEL_PAGES
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
extern int create_section_mapping(unsigned long start, unsigned long end,
|
||||
int nid, pgprot_t prot);
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_MMZONE_H_ */
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#ifndef _ASM_POWERPC_PAPR_SYSPARM_H
|
||||
#define _ASM_POWERPC_PAPR_SYSPARM_H
|
||||
|
||||
#include <uapi/asm/papr-sysparm.h>
|
||||
|
||||
typedef struct {
|
||||
const u32 token;
|
||||
u32 token;
|
||||
} papr_sysparm_t;
|
||||
|
||||
#define mk_papr_sysparm(x_) ((papr_sysparm_t){ .token = x_, })
|
||||
@@ -20,11 +22,14 @@ typedef struct {
|
||||
#define PAPR_SYSPARM_TLB_BLOCK_INVALIDATE_ATTRS mk_papr_sysparm(50)
|
||||
#define PAPR_SYSPARM_LPAR_NAME mk_papr_sysparm(55)
|
||||
|
||||
enum {
|
||||
PAPR_SYSPARM_MAX_INPUT = 1024,
|
||||
PAPR_SYSPARM_MAX_OUTPUT = 4000,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct papr_sysparm_buf - RTAS work area layout for system parameter functions.
|
||||
*
|
||||
* This is the memory layout of the buffers passed to/from
|
||||
* ibm,get-system-parameter and ibm,set-system-parameter. It is
|
||||
* distinct from the papr_sysparm_io_block structure that is passed
|
||||
* between user space and the kernel.
|
||||
*/
|
||||
struct papr_sysparm_buf {
|
||||
__be16 len;
|
||||
char val[PAPR_SYSPARM_MAX_OUTPUT];
|
||||
|
||||
@@ -76,6 +76,17 @@ static inline bool is_vcpu_idle(int vcpu)
|
||||
{
|
||||
return lppaca_of(vcpu).idle;
|
||||
}
|
||||
|
||||
static inline bool vcpu_is_dispatched(int vcpu)
|
||||
{
|
||||
/*
|
||||
* This is the yield_count. An "odd" value (low bit on) means that
|
||||
* the processor is yielded (either because of an OS yield or a
|
||||
* hypervisor preempt). An even value implies that the processor is
|
||||
* currently executing.
|
||||
*/
|
||||
return (!(yield_count_of(vcpu) & 1));
|
||||
}
|
||||
#else
|
||||
static inline bool is_shared_processor(void)
|
||||
{
|
||||
@@ -109,6 +120,10 @@ static inline bool is_vcpu_idle(int vcpu)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool vcpu_is_dispatched(int vcpu)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define vcpu_is_preempted vcpu_is_preempted
|
||||
@@ -134,12 +149,12 @@ static inline bool vcpu_is_preempted(int cpu)
|
||||
* If the hypervisor has dispatched the target CPU on a physical
|
||||
* processor, then the target CPU is definitely not preempted.
|
||||
*/
|
||||
if (!(yield_count_of(cpu) & 1))
|
||||
if (vcpu_is_dispatched(cpu))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If the target CPU has yielded to Hypervisor but OS has not
|
||||
* requested idle then the target CPU is definitely preempted.
|
||||
* if the target CPU is not dispatched and the guest OS
|
||||
* has not marked the CPU idle, then it is hypervisor preempted.
|
||||
*/
|
||||
if (!is_vcpu_idle(cpu))
|
||||
return true;
|
||||
@@ -166,7 +181,7 @@ static inline bool vcpu_is_preempted(int cpu)
|
||||
|
||||
/*
|
||||
* The PowerVM hypervisor dispatches VMs on a whole core
|
||||
* basis. So we know that a thread sibling of the local CPU
|
||||
* basis. So we know that a thread sibling of the executing CPU
|
||||
* cannot have been preempted by the hypervisor, even if it
|
||||
* has called H_CONFER, which will set the yield bit.
|
||||
*/
|
||||
@@ -174,15 +189,17 @@ static inline bool vcpu_is_preempted(int cpu)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If any of the threads of the target CPU's core are not
|
||||
* preempted or ceded, then consider target CPU to be
|
||||
* non-preempted.
|
||||
* The specific target CPU was marked by guest OS as idle, but
|
||||
* then also check all other cpus in the core for PowerVM
|
||||
* because it does core scheduling and one of the vcpu
|
||||
* of the core getting preempted by hypervisor implies
|
||||
* other vcpus can also be considered preempted.
|
||||
*/
|
||||
first_cpu = cpu_first_thread_sibling(cpu);
|
||||
for (i = first_cpu; i < first_cpu + threads_per_core; i++) {
|
||||
if (i == cpu)
|
||||
continue;
|
||||
if (!(yield_count_of(i) & 1))
|
||||
if (vcpu_is_dispatched(i))
|
||||
return false;
|
||||
if (!is_vcpu_idle(i))
|
||||
return true;
|
||||
|
||||
@@ -35,6 +35,9 @@ extern void init_pci_config_tokens (void);
|
||||
extern unsigned long get_phb_buid (struct device_node *);
|
||||
extern int rtas_setup_phb(struct pci_controller *phb);
|
||||
|
||||
int rtas_pci_dn_read_config(struct pci_dn *pdn, int where, int size, u32 *val);
|
||||
int rtas_pci_dn_write_config(struct pci_dn *pdn, int where, int size, u32 val);
|
||||
|
||||
#ifdef CONFIG_EEH
|
||||
|
||||
void eeh_addr_cache_insert_dev(struct pci_dev *dev);
|
||||
@@ -44,8 +47,6 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity);
|
||||
int eeh_pci_enable(struct eeh_pe *pe, int function);
|
||||
int eeh_pe_reset_full(struct eeh_pe *pe, bool include_passed);
|
||||
void eeh_save_bars(struct eeh_dev *edev);
|
||||
int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
|
||||
int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
|
||||
void eeh_pe_state_mark(struct eeh_pe *pe, int state);
|
||||
void eeh_pe_mark_isolated(struct eeh_pe *pe);
|
||||
void eeh_pe_state_clear(struct eeh_pe *pe, int state, bool include_passed);
|
||||
|
||||
@@ -514,4 +514,10 @@ u64 ps3_get_spe_id(void *arg);
|
||||
|
||||
void ps3_early_mm_init(void);
|
||||
|
||||
#ifdef CONFIG_PPC_EARLY_DEBUG_PS3GELIC
|
||||
void udbg_shutdown_ps3gelic(void);
|
||||
#else
|
||||
static inline void udbg_shutdown_ps3gelic(void) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1361,6 +1361,7 @@
|
||||
#define PVR_POWER8E 0x004B
|
||||
#define PVR_POWER8NVL 0x004C
|
||||
#define PVR_POWER8 0x004D
|
||||
#define PVR_HX_C2000 0x0066
|
||||
#define PVR_POWER9 0x004E
|
||||
#define PVR_POWER10 0x0080
|
||||
#define PVR_BE 0x0070
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Register definitions specific to the A2 core
|
||||
*
|
||||
* Copyright (C) 2008 Ben. Herrenschmidt (benh@kernel.crashing.org), IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_POWERPC_REG_A2_H__
|
||||
#define __ASM_POWERPC_REG_A2_H__
|
||||
|
||||
#include <asm/asm-const.h>
|
||||
|
||||
#define SPRN_TENSR 0x1b5
|
||||
#define SPRN_TENS 0x1b6 /* Thread ENable Set */
|
||||
#define SPRN_TENC 0x1b7 /* Thread ENable Clear */
|
||||
|
||||
#define SPRN_A2_CCR0 0x3f0 /* Core Configuration Register 0 */
|
||||
#define SPRN_A2_CCR1 0x3f1 /* Core Configuration Register 1 */
|
||||
#define SPRN_A2_CCR2 0x3f2 /* Core Configuration Register 2 */
|
||||
#define SPRN_MMUCR0 0x3fc /* MMU Control Register 0 */
|
||||
#define SPRN_MMUCR1 0x3fd /* MMU Control Register 1 */
|
||||
#define SPRN_MMUCR2 0x3fe /* MMU Control Register 2 */
|
||||
#define SPRN_MMUCR3 0x3ff /* MMU Control Register 3 */
|
||||
|
||||
#define SPRN_IAR 0x372
|
||||
|
||||
#define SPRN_IUCR0 0x3f3
|
||||
#define IUCR0_ICBI_ACK 0x1000
|
||||
|
||||
#define SPRN_XUCR0 0x3f6 /* Execution Unit Config Register 0 */
|
||||
|
||||
#define A2_IERAT_SIZE 16
|
||||
#define A2_DERAT_SIZE 32
|
||||
|
||||
/* A2 MMUCR0 bits */
|
||||
#define MMUCR0_ECL 0x80000000 /* Extended Class for TLB fills */
|
||||
#define MMUCR0_TID_NZ 0x40000000 /* TID is non-zero */
|
||||
#define MMUCR0_TS 0x10000000 /* Translation space for TLB fills */
|
||||
#define MMUCR0_TGS 0x20000000 /* Guest space for TLB fills */
|
||||
#define MMUCR0_TLBSEL 0x0c000000 /* TLB or ERAT target for TLB fills */
|
||||
#define MMUCR0_TLBSEL_U 0x00000000 /* TLBSEL = UTLB */
|
||||
#define MMUCR0_TLBSEL_I 0x08000000 /* TLBSEL = I-ERAT */
|
||||
#define MMUCR0_TLBSEL_D 0x0c000000 /* TLBSEL = D-ERAT */
|
||||
#define MMUCR0_LOCKSRSH 0x02000000 /* Use TLB lock on tlbsx. */
|
||||
#define MMUCR0_TID_MASK 0x000000ff /* TID field */
|
||||
|
||||
/* A2 MMUCR1 bits */
|
||||
#define MMUCR1_IRRE 0x80000000 /* I-ERAT round robin enable */
|
||||
#define MMUCR1_DRRE 0x40000000 /* D-ERAT round robin enable */
|
||||
#define MMUCR1_REE 0x20000000 /* Reference Exception Enable*/
|
||||
#define MMUCR1_CEE 0x10000000 /* Change exception enable */
|
||||
#define MMUCR1_CSINV_ALL 0x00000000 /* Inval ERAT on all CS evts */
|
||||
#define MMUCR1_CSINV_NISYNC 0x04000000 /* Inval ERAT on all ex isync*/
|
||||
#define MMUCR1_CSINV_NEVER 0x0c000000 /* Don't inval ERAT on CS */
|
||||
#define MMUCR1_ICTID 0x00080000 /* IERAT class field as TID */
|
||||
#define MMUCR1_ITTID 0x00040000 /* IERAT thdid field as TID */
|
||||
#define MMUCR1_DCTID 0x00020000 /* DERAT class field as TID */
|
||||
#define MMUCR1_DTTID 0x00010000 /* DERAT thdid field as TID */
|
||||
#define MMUCR1_DCCD 0x00008000 /* DERAT class ignore */
|
||||
#define MMUCR1_TLBWE_BINV 0x00004000 /* back invalidate on tlbwe */
|
||||
|
||||
/* A2 MMUCR2 bits */
|
||||
#define MMUCR2_PSSEL_SHIFT 4
|
||||
|
||||
/* A2 MMUCR3 bits */
|
||||
#define MMUCR3_THID 0x0000000f /* Thread ID */
|
||||
|
||||
/* *** ERAT TLB bits definitions */
|
||||
#define TLB0_EPN_MASK ASM_CONST(0xfffffffffffff000)
|
||||
#define TLB0_CLASS_MASK ASM_CONST(0x0000000000000c00)
|
||||
#define TLB0_CLASS_00 ASM_CONST(0x0000000000000000)
|
||||
#define TLB0_CLASS_01 ASM_CONST(0x0000000000000400)
|
||||
#define TLB0_CLASS_10 ASM_CONST(0x0000000000000800)
|
||||
#define TLB0_CLASS_11 ASM_CONST(0x0000000000000c00)
|
||||
#define TLB0_V ASM_CONST(0x0000000000000200)
|
||||
#define TLB0_X ASM_CONST(0x0000000000000100)
|
||||
#define TLB0_SIZE_MASK ASM_CONST(0x00000000000000f0)
|
||||
#define TLB0_SIZE_4K ASM_CONST(0x0000000000000010)
|
||||
#define TLB0_SIZE_64K ASM_CONST(0x0000000000000030)
|
||||
#define TLB0_SIZE_1M ASM_CONST(0x0000000000000050)
|
||||
#define TLB0_SIZE_16M ASM_CONST(0x0000000000000070)
|
||||
#define TLB0_SIZE_1G ASM_CONST(0x00000000000000a0)
|
||||
#define TLB0_THDID_MASK ASM_CONST(0x000000000000000f)
|
||||
#define TLB0_THDID_0 ASM_CONST(0x0000000000000001)
|
||||
#define TLB0_THDID_1 ASM_CONST(0x0000000000000002)
|
||||
#define TLB0_THDID_2 ASM_CONST(0x0000000000000004)
|
||||
#define TLB0_THDID_3 ASM_CONST(0x0000000000000008)
|
||||
#define TLB0_THDID_ALL ASM_CONST(0x000000000000000f)
|
||||
|
||||
#define TLB1_RESVATTR ASM_CONST(0x00f0000000000000)
|
||||
#define TLB1_U0 ASM_CONST(0x0008000000000000)
|
||||
#define TLB1_U1 ASM_CONST(0x0004000000000000)
|
||||
#define TLB1_U2 ASM_CONST(0x0002000000000000)
|
||||
#define TLB1_U3 ASM_CONST(0x0001000000000000)
|
||||
#define TLB1_R ASM_CONST(0x0000800000000000)
|
||||
#define TLB1_C ASM_CONST(0x0000400000000000)
|
||||
#define TLB1_RPN_MASK ASM_CONST(0x000003fffffff000)
|
||||
#define TLB1_W ASM_CONST(0x0000000000000800)
|
||||
#define TLB1_I ASM_CONST(0x0000000000000400)
|
||||
#define TLB1_M ASM_CONST(0x0000000000000200)
|
||||
#define TLB1_G ASM_CONST(0x0000000000000100)
|
||||
#define TLB1_E ASM_CONST(0x0000000000000080)
|
||||
#define TLB1_VF ASM_CONST(0x0000000000000040)
|
||||
#define TLB1_UX ASM_CONST(0x0000000000000020)
|
||||
#define TLB1_SX ASM_CONST(0x0000000000000010)
|
||||
#define TLB1_UW ASM_CONST(0x0000000000000008)
|
||||
#define TLB1_SW ASM_CONST(0x0000000000000004)
|
||||
#define TLB1_UR ASM_CONST(0x0000000000000002)
|
||||
#define TLB1_SR ASM_CONST(0x0000000000000001)
|
||||
|
||||
/* A2 erativax attributes definitions */
|
||||
#define ERATIVAX_RS_IS_ALL 0x000
|
||||
#define ERATIVAX_RS_IS_TID 0x040
|
||||
#define ERATIVAX_RS_IS_CLASS 0x080
|
||||
#define ERATIVAX_RS_IS_FULLMATCH 0x0c0
|
||||
#define ERATIVAX_CLASS_00 0x000
|
||||
#define ERATIVAX_CLASS_01 0x010
|
||||
#define ERATIVAX_CLASS_10 0x020
|
||||
#define ERATIVAX_CLASS_11 0x030
|
||||
#define ERATIVAX_PSIZE_4K (TLB_PSIZE_4K >> 1)
|
||||
#define ERATIVAX_PSIZE_64K (TLB_PSIZE_64K >> 1)
|
||||
#define ERATIVAX_PSIZE_1M (TLB_PSIZE_1M >> 1)
|
||||
#define ERATIVAX_PSIZE_16M (TLB_PSIZE_16M >> 1)
|
||||
#define ERATIVAX_PSIZE_1G (TLB_PSIZE_1G >> 1)
|
||||
|
||||
/* A2 eratilx attributes definitions */
|
||||
#define ERATILX_T_ALL 0
|
||||
#define ERATILX_T_TID 1
|
||||
#define ERATILX_T_TGS 2
|
||||
#define ERATILX_T_FULLMATCH 3
|
||||
#define ERATILX_T_CLASS0 4
|
||||
#define ERATILX_T_CLASS1 5
|
||||
#define ERATILX_T_CLASS2 6
|
||||
#define ERATILX_T_CLASS3 7
|
||||
|
||||
/* XUCR0 bits */
|
||||
#define XUCR0_TRACE_UM_T0 0x40000000 /* Thread 0 */
|
||||
#define XUCR0_TRACE_UM_T1 0x20000000 /* Thread 1 */
|
||||
#define XUCR0_TRACE_UM_T2 0x10000000 /* Thread 2 */
|
||||
#define XUCR0_TRACE_UM_T3 0x08000000 /* Thread 3 */
|
||||
|
||||
/* A2 CCR0 register */
|
||||
#define A2_CCR0_PME_DISABLED 0x00000000
|
||||
#define A2_CCR0_PME_SLEEP 0x40000000
|
||||
#define A2_CCR0_PME_RVW 0x80000000
|
||||
#define A2_CCR0_PME_DISABLED2 0xc0000000
|
||||
|
||||
/* A2 CCR2 register */
|
||||
#define A2_CCR2_ERAT_ONLY_MODE 0x00000001
|
||||
#define A2_CCR2_ENABLE_ICSWX 0x00000002
|
||||
#define A2_CCR2_ENABLE_PC 0x20000000
|
||||
#define A2_CCR2_ENABLE_TRACE 0x40000000
|
||||
|
||||
#endif /* __ASM_POWERPC_REG_A2_H__ */
|
||||
@@ -3,6 +3,7 @@
|
||||
#define _POWERPC_RTAS_H
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/rtas-types.h>
|
||||
@@ -201,12 +202,25 @@ typedef struct {
|
||||
/* Memory set aside for sys_rtas to use with calls that need a work area. */
|
||||
#define RTAS_USER_REGION_SIZE (64 * 1024)
|
||||
|
||||
/* RTAS return status codes */
|
||||
#define RTAS_HARDWARE_ERROR -1 /* Hardware Error */
|
||||
#define RTAS_BUSY -2 /* RTAS Busy */
|
||||
#define RTAS_INVALID_PARAMETER -3 /* Invalid indicator/domain/sensor etc. */
|
||||
#define RTAS_EXTENDED_DELAY_MIN 9900
|
||||
#define RTAS_EXTENDED_DELAY_MAX 9905
|
||||
/*
|
||||
* Common RTAS function return values, derived from the table "RTAS
|
||||
* Status Word Values" in PAPR+ v2.13 7.2.8: "Return Codes". If a
|
||||
* function can return a value in this table then generally it has the
|
||||
* meaning listed here. More extended commentary in the documentation
|
||||
* for rtas_call().
|
||||
*
|
||||
* RTAS functions may use negative and positive numbers not in this
|
||||
* set for function-specific error and success conditions,
|
||||
* respectively.
|
||||
*/
|
||||
#define RTAS_SUCCESS 0 /* Success. */
|
||||
#define RTAS_HARDWARE_ERROR -1 /* Hardware or other unspecified error. */
|
||||
#define RTAS_BUSY -2 /* Retry immediately. */
|
||||
#define RTAS_INVALID_PARAMETER -3 /* Invalid indicator/domain/sensor etc. */
|
||||
#define RTAS_UNEXPECTED_STATE_CHANGE -7 /* Seems limited to EEH and slot reset. */
|
||||
#define RTAS_EXTENDED_DELAY_MIN 9900 /* Retry after delaying for ~1ms. */
|
||||
#define RTAS_EXTENDED_DELAY_MAX 9905 /* Retry after delaying for ~100s. */
|
||||
#define RTAS_ML_ISOLATION_ERROR -9000 /* Multi-level isolation error. */
|
||||
|
||||
/* statuses specific to ibm,suspend-me */
|
||||
#define RTAS_SUSPEND_ABORTED 9000 /* Suspension aborted */
|
||||
@@ -268,7 +282,7 @@ typedef struct {
|
||||
#define RTAS_TYPE_DEALLOC 0xE3
|
||||
#define RTAS_TYPE_DUMP 0xE4
|
||||
#define RTAS_TYPE_HOTPLUG 0xE5
|
||||
/* I don't add PowerMGM events right now, this is a different topic */
|
||||
/* I don't add PowerMGM events right now, this is a different topic */
|
||||
#define RTAS_TYPE_PMGM_POWER_SW_ON 0x60
|
||||
#define RTAS_TYPE_PMGM_POWER_SW_OFF 0x61
|
||||
#define RTAS_TYPE_PMGM_LID_OPEN 0x62
|
||||
@@ -408,44 +422,41 @@ static inline bool rtas_function_implemented(const rtas_fn_handle_t handle)
|
||||
{
|
||||
return rtas_function_token(handle) != RTAS_UNKNOWN_SERVICE;
|
||||
}
|
||||
extern int rtas_token(const char *service);
|
||||
extern int rtas_service_present(const char *service);
|
||||
extern int rtas_call(int token, int, int, int *, ...);
|
||||
int rtas_token(const char *service);
|
||||
int rtas_call(int token, int nargs, int nret, int *outputs, ...);
|
||||
void rtas_call_unlocked(struct rtas_args *args, int token, int nargs,
|
||||
int nret, ...);
|
||||
extern void __noreturn rtas_restart(char *cmd);
|
||||
extern void rtas_power_off(void);
|
||||
extern void __noreturn rtas_halt(void);
|
||||
extern void rtas_os_term(char *str);
|
||||
void __noreturn rtas_restart(char *cmd);
|
||||
void rtas_power_off(void);
|
||||
void __noreturn rtas_halt(void);
|
||||
void rtas_os_term(char *str);
|
||||
void rtas_activate_firmware(void);
|
||||
extern int rtas_get_sensor(int sensor, int index, int *state);
|
||||
extern int rtas_get_sensor_fast(int sensor, int index, int *state);
|
||||
extern int rtas_get_power_level(int powerdomain, int *level);
|
||||
extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
|
||||
extern bool rtas_indicator_present(int token, int *maxindex);
|
||||
extern int rtas_set_indicator(int indicator, int index, int new_value);
|
||||
extern int rtas_set_indicator_fast(int indicator, int index, int new_value);
|
||||
extern void rtas_progress(char *s, unsigned short hex);
|
||||
int rtas_get_sensor(int sensor, int index, int *state);
|
||||
int rtas_get_sensor_fast(int sensor, int index, int *state);
|
||||
int rtas_get_power_level(int powerdomain, int *level);
|
||||
int rtas_set_power_level(int powerdomain, int level, int *setlevel);
|
||||
bool rtas_indicator_present(int token, int *maxindex);
|
||||
int rtas_set_indicator(int indicator, int index, int new_value);
|
||||
int rtas_set_indicator_fast(int indicator, int index, int new_value);
|
||||
void rtas_progress(char *s, unsigned short hex);
|
||||
int rtas_ibm_suspend_me(int *fw_status);
|
||||
int rtas_error_rc(int rtas_rc);
|
||||
|
||||
struct rtc_time;
|
||||
extern time64_t rtas_get_boot_time(void);
|
||||
extern void rtas_get_rtc_time(struct rtc_time *rtc_time);
|
||||
extern int rtas_set_rtc_time(struct rtc_time *rtc_time);
|
||||
time64_t rtas_get_boot_time(void);
|
||||
void rtas_get_rtc_time(struct rtc_time *rtc_time);
|
||||
int rtas_set_rtc_time(struct rtc_time *rtc_time);
|
||||
|
||||
extern unsigned int rtas_busy_delay_time(int status);
|
||||
unsigned int rtas_busy_delay_time(int status);
|
||||
bool rtas_busy_delay(int status);
|
||||
|
||||
extern int early_init_dt_scan_rtas(unsigned long node,
|
||||
const char *uname, int depth, void *data);
|
||||
int early_init_dt_scan_rtas(unsigned long node, const char *uname, int depth, void *data);
|
||||
|
||||
extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
|
||||
void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
extern time64_t last_rtas_event;
|
||||
extern int clobbering_unread_rtas_event(void);
|
||||
extern void post_mobility_fixup(void);
|
||||
int clobbering_unread_rtas_event(void);
|
||||
int rtas_syscall_dispatch_ibm_suspend_me(u64 handle);
|
||||
#else
|
||||
static inline int clobbering_unread_rtas_event(void) { return 0; }
|
||||
@@ -456,14 +467,14 @@ static inline int rtas_syscall_dispatch_ibm_suspend_me(u64 handle)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_RTAS_DAEMON
|
||||
extern void rtas_cancel_event_scan(void);
|
||||
void rtas_cancel_event_scan(void);
|
||||
#else
|
||||
static inline void rtas_cancel_event_scan(void) { }
|
||||
#endif
|
||||
|
||||
/* Error types logged. */
|
||||
#define ERR_FLAG_ALREADY_LOGGED 0x0
|
||||
#define ERR_FLAG_BOOT 0x1 /* log was pulled from NVRAM on boot */
|
||||
#define ERR_FLAG_BOOT 0x1 /* log was pulled from NVRAM on boot */
|
||||
#define ERR_TYPE_RTAS_LOG 0x2 /* from rtas event-scan */
|
||||
#define ERR_TYPE_KERNEL_PANIC 0x4 /* from die()/panic() */
|
||||
#define ERR_TYPE_KERNEL_PANIC_GZ 0x8 /* ditto, compressed */
|
||||
@@ -473,7 +484,7 @@ static inline void rtas_cancel_event_scan(void) { }
|
||||
(ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC | ERR_TYPE_KERNEL_PANIC_GZ)
|
||||
|
||||
#define RTAS_DEBUG KERN_DEBUG "RTAS: "
|
||||
|
||||
|
||||
#define RTAS_ERROR_LOG_MAX 2048
|
||||
|
||||
/*
|
||||
@@ -481,7 +492,7 @@ static inline void rtas_cancel_event_scan(void) { }
|
||||
* for all rtas calls that require an error buffer argument.
|
||||
* This includes 'check-exception' and 'rtas-last-error'.
|
||||
*/
|
||||
extern int rtas_get_error_log_max(void);
|
||||
int rtas_get_error_log_max(void);
|
||||
|
||||
/* Event Scan Parameters */
|
||||
#define EVENT_SCAN_ALL_EVENTS 0xf0000000
|
||||
@@ -502,6 +513,8 @@ extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
|
||||
/* RMO buffer reserved for user-space RTAS use */
|
||||
extern unsigned long rtas_rmo_buf;
|
||||
|
||||
extern struct mutex rtas_ibm_get_vpd_lock;
|
||||
|
||||
#define GLOBAL_INTERRUPT_QUEUE 9005
|
||||
|
||||
/**
|
||||
@@ -520,8 +533,8 @@ static inline u32 rtas_config_addr(int busno, int devfn, int reg)
|
||||
(devfn << 8) | (reg & 0xff);
|
||||
}
|
||||
|
||||
extern void rtas_give_timebase(void);
|
||||
extern void rtas_take_timebase(void);
|
||||
void rtas_give_timebase(void);
|
||||
void rtas_take_timebase(void);
|
||||
|
||||
#ifdef CONFIG_PPC_RTAS
|
||||
static inline int page_is_rtas_user_buf(unsigned long pfn)
|
||||
@@ -534,7 +547,7 @@ static inline int page_is_rtas_user_buf(unsigned long pfn)
|
||||
|
||||
/* Not the best place to put pSeries_coalesce_init, will be fixed when we
|
||||
* move some of the rtas suspend-me stuff to pseries */
|
||||
extern void pSeries_coalesce_init(void);
|
||||
void pSeries_coalesce_init(void);
|
||||
void rtas_initialize(void);
|
||||
#else
|
||||
static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;}
|
||||
@@ -542,8 +555,6 @@ static inline void pSeries_coalesce_init(void) { }
|
||||
static inline void rtas_initialize(void) { }
|
||||
#endif
|
||||
|
||||
extern int call_rtas(const char *, int, int, unsigned long *, ...);
|
||||
|
||||
#ifdef CONFIG_HV_PERF_CTRS
|
||||
void read_24x7_sys_info(void);
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_PAPR_MISCDEV_H_
|
||||
#define _UAPI_PAPR_MISCDEV_H_
|
||||
|
||||
enum {
|
||||
PAPR_MISCDEV_IOC_ID = 0xb2,
|
||||
};
|
||||
|
||||
#endif /* _UAPI_PAPR_MISCDEV_H_ */
|
||||
@@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_PAPR_SYSPARM_H_
|
||||
#define _UAPI_PAPR_SYSPARM_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/ioctl.h>
|
||||
#include <asm/papr-miscdev.h>
|
||||
|
||||
enum {
|
||||
PAPR_SYSPARM_MAX_INPUT = 1024,
|
||||
PAPR_SYSPARM_MAX_OUTPUT = 4000,
|
||||
};
|
||||
|
||||
struct papr_sysparm_io_block {
|
||||
__u32 parameter;
|
||||
__u16 length;
|
||||
char data[PAPR_SYSPARM_MAX_OUTPUT];
|
||||
};
|
||||
|
||||
/**
|
||||
* PAPR_SYSPARM_IOC_GET - Retrieve the value of a PAPR system parameter.
|
||||
*
|
||||
* Uses _IOWR because of one corner case: Retrieving the value of the
|
||||
* "OS Service Entitlement Status" parameter (60) requires the caller
|
||||
* to supply input data (a date string) in the buffer passed to
|
||||
* firmware. So the @length and @data of the incoming
|
||||
* papr_sysparm_io_block are always used to initialize the work area
|
||||
* supplied to ibm,get-system-parameter. No other parameters are known
|
||||
* to parameterize the result this way, and callers are encouraged
|
||||
* (but not required) to zero-initialize @length and @data in the
|
||||
* common case.
|
||||
*
|
||||
* On error the contents of the ioblock are indeterminate.
|
||||
*
|
||||
* Return:
|
||||
* 0: Success; @length is the length of valid data in @data, not to exceed @PAPR_SYSPARM_MAX_OUTPUT.
|
||||
* -EIO: Platform error. (-1)
|
||||
* -EINVAL: Incorrect data length or format. (-9999)
|
||||
* -EPERM: The calling partition is not allowed to access this parameter. (-9002)
|
||||
* -EOPNOTSUPP: Parameter not supported on this platform (-3)
|
||||
*/
|
||||
#define PAPR_SYSPARM_IOC_GET _IOWR(PAPR_MISCDEV_IOC_ID, 1, struct papr_sysparm_io_block)
|
||||
|
||||
/**
|
||||
* PAPR_SYSPARM_IOC_SET - Update the value of a PAPR system parameter.
|
||||
*
|
||||
* The contents of the ioblock are unchanged regardless of success.
|
||||
*
|
||||
* Return:
|
||||
* 0: Success; the parameter has been updated.
|
||||
* -EIO: Platform error. (-1)
|
||||
* -EINVAL: Incorrect data length or format. (-9999)
|
||||
* -EPERM: The calling partition is not allowed to access this parameter. (-9002)
|
||||
* -EOPNOTSUPP: Parameter not supported on this platform (-3)
|
||||
*/
|
||||
#define PAPR_SYSPARM_IOC_SET _IOW(PAPR_MISCDEV_IOC_ID, 2, struct papr_sysparm_io_block)
|
||||
|
||||
#endif /* _UAPI_PAPR_SYSPARM_H_ */
|
||||
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_PAPR_VPD_H_
|
||||
#define _UAPI_PAPR_VPD_H_
|
||||
|
||||
#include <asm/ioctl.h>
|
||||
#include <asm/papr-miscdev.h>
|
||||
|
||||
struct papr_location_code {
|
||||
/*
|
||||
* PAPR+ v2.13 12.3.2.4 Converged Location Code Rules - Length
|
||||
* Restrictions. 79 characters plus nul.
|
||||
*/
|
||||
char str[80];
|
||||
};
|
||||
|
||||
/*
|
||||
* ioctl for /dev/papr-vpd. Returns a VPD handle fd corresponding to
|
||||
* the location code.
|
||||
*/
|
||||
#define PAPR_VPD_IOC_CREATE_HANDLE _IOW(PAPR_MISCDEV_IOC_ID, 0, struct papr_location_code)
|
||||
|
||||
#endif /* _UAPI_PAPR_VPD_H_ */
|
||||
@@ -238,6 +238,21 @@ static struct cpu_spec cpu_specs[] __initdata = {
|
||||
.machine_check_early = __machine_check_early_realmode_p8,
|
||||
.platform = "power8",
|
||||
},
|
||||
{ /* 2.07-compliant processor, HeXin C2000 processor */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00660000,
|
||||
.cpu_name = "HX-C2000",
|
||||
.cpu_features = CPU_FTRS_POWER8,
|
||||
.cpu_user_features = COMMON_USER_POWER8,
|
||||
.cpu_user_features2 = COMMON_USER2_POWER8,
|
||||
.mmu_features = MMU_FTRS_POWER8,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power8,
|
||||
.cpu_restore = __restore_cpu_power8,
|
||||
.machine_check_early = __machine_check_early_realmode_p8,
|
||||
.platform = "power8",
|
||||
},
|
||||
{ /* 3.00-compliant processor, i.e. Power9 "architected" mode */
|
||||
.pvr_mask = 0xffffffff,
|
||||
.pvr_value = 0x0f000005,
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
#include <asm/setup.h>
|
||||
#include <asm/cpu_setup.h>
|
||||
|
||||
static struct cpu_spec the_cpu_spec __read_mostly;
|
||||
static struct cpu_spec the_cpu_spec __ro_after_init;
|
||||
|
||||
struct cpu_spec* cur_cpu_spec __read_mostly = NULL;
|
||||
struct cpu_spec *cur_cpu_spec __ro_after_init = NULL;
|
||||
EXPORT_SYMBOL(cur_cpu_spec);
|
||||
|
||||
/* The platform string corresponding to the real PVR */
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/reg_a2.h>
|
||||
#include <asm/exception-64e.h>
|
||||
#include <asm/bug.h>
|
||||
#include <asm/irqflags.h>
|
||||
|
||||
+159
-50
@@ -18,6 +18,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/reboot.h>
|
||||
@@ -70,14 +71,33 @@ struct rtas_filter {
|
||||
* ppc64le, and we want to keep it that way. It does
|
||||
* not make sense for this to be set when @filter
|
||||
* is NULL.
|
||||
* @lock: Pointer to an optional dedicated per-function mutex. This
|
||||
* should be set for functions that require multiple calls in
|
||||
* sequence to complete a single operation, and such sequences
|
||||
* will disrupt each other if allowed to interleave. Users of
|
||||
* this function are required to hold the associated lock for
|
||||
* the duration of the call sequence. Add an explanatory
|
||||
* comment to the function table entry if setting this member.
|
||||
*/
|
||||
struct rtas_function {
|
||||
s32 token;
|
||||
const bool banned_for_syscall_on_le:1;
|
||||
const char * const name;
|
||||
const struct rtas_filter *filter;
|
||||
struct mutex *lock;
|
||||
};
|
||||
|
||||
/*
|
||||
* Per-function locks for sequence-based RTAS functions.
|
||||
*/
|
||||
static DEFINE_MUTEX(rtas_ibm_activate_firmware_lock);
|
||||
static DEFINE_MUTEX(rtas_ibm_get_dynamic_sensor_state_lock);
|
||||
static DEFINE_MUTEX(rtas_ibm_get_indices_lock);
|
||||
static DEFINE_MUTEX(rtas_ibm_lpar_perftools_lock);
|
||||
static DEFINE_MUTEX(rtas_ibm_physical_attestation_lock);
|
||||
static DEFINE_MUTEX(rtas_ibm_set_dynamic_indicator_lock);
|
||||
DEFINE_MUTEX(rtas_ibm_get_vpd_lock);
|
||||
|
||||
static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
[RTAS_FNIDX__CHECK_EXCEPTION] = {
|
||||
.name = "check-exception",
|
||||
@@ -125,6 +145,13 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
.buf_idx1 = -1, .size_idx1 = -1,
|
||||
.buf_idx2 = -1, .size_idx2 = -1,
|
||||
},
|
||||
/*
|
||||
* PAPR+ as of v2.13 doesn't explicitly impose any
|
||||
* restriction, but this typically requires multiple
|
||||
* calls before success, and there's no reason to
|
||||
* allow sequences to interleave.
|
||||
*/
|
||||
.lock = &rtas_ibm_activate_firmware_lock,
|
||||
},
|
||||
[RTAS_FNIDX__IBM_CBE_START_PTCAL] = {
|
||||
.name = "ibm,cbe-start-ptcal",
|
||||
@@ -196,6 +223,13 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
.buf_idx1 = 1, .size_idx1 = -1,
|
||||
.buf_idx2 = -1, .size_idx2 = -1,
|
||||
},
|
||||
/*
|
||||
* PAPR+ v2.13 R1–7.3.19–3 is explicit that the OS
|
||||
* must not call ibm,get-dynamic-sensor-state with
|
||||
* different inputs until a non-retry status has been
|
||||
* returned.
|
||||
*/
|
||||
.lock = &rtas_ibm_get_dynamic_sensor_state_lock,
|
||||
},
|
||||
[RTAS_FNIDX__IBM_GET_INDICES] = {
|
||||
.name = "ibm,get-indices",
|
||||
@@ -203,6 +237,12 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
.buf_idx1 = 2, .size_idx1 = 3,
|
||||
.buf_idx2 = -1, .size_idx2 = -1,
|
||||
},
|
||||
/*
|
||||
* PAPR+ v2.13 R1–7.3.17–2 says that the OS must not
|
||||
* interleave ibm,get-indices call sequences with
|
||||
* different inputs.
|
||||
*/
|
||||
.lock = &rtas_ibm_get_indices_lock,
|
||||
},
|
||||
[RTAS_FNIDX__IBM_GET_RIO_TOPOLOGY] = {
|
||||
.name = "ibm,get-rio-topology",
|
||||
@@ -220,6 +260,11 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
.buf_idx1 = 0, .size_idx1 = -1,
|
||||
.buf_idx2 = 1, .size_idx2 = 2,
|
||||
},
|
||||
/*
|
||||
* PAPR+ v2.13 R1–7.3.20–4 indicates that sequences
|
||||
* should not be allowed to interleave.
|
||||
*/
|
||||
.lock = &rtas_ibm_get_vpd_lock,
|
||||
},
|
||||
[RTAS_FNIDX__IBM_GET_XIVE] = {
|
||||
.name = "ibm,get-xive",
|
||||
@@ -239,6 +284,11 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
.buf_idx1 = 2, .size_idx1 = 3,
|
||||
.buf_idx2 = -1, .size_idx2 = -1,
|
||||
},
|
||||
/*
|
||||
* PAPR+ v2.13 R1–7.3.26–6 says the OS should allow
|
||||
* only one call sequence in progress at a time.
|
||||
*/
|
||||
.lock = &rtas_ibm_lpar_perftools_lock,
|
||||
},
|
||||
[RTAS_FNIDX__IBM_MANAGE_FLASH_IMAGE] = {
|
||||
.name = "ibm,manage-flash-image",
|
||||
@@ -277,6 +327,14 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
.buf_idx1 = 0, .size_idx1 = 1,
|
||||
.buf_idx2 = -1, .size_idx2 = -1,
|
||||
},
|
||||
/*
|
||||
* This follows a sequence-based pattern similar to
|
||||
* ibm,get-vpd et al. Since PAPR+ restricts
|
||||
* interleaving call sequences for other functions of
|
||||
* this style, assume the restriction applies here,
|
||||
* even though it's not explicit in the spec.
|
||||
*/
|
||||
.lock = &rtas_ibm_physical_attestation_lock,
|
||||
},
|
||||
[RTAS_FNIDX__IBM_PLATFORM_DUMP] = {
|
||||
.name = "ibm,platform-dump",
|
||||
@@ -284,6 +342,13 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
.buf_idx1 = 4, .size_idx1 = 5,
|
||||
.buf_idx2 = -1, .size_idx2 = -1,
|
||||
},
|
||||
/*
|
||||
* PAPR+ v2.13 7.3.3.4.1 indicates that concurrent
|
||||
* sequences of ibm,platform-dump are allowed if they
|
||||
* are operating on different dump tags. So leave the
|
||||
* lock pointer unset for now. This may need
|
||||
* reconsideration if kernel-internal users appear.
|
||||
*/
|
||||
},
|
||||
[RTAS_FNIDX__IBM_POWER_OFF_UPS] = {
|
||||
.name = "ibm,power-off-ups",
|
||||
@@ -326,6 +391,12 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
.buf_idx1 = 2, .size_idx1 = -1,
|
||||
.buf_idx2 = -1, .size_idx2 = -1,
|
||||
},
|
||||
/*
|
||||
* PAPR+ v2.13 R1–7.3.18–3 says the OS must not call
|
||||
* this function with different inputs until a
|
||||
* non-retry status has been returned.
|
||||
*/
|
||||
.lock = &rtas_ibm_set_dynamic_indicator_lock,
|
||||
},
|
||||
[RTAS_FNIDX__IBM_SET_EEH_OPTION] = {
|
||||
.name = "ibm,set-eeh-option",
|
||||
@@ -454,6 +525,11 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
|
||||
},
|
||||
};
|
||||
|
||||
#define for_each_rtas_function(funcp) \
|
||||
for (funcp = &rtas_function_table[0]; \
|
||||
funcp < &rtas_function_table[ARRAY_SIZE(rtas_function_table)]; \
|
||||
++funcp)
|
||||
|
||||
/*
|
||||
* Nearly all RTAS calls need to be serialized. All uses of the
|
||||
* default rtas_args block must hold rtas_lock.
|
||||
@@ -525,10 +601,10 @@ static DEFINE_XARRAY(rtas_token_to_function_xarray);
|
||||
|
||||
static int __init rtas_token_to_function_xarray_init(void)
|
||||
{
|
||||
const struct rtas_function *func;
|
||||
int err = 0;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(rtas_function_table); ++i) {
|
||||
const struct rtas_function *func = &rtas_function_table[i];
|
||||
for_each_rtas_function(func) {
|
||||
const s32 token = func->token;
|
||||
|
||||
if (token == RTAS_UNKNOWN_SERVICE)
|
||||
@@ -544,6 +620,21 @@ static int __init rtas_token_to_function_xarray_init(void)
|
||||
}
|
||||
arch_initcall(rtas_token_to_function_xarray_init);
|
||||
|
||||
/*
|
||||
* For use by sys_rtas(), where the token value is provided by user
|
||||
* space and we don't want to warn on failed lookups.
|
||||
*/
|
||||
static const struct rtas_function *rtas_token_to_function_untrusted(s32 token)
|
||||
{
|
||||
return xa_load(&rtas_token_to_function_xarray, token);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reverse lookup for deriving the function descriptor from a
|
||||
* known-good token value in contexts where the former is not already
|
||||
* available. @token must be valid, e.g. derived from the result of a
|
||||
* prior lookup against the function table.
|
||||
*/
|
||||
static const struct rtas_function *rtas_token_to_function(s32 token)
|
||||
{
|
||||
const struct rtas_function *func;
|
||||
@@ -551,12 +642,22 @@ static const struct rtas_function *rtas_token_to_function(s32 token)
|
||||
if (WARN_ONCE(token < 0, "invalid token %d", token))
|
||||
return NULL;
|
||||
|
||||
func = xa_load(&rtas_token_to_function_xarray, token);
|
||||
func = rtas_token_to_function_untrusted(token);
|
||||
if (func)
|
||||
return func;
|
||||
/*
|
||||
* Fall back to linear scan in case the reverse mapping hasn't
|
||||
* been initialized yet.
|
||||
*/
|
||||
if (xa_empty(&rtas_token_to_function_xarray)) {
|
||||
for_each_rtas_function(func) {
|
||||
if (func->token == token)
|
||||
return func;
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ONCE(!func, "unexpected failed lookup for token %d", token))
|
||||
return NULL;
|
||||
|
||||
return func;
|
||||
WARN_ONCE(true, "unexpected failed lookup for token %d", token);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This is here deliberately so it's only used in this file */
|
||||
@@ -570,28 +671,25 @@ static void __do_enter_rtas(struct rtas_args *args)
|
||||
|
||||
static void __do_enter_rtas_trace(struct rtas_args *args)
|
||||
{
|
||||
const char *name = NULL;
|
||||
const struct rtas_function *func = rtas_token_to_function(be32_to_cpu(args->token));
|
||||
|
||||
/*
|
||||
* If there is a per-function lock, it must be held by the
|
||||
* caller.
|
||||
*/
|
||||
if (func->lock)
|
||||
lockdep_assert_held(func->lock);
|
||||
|
||||
if (args == &rtas_args)
|
||||
lockdep_assert_held(&rtas_lock);
|
||||
/*
|
||||
* If the tracepoints that consume the function name aren't
|
||||
* active, avoid the lookup.
|
||||
*/
|
||||
if ((trace_rtas_input_enabled() || trace_rtas_output_enabled())) {
|
||||
const s32 token = be32_to_cpu(args->token);
|
||||
const struct rtas_function *func = rtas_token_to_function(token);
|
||||
|
||||
name = func->name;
|
||||
}
|
||||
|
||||
trace_rtas_input(args, name);
|
||||
trace_rtas_input(args, func->name);
|
||||
trace_rtas_ll_entry(args);
|
||||
|
||||
__do_enter_rtas(args);
|
||||
|
||||
trace_rtas_ll_exit(args);
|
||||
trace_rtas_output(args, name);
|
||||
trace_rtas_output(args, func->name);
|
||||
}
|
||||
|
||||
static void do_enter_rtas(struct rtas_args *args)
|
||||
@@ -670,7 +768,7 @@ static void call_rtas_display_status_delay(char c)
|
||||
static int pending_newline = 0; /* did last write end with unprinted newline? */
|
||||
static int width = 16;
|
||||
|
||||
if (c == '\n') {
|
||||
if (c == '\n') {
|
||||
while (width-- > 0)
|
||||
call_rtas_display_status(' ');
|
||||
width = 16;
|
||||
@@ -680,7 +778,7 @@ static void call_rtas_display_status_delay(char c)
|
||||
if (pending_newline) {
|
||||
call_rtas_display_status('\r');
|
||||
call_rtas_display_status('\n');
|
||||
}
|
||||
}
|
||||
pending_newline = 0;
|
||||
if (width--) {
|
||||
call_rtas_display_status(c);
|
||||
@@ -820,7 +918,7 @@ void rtas_progress(char *s, unsigned short hex)
|
||||
else
|
||||
rtas_call(display_character, 1, 1, NULL, '\r');
|
||||
}
|
||||
|
||||
|
||||
if (row_width)
|
||||
width = row_width[current_line];
|
||||
else
|
||||
@@ -840,9 +938,9 @@ void rtas_progress(char *s, unsigned short hex)
|
||||
spin_unlock(&progress_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* RTAS wants CR-LF, not just LF */
|
||||
|
||||
|
||||
if (*os == '\n') {
|
||||
rtas_call(display_character, 1, 1, NULL, '\r');
|
||||
rtas_call(display_character, 1, 1, NULL, '\n');
|
||||
@@ -852,7 +950,7 @@ void rtas_progress(char *s, unsigned short hex)
|
||||
*/
|
||||
rtas_call(display_character, 1, 1, NULL, *os);
|
||||
}
|
||||
|
||||
|
||||
if (row_width)
|
||||
width = row_width[current_line];
|
||||
else
|
||||
@@ -861,15 +959,15 @@ void rtas_progress(char *s, unsigned short hex)
|
||||
width--;
|
||||
rtas_call(display_character, 1, 1, NULL, *os);
|
||||
}
|
||||
|
||||
|
||||
os++;
|
||||
|
||||
|
||||
/* if we overwrite the screen length */
|
||||
if (width <= 0)
|
||||
while ((*os != 0) && (*os != '\n') && (*os != '\r'))
|
||||
os++;
|
||||
}
|
||||
|
||||
|
||||
spin_unlock(&progress_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rtas_progress); /* needed by rtas_flash module */
|
||||
@@ -900,11 +998,6 @@ int rtas_token(const char *service)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rtas_token);
|
||||
|
||||
int rtas_service_present(const char *service)
|
||||
{
|
||||
return rtas_token(service) != RTAS_UNKNOWN_SERVICE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RTAS_ERROR_LOGGING
|
||||
|
||||
static u32 rtas_error_log_max __ro_after_init = RTAS_ERROR_LOG_MAX;
|
||||
@@ -1638,10 +1731,14 @@ void rtas_activate_firmware(void)
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&rtas_ibm_activate_firmware_lock);
|
||||
|
||||
do {
|
||||
fwrc = rtas_call(token, 0, 1, NULL);
|
||||
} while (rtas_busy_delay(fwrc));
|
||||
|
||||
mutex_unlock(&rtas_ibm_activate_firmware_lock);
|
||||
|
||||
if (fwrc)
|
||||
pr_err("ibm,activate-firmware failed (%i)\n", fwrc);
|
||||
}
|
||||
@@ -1713,24 +1810,18 @@ static bool in_rmo_buf(u32 base, u32 end)
|
||||
end < (rtas_rmo_buf + RTAS_USER_REGION_SIZE);
|
||||
}
|
||||
|
||||
static bool block_rtas_call(int token, int nargs,
|
||||
static bool block_rtas_call(const struct rtas_function *func, int nargs,
|
||||
struct rtas_args *args)
|
||||
{
|
||||
const struct rtas_function *func;
|
||||
const struct rtas_filter *f;
|
||||
const bool is_platform_dump = token == rtas_function_token(RTAS_FN_IBM_PLATFORM_DUMP);
|
||||
const bool is_config_conn = token == rtas_function_token(RTAS_FN_IBM_CONFIGURE_CONNECTOR);
|
||||
const bool is_platform_dump =
|
||||
func == &rtas_function_table[RTAS_FNIDX__IBM_PLATFORM_DUMP];
|
||||
const bool is_config_conn =
|
||||
func == &rtas_function_table[RTAS_FNIDX__IBM_CONFIGURE_CONNECTOR];
|
||||
u32 base, size, end;
|
||||
|
||||
/*
|
||||
* If this token doesn't correspond to a function the kernel
|
||||
* understands, you're not allowed to call it.
|
||||
*/
|
||||
func = rtas_token_to_function(token);
|
||||
if (!func)
|
||||
goto err;
|
||||
/*
|
||||
* And only functions with filters attached are allowed.
|
||||
* Only functions with filters attached are allowed.
|
||||
*/
|
||||
f = func->filter;
|
||||
if (!f)
|
||||
@@ -1787,14 +1878,15 @@ static bool block_rtas_call(int token, int nargs,
|
||||
return false;
|
||||
err:
|
||||
pr_err_ratelimited("sys_rtas: RTAS call blocked - exploit attempt?\n");
|
||||
pr_err_ratelimited("sys_rtas: token=0x%x, nargs=%d (called by %s)\n",
|
||||
token, nargs, current->comm);
|
||||
pr_err_ratelimited("sys_rtas: %s nargs=%d (called by %s)\n",
|
||||
func->name, nargs, current->comm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We assume to be passed big endian arguments */
|
||||
SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
|
||||
{
|
||||
const struct rtas_function *func;
|
||||
struct pin_cookie cookie;
|
||||
struct rtas_args args;
|
||||
unsigned long flags;
|
||||
@@ -1824,13 +1916,18 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
|
||||
nargs * sizeof(rtas_arg_t)) != 0)
|
||||
return -EFAULT;
|
||||
|
||||
if (token == RTAS_UNKNOWN_SERVICE)
|
||||
/*
|
||||
* If this token doesn't correspond to a function the kernel
|
||||
* understands, you're not allowed to call it.
|
||||
*/
|
||||
func = rtas_token_to_function_untrusted(token);
|
||||
if (!func)
|
||||
return -EINVAL;
|
||||
|
||||
args.rets = &args.args[nargs];
|
||||
memset(args.rets, 0, nret * sizeof(rtas_arg_t));
|
||||
|
||||
if (block_rtas_call(token, nargs, &args))
|
||||
if (block_rtas_call(func, nargs, &args))
|
||||
return -EINVAL;
|
||||
|
||||
if (token_is_restricted_errinjct(token)) {
|
||||
@@ -1863,6 +1960,15 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
|
||||
|
||||
buff_copy = get_errorlog_buffer();
|
||||
|
||||
/*
|
||||
* If this function has a mutex assigned to it, we must
|
||||
* acquire it to avoid interleaving with any kernel-based uses
|
||||
* of the same function. Kernel-based sequences acquire the
|
||||
* appropriate mutex explicitly.
|
||||
*/
|
||||
if (func->lock)
|
||||
mutex_lock(func->lock);
|
||||
|
||||
raw_spin_lock_irqsave(&rtas_lock, flags);
|
||||
cookie = lockdep_pin_lock(&rtas_lock);
|
||||
|
||||
@@ -1878,6 +1984,9 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
|
||||
lockdep_unpin_lock(&rtas_lock, cookie);
|
||||
raw_spin_unlock_irqrestore(&rtas_lock, flags);
|
||||
|
||||
if (func->lock)
|
||||
mutex_unlock(func->lock);
|
||||
|
||||
if (buff_copy) {
|
||||
if (errbuf)
|
||||
log_error(errbuf, ERR_TYPE_RTAS_LOG, 0);
|
||||
|
||||
@@ -43,7 +43,7 @@ static inline int config_access_valid(struct pci_dn *dn, int where)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
|
||||
int rtas_pci_dn_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
|
||||
{
|
||||
int returnval = -1;
|
||||
unsigned long buid, addr;
|
||||
@@ -87,7 +87,7 @@ static int rtas_pci_read_config(struct pci_bus *bus,
|
||||
pdn = pci_get_pdn_by_devfn(bus, devfn);
|
||||
|
||||
/* Validity of pdn is checked in here */
|
||||
ret = rtas_read_config(pdn, where, size, val);
|
||||
ret = rtas_pci_dn_read_config(pdn, where, size, val);
|
||||
if (*val == EEH_IO_ERROR_VALUE(size) &&
|
||||
eeh_dev_check_failure(pdn_to_eeh_dev(pdn)))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
@@ -95,7 +95,7 @@ static int rtas_pci_read_config(struct pci_bus *bus,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val)
|
||||
int rtas_pci_dn_write_config(struct pci_dn *pdn, int where, int size, u32 val)
|
||||
{
|
||||
unsigned long buid, addr;
|
||||
int ret;
|
||||
@@ -134,7 +134,7 @@ static int rtas_pci_write_config(struct pci_bus *bus,
|
||||
pdn = pci_get_pdn_by_devfn(bus, devfn);
|
||||
|
||||
/* Validity of pdn is checked in here. */
|
||||
return rtas_write_config(pdn, where, size, val);
|
||||
return rtas_pci_dn_write_config(pdn, where, size, val);
|
||||
}
|
||||
|
||||
static struct pci_ops rtas_pci_ops = {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user