mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
Merge branch 'android-4.9' into amlogic-4.9-dev
Signed-off-by: Victor Wan <victor.wan@amlogic.com> Conflicts: arch/arm/configs/bcm2835_defconfig arch/arm/configs/sunxi_defconfig include/linux/cpufreq.h init/main.c
This commit is contained in:
@@ -32,7 +32,7 @@ Description:
|
||||
Description of the physical chip / device for device X.
|
||||
Typically a part number.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/timestamp_clock
|
||||
What: /sys/bus/iio/devices/iio:deviceX/current_timestamp_clock
|
||||
KernelVersion: 4.5
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
|
||||
@@ -350,3 +350,19 @@ Contact: Linux ARM Kernel Mailing list <linux-arm-kernel@lists.infradead.org>
|
||||
Description: AArch64 CPU registers
|
||||
'identification' directory exposes the CPU ID registers for
|
||||
identifying model and revision of the CPU.
|
||||
|
||||
What: /sys/devices/system/cpu/vulnerabilities
|
||||
/sys/devices/system/cpu/vulnerabilities/meltdown
|
||||
/sys/devices/system/cpu/vulnerabilities/spectre_v1
|
||||
/sys/devices/system/cpu/vulnerabilities/spectre_v2
|
||||
Date: January 2018
|
||||
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
Description: Information about CPU vulnerabilities
|
||||
|
||||
The files are named after the code names of CPU
|
||||
vulnerabilities. The output of those files reflects the
|
||||
state of the CPUs in the system. Possible output values:
|
||||
|
||||
"Not affected" CPU is not affected by the vulnerability
|
||||
"Vulnerable" CPU is affected and no mitigation in effect
|
||||
"Mitigation: $M" CPU is affected and mitigation $M is in effect
|
||||
|
||||
@@ -186,3 +186,9 @@ Date: August 2017
|
||||
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
|
||||
Description:
|
||||
Controls sleep time of GC urgent mode
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/readdir_ra
|
||||
Date: November 2017
|
||||
Contact: "Sheng Yong" <shengyong1@huawei.com>
|
||||
Description:
|
||||
Controls readahead inode block in readdir.
|
||||
|
||||
@@ -2,7 +2,7 @@ Toppoly TD028TTEC1 Panel
|
||||
========================
|
||||
|
||||
Required properties:
|
||||
- compatible: "toppoly,td028ttec1"
|
||||
- compatible: "tpo,td028ttec1"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the panel
|
||||
@@ -14,7 +14,7 @@ Example
|
||||
-------
|
||||
|
||||
lcd-panel: td028ttec1@0 {
|
||||
compatible = "toppoly,td028ttec1";
|
||||
compatible = "tpo,td028ttec1";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <100000>;
|
||||
spi-cpol;
|
||||
@@ -63,6 +63,6 @@ Example:
|
||||
interrupts = <0 35 0x4>;
|
||||
status = "disabled";
|
||||
dmas = <&dmahost 12 0 1>,
|
||||
<&dmahost 13 0 1 0>;
|
||||
<&dmahost 13 1 0>;
|
||||
dma-names = "rx", "rx";
|
||||
};
|
||||
|
||||
@@ -28,6 +28,9 @@ Optional properties:
|
||||
regulator to drive the OTG VBus, rather then as an input pin
|
||||
which signals whether the board is driving OTG VBus or not.
|
||||
|
||||
- x-powers,master-mode: Boolean (axp806 only). Set this when the PMIC is
|
||||
wired for master mode. The default is slave mode.
|
||||
|
||||
- <input>-supply: a phandle to the regulator supply node. May be omitted if
|
||||
inputs are unregulated, such as using the IPSOUT output
|
||||
from the PMIC.
|
||||
|
||||
@@ -35,6 +35,15 @@ Optional properties:
|
||||
- ti,palmas-enable-dvfs2: Enable DVFS2. Configure pins for DVFS2 mode.
|
||||
Selection primary or secondary function associated to GPADC_START
|
||||
and SYSEN2 pin/pad for DVFS2 interface
|
||||
- ti,palmas-override-powerhold: This is applicable for PMICs for which
|
||||
GPIO7 is configured in POWERHOLD mode which has higher priority
|
||||
over DEV_ON bit and keeps the PMIC supplies on even after the DEV_ON
|
||||
bit is turned off. This property enables driver to over ride the
|
||||
POWERHOLD value to GPIO7 so as to turn off the PMIC in power off
|
||||
scenarios. So for GPIO7 if ti,palmas-override-powerhold is set
|
||||
then the GPIO_7 field should never be muxed to anything else.
|
||||
It should be set to POWERHOLD by default and only in case of
|
||||
power off scenarios the driver will over ride the mux value.
|
||||
|
||||
This binding uses the following generic properties as defined in
|
||||
pinctrl-bindings.txt:
|
||||
|
||||
@@ -233,7 +233,7 @@ data_err=ignore(*) Just print an error message if an error occurs
|
||||
data_err=abort Abort the journal if an error occurs in a file
|
||||
data buffer in ordered mode.
|
||||
|
||||
grpid Give objects the same group ID as their creator.
|
||||
grpid New objects have the group ID of their parent.
|
||||
bsdgroups
|
||||
|
||||
nogrpid (*) New objects have the group ID of their creator.
|
||||
|
||||
@@ -2703,6 +2703,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
nosmt [KNL,S390] Disable symmetric multithreading (SMT).
|
||||
Equivalent to smt=1.
|
||||
|
||||
nospectre_v2 [X86] Disable all mitigations for the Spectre variant 2
|
||||
(indirect branch prediction) vulnerability. System may
|
||||
allow data leaks with this option, which is equivalent
|
||||
to spectre_v2=off.
|
||||
|
||||
noxsave [BUGS=X86] Disables x86 extended register state save
|
||||
and restore using xsave. The kernel will fallback to
|
||||
enabling legacy floating-point and sse state.
|
||||
@@ -2775,8 +2780,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
|
||||
nojitter [IA-64] Disables jitter checking for ITC timers.
|
||||
|
||||
nopti [X86-64] Disable KAISER isolation of kernel from user.
|
||||
|
||||
no-kvmclock [X86,KVM] Disable paravirtualized KVM clock driver
|
||||
|
||||
no-kvmapf [X86,KVM] Disable paravirtualized asynchronous page
|
||||
@@ -2814,8 +2817,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
norandmaps Don't use address space randomization. Equivalent to
|
||||
echo 0 > /proc/sys/kernel/randomize_va_space
|
||||
|
||||
noreplace-paravirt [X86,IA-64,PV_OPS] Don't patch paravirt_ops
|
||||
|
||||
noreplace-smp [X86-32,SMP] Don't replace SMP instructions
|
||||
with UP alternatives
|
||||
|
||||
@@ -3339,11 +3340,20 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
pt. [PARIDE]
|
||||
See Documentation/blockdev/paride.txt.
|
||||
|
||||
pti= [X86_64]
|
||||
Control KAISER user/kernel address space isolation:
|
||||
on - enable
|
||||
off - disable
|
||||
auto - default setting
|
||||
pti= [X86_64] Control Page Table Isolation of user and
|
||||
kernel address spaces. Disabling this feature
|
||||
removes hardening, but improves performance of
|
||||
system calls and interrupts.
|
||||
|
||||
on - unconditionally enable
|
||||
off - unconditionally disable
|
||||
auto - kernel detects whether your CPU model is
|
||||
vulnerable to issues that PTI mitigates
|
||||
|
||||
Not specifying this option is equivalent to pti=auto.
|
||||
|
||||
nopti [X86_64]
|
||||
Equivalent to pti=off
|
||||
|
||||
pty.legacy_count=
|
||||
[KNL] Number of legacy pty's. Overwrites compiled-in
|
||||
@@ -3949,6 +3959,29 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
sonypi.*= [HW] Sony Programmable I/O Control Device driver
|
||||
See Documentation/laptops/sonypi.txt
|
||||
|
||||
spectre_v2= [X86] Control mitigation of Spectre variant 2
|
||||
(indirect branch speculation) vulnerability.
|
||||
|
||||
on - unconditionally enable
|
||||
off - unconditionally disable
|
||||
auto - kernel detects whether your CPU model is
|
||||
vulnerable
|
||||
|
||||
Selecting 'on' will, and 'auto' may, choose a
|
||||
mitigation method at run time according to the
|
||||
CPU, the available microcode, the setting of the
|
||||
CONFIG_RETPOLINE configuration option, and the
|
||||
compiler with which the kernel was built.
|
||||
|
||||
Specific mitigations can also be selected manually:
|
||||
|
||||
retpoline - replace indirect branches
|
||||
retpoline,generic - google's original retpoline
|
||||
retpoline,amd - AMD-specific minimal thunk
|
||||
|
||||
Not specifying this option is equivalent to
|
||||
spectre_v2=auto.
|
||||
|
||||
spia_io_base= [HW,MTD]
|
||||
spia_fio_base=
|
||||
spia_pedr=
|
||||
|
||||
90
Documentation/speculation.txt
Normal file
90
Documentation/speculation.txt
Normal file
@@ -0,0 +1,90 @@
|
||||
This document explains potential effects of speculation, and how undesirable
|
||||
effects can be mitigated portably using common APIs.
|
||||
|
||||
===========
|
||||
Speculation
|
||||
===========
|
||||
|
||||
To improve performance and minimize average latencies, many contemporary CPUs
|
||||
employ speculative execution techniques such as branch prediction, performing
|
||||
work which may be discarded at a later stage.
|
||||
|
||||
Typically speculative execution cannot be observed from architectural state,
|
||||
such as the contents of registers. However, in some cases it is possible to
|
||||
observe its impact on microarchitectural state, such as the presence or
|
||||
absence of data in caches. Such state may form side-channels which can be
|
||||
observed to extract secret information.
|
||||
|
||||
For example, in the presence of branch prediction, it is possible for bounds
|
||||
checks to be ignored by code which is speculatively executed. Consider the
|
||||
following code:
|
||||
|
||||
int load_array(int *array, unsigned int index)
|
||||
{
|
||||
if (index >= MAX_ARRAY_ELEMS)
|
||||
return 0;
|
||||
else
|
||||
return array[index];
|
||||
}
|
||||
|
||||
Which, on arm64, may be compiled to an assembly sequence such as:
|
||||
|
||||
CMP <index>, #MAX_ARRAY_ELEMS
|
||||
B.LT less
|
||||
MOV <returnval>, #0
|
||||
RET
|
||||
less:
|
||||
LDR <returnval>, [<array>, <index>]
|
||||
RET
|
||||
|
||||
It is possible that a CPU mis-predicts the conditional branch, and
|
||||
speculatively loads array[index], even if index >= MAX_ARRAY_ELEMS. This
|
||||
value will subsequently be discarded, but the speculated load may affect
|
||||
microarchitectural state which can be subsequently measured.
|
||||
|
||||
More complex sequences involving multiple dependent memory accesses may
|
||||
result in sensitive information being leaked. Consider the following
|
||||
code, building on the prior example:
|
||||
|
||||
int load_dependent_arrays(int *arr1, int *arr2, int index)
|
||||
{
|
||||
int val1, val2,
|
||||
|
||||
val1 = load_array(arr1, index);
|
||||
val2 = load_array(arr2, val1);
|
||||
|
||||
return val2;
|
||||
}
|
||||
|
||||
Under speculation, the first call to load_array() may return the value
|
||||
of an out-of-bounds address, while the second call will influence
|
||||
microarchitectural state dependent on this value. This may provide an
|
||||
arbitrary read primitive.
|
||||
|
||||
====================================
|
||||
Mitigating speculation side-channels
|
||||
====================================
|
||||
|
||||
The kernel provides a generic API to ensure that bounds checks are
|
||||
respected even under speculation. Architectures which are affected by
|
||||
speculation-based side-channels are expected to implement these
|
||||
primitives.
|
||||
|
||||
The array_index_nospec() helper in <linux/nospec.h> can be used to
|
||||
prevent information from being leaked via side-channels.
|
||||
|
||||
A call to array_index_nospec(index, size) returns a sanitized index
|
||||
value that is bounded to [0, size) even under cpu speculation
|
||||
conditions.
|
||||
|
||||
This can be used to protect the earlier load_array() example:
|
||||
|
||||
int load_array(int *array, unsigned int index)
|
||||
{
|
||||
if (index >= MAX_ARRAY_ELEMS)
|
||||
return 0;
|
||||
else {
|
||||
index = array_index_nospec(index, MAX_ARRAY_ELEMS);
|
||||
return array[index];
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
=============
|
||||
TEE subsystem
|
||||
=============
|
||||
|
||||
This document describes the TEE subsystem in Linux.
|
||||
|
||||
A TEE (Trusted Execution Environment) is a trusted OS running in some
|
||||
@@ -80,27 +83,27 @@ The GlobalPlatform TEE Client API [5] is implemented on top of the generic
|
||||
TEE API.
|
||||
|
||||
Picture of the relationship between the different components in the
|
||||
OP-TEE architecture.
|
||||
OP-TEE architecture::
|
||||
|
||||
User space Kernel Secure world
|
||||
~~~~~~~~~~ ~~~~~~ ~~~~~~~~~~~~
|
||||
+--------+ +-------------+
|
||||
| Client | | Trusted |
|
||||
+--------+ | Application |
|
||||
/\ +-------------+
|
||||
|| +----------+ /\
|
||||
|| |tee- | ||
|
||||
|| |supplicant| \/
|
||||
|| +----------+ +-------------+
|
||||
\/ /\ | TEE Internal|
|
||||
+-------+ || | API |
|
||||
+ TEE | || +--------+--------+ +-------------+
|
||||
| Client| || | TEE | OP-TEE | | OP-TEE |
|
||||
| API | \/ | subsys | driver | | Trusted OS |
|
||||
+-------+----------------+----+-------+----+-----------+-------------+
|
||||
| Generic TEE API | | OP-TEE MSG |
|
||||
| IOCTL (TEE_IOC_*) | | SMCCC (OPTEE_SMC_CALL_*) |
|
||||
+-----------------------------+ +------------------------------+
|
||||
User space Kernel Secure world
|
||||
~~~~~~~~~~ ~~~~~~ ~~~~~~~~~~~~
|
||||
+--------+ +-------------+
|
||||
| Client | | Trusted |
|
||||
+--------+ | Application |
|
||||
/\ +-------------+
|
||||
|| +----------+ /\
|
||||
|| |tee- | ||
|
||||
|| |supplicant| \/
|
||||
|| +----------+ +-------------+
|
||||
\/ /\ | TEE Internal|
|
||||
+-------+ || | API |
|
||||
+ TEE | || +--------+--------+ +-------------+
|
||||
| Client| || | TEE | OP-TEE | | OP-TEE |
|
||||
| API | \/ | subsys | driver | | Trusted OS |
|
||||
+-------+----------------+----+-------+----+-----------+-------------+
|
||||
| Generic TEE API | | OP-TEE MSG |
|
||||
| IOCTL (TEE_IOC_*) | | SMCCC (OPTEE_SMC_CALL_*) |
|
||||
+-----------------------------+ +------------------------------+
|
||||
|
||||
RPC (Remote Procedure Call) are requests from secure world to kernel driver
|
||||
or tee-supplicant. An RPC is identified by a special range of SMCCC return
|
||||
@@ -109,10 +112,16 @@ kernel are handled by the kernel driver. Other RPC messages will be forwarded to
|
||||
tee-supplicant without further involvement of the driver, except switching
|
||||
shared memory buffer representation.
|
||||
|
||||
References:
|
||||
References
|
||||
==========
|
||||
|
||||
[1] https://github.com/OP-TEE/optee_os
|
||||
|
||||
[2] http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
|
||||
|
||||
[3] drivers/tee/optee/optee_smc.h
|
||||
|
||||
[4] drivers/tee/optee/optee_msg.h
|
||||
|
||||
[5] http://www.globalplatform.org/specificationsdevice.asp look for
|
||||
"TEE Client API Specification v1.0" and click download.
|
||||
|
||||
186
Documentation/x86/pti.txt
Normal file
186
Documentation/x86/pti.txt
Normal file
@@ -0,0 +1,186 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
Page Table Isolation (pti, previously known as KAISER[1]) is a
|
||||
countermeasure against attacks on the shared user/kernel address
|
||||
space such as the "Meltdown" approach[2].
|
||||
|
||||
To mitigate this class of attacks, we create an independent set of
|
||||
page tables for use only when running userspace applications. When
|
||||
the kernel is entered via syscalls, interrupts or exceptions, the
|
||||
page tables are switched to the full "kernel" copy. When the system
|
||||
switches back to user mode, the user copy is used again.
|
||||
|
||||
The userspace page tables contain only a minimal amount of kernel
|
||||
data: only what is needed to enter/exit the kernel such as the
|
||||
entry/exit functions themselves and the interrupt descriptor table
|
||||
(IDT). There are a few strictly unnecessary things that get mapped
|
||||
such as the first C function when entering an interrupt (see
|
||||
comments in pti.c).
|
||||
|
||||
This approach helps to ensure that side-channel attacks leveraging
|
||||
the paging structures do not function when PTI is enabled. It can be
|
||||
enabled by setting CONFIG_PAGE_TABLE_ISOLATION=y at compile time.
|
||||
Once enabled at compile-time, it can be disabled at boot with the
|
||||
'nopti' or 'pti=' kernel parameters (see kernel-parameters.txt).
|
||||
|
||||
Page Table Management
|
||||
=====================
|
||||
|
||||
When PTI is enabled, the kernel manages two sets of page tables.
|
||||
The first set is very similar to the single set which is present in
|
||||
kernels without PTI. This includes a complete mapping of userspace
|
||||
that the kernel can use for things like copy_to_user().
|
||||
|
||||
Although _complete_, the user portion of the kernel page tables is
|
||||
crippled by setting the NX bit in the top level. This ensures
|
||||
that any missed kernel->user CR3 switch will immediately crash
|
||||
userspace upon executing its first instruction.
|
||||
|
||||
The userspace page tables map only the kernel data needed to enter
|
||||
and exit the kernel. This data is entirely contained in the 'struct
|
||||
cpu_entry_area' structure which is placed in the fixmap which gives
|
||||
each CPU's copy of the area a compile-time-fixed virtual address.
|
||||
|
||||
For new userspace mappings, the kernel makes the entries in its
|
||||
page tables like normal. The only difference is when the kernel
|
||||
makes entries in the top (PGD) level. In addition to setting the
|
||||
entry in the main kernel PGD, a copy of the entry is made in the
|
||||
userspace page tables' PGD.
|
||||
|
||||
This sharing at the PGD level also inherently shares all the lower
|
||||
layers of the page tables. This leaves a single, shared set of
|
||||
userspace page tables to manage. One PTE to lock, one set of
|
||||
accessed bits, dirty bits, etc...
|
||||
|
||||
Overhead
|
||||
========
|
||||
|
||||
Protection against side-channel attacks is important. But,
|
||||
this protection comes at a cost:
|
||||
|
||||
1. Increased Memory Use
|
||||
a. Each process now needs an order-1 PGD instead of order-0.
|
||||
(Consumes an additional 4k per process).
|
||||
b. The 'cpu_entry_area' structure must be 2MB in size and 2MB
|
||||
aligned so that it can be mapped by setting a single PMD
|
||||
entry. This consumes nearly 2MB of RAM once the kernel
|
||||
is decompressed, but no space in the kernel image itself.
|
||||
|
||||
2. Runtime Cost
|
||||
a. CR3 manipulation to switch between the page table copies
|
||||
must be done at interrupt, syscall, and exception entry
|
||||
and exit (it can be skipped when the kernel is interrupted,
|
||||
though.) Moves to CR3 are on the order of a hundred
|
||||
cycles, and are required at every entry and exit.
|
||||
b. A "trampoline" must be used for SYSCALL entry. This
|
||||
trampoline depends on a smaller set of resources than the
|
||||
non-PTI SYSCALL entry code, so requires mapping fewer
|
||||
things into the userspace page tables. The downside is
|
||||
that stacks must be switched at entry time.
|
||||
c. Global pages are disabled for all kernel structures not
|
||||
mapped into both kernel and userspace page tables. This
|
||||
feature of the MMU allows different processes to share TLB
|
||||
entries mapping the kernel. Losing the feature means more
|
||||
TLB misses after a context switch. The actual loss of
|
||||
performance is very small, however, never exceeding 1%.
|
||||
d. Process Context IDentifiers (PCID) is a CPU feature that
|
||||
allows us to skip flushing the entire TLB when switching page
|
||||
tables by setting a special bit in CR3 when the page tables
|
||||
are changed. This makes switching the page tables (at context
|
||||
switch, or kernel entry/exit) cheaper. But, on systems with
|
||||
PCID support, the context switch code must flush both the user
|
||||
and kernel entries out of the TLB. The user PCID TLB flush is
|
||||
deferred until the exit to userspace, minimizing the cost.
|
||||
See intel.com/sdm for the gory PCID/INVPCID details.
|
||||
e. The userspace page tables must be populated for each new
|
||||
process. Even without PTI, the shared kernel mappings
|
||||
are created by copying top-level (PGD) entries into each
|
||||
new process. But, with PTI, there are now *two* kernel
|
||||
mappings: one in the kernel page tables that maps everything
|
||||
and one for the entry/exit structures. At fork(), we need to
|
||||
copy both.
|
||||
f. In addition to the fork()-time copying, there must also
|
||||
be an update to the userspace PGD any time a set_pgd() is done
|
||||
on a PGD used to map userspace. This ensures that the kernel
|
||||
and userspace copies always map the same userspace
|
||||
memory.
|
||||
g. On systems without PCID support, each CR3 write flushes
|
||||
the entire TLB. That means that each syscall, interrupt
|
||||
or exception flushes the TLB.
|
||||
h. INVPCID is a TLB-flushing instruction which allows flushing
|
||||
of TLB entries for non-current PCIDs. Some systems support
|
||||
PCIDs, but do not support INVPCID. On these systems, addresses
|
||||
can only be flushed from the TLB for the current PCID. When
|
||||
flushing a kernel address, we need to flush all PCIDs, so a
|
||||
single kernel address flush will require a TLB-flushing CR3
|
||||
write upon the next use of every PCID.
|
||||
|
||||
Possible Future Work
|
||||
====================
|
||||
1. We can be more careful about not actually writing to CR3
|
||||
unless its value is actually changed.
|
||||
2. Allow PTI to be enabled/disabled at runtime in addition to the
|
||||
boot-time switching.
|
||||
|
||||
Testing
|
||||
========
|
||||
|
||||
To test stability of PTI, the following test procedure is recommended,
|
||||
ideally doing all of these in parallel:
|
||||
|
||||
1. Set CONFIG_DEBUG_ENTRY=y
|
||||
2. Run several copies of all of the tools/testing/selftests/x86/ tests
|
||||
(excluding MPX and protection_keys) in a loop on multiple CPUs for
|
||||
several minutes. These tests frequently uncover corner cases in the
|
||||
kernel entry code. In general, old kernels might cause these tests
|
||||
themselves to crash, but they should never crash the kernel.
|
||||
3. Run the 'perf' tool in a mode (top or record) that generates many
|
||||
frequent performance monitoring non-maskable interrupts (see "NMI"
|
||||
in /proc/interrupts). This exercises the NMI entry/exit code which
|
||||
is known to trigger bugs in code paths that did not expect to be
|
||||
interrupted, including nested NMIs. Using "-c" boosts the rate of
|
||||
NMIs, and using two -c with separate counters encourages nested NMIs
|
||||
and less deterministic behavior.
|
||||
|
||||
while true; do perf record -c 10000 -e instructions,cycles -a sleep 10; done
|
||||
|
||||
4. Launch a KVM virtual machine.
|
||||
5. Run 32-bit binaries on systems supporting the SYSCALL instruction.
|
||||
This has been a lightly-tested code path and needs extra scrutiny.
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
Bugs in PTI cause a few different signatures of crashes
|
||||
that are worth noting here.
|
||||
|
||||
* Failures of the selftests/x86 code. Usually a bug in one of the
|
||||
more obscure corners of entry_64.S
|
||||
* Crashes in early boot, especially around CPU bringup. Bugs
|
||||
in the trampoline code or mappings cause these.
|
||||
* Crashes at the first interrupt. Caused by bugs in entry_64.S,
|
||||
like screwing up a page table switch. Also caused by
|
||||
incorrectly mapping the IRQ handler entry code.
|
||||
* Crashes at the first NMI. The NMI code is separate from main
|
||||
interrupt handlers and can have bugs that do not affect
|
||||
normal interrupts. Also caused by incorrectly mapping NMI
|
||||
code. NMIs that interrupt the entry code must be very
|
||||
careful and can be the cause of crashes that show up when
|
||||
running perf.
|
||||
* Kernel crashes at the first exit to userspace. entry_64.S
|
||||
bugs, or failing to map some of the exit code.
|
||||
* Crashes at first interrupt that interrupts userspace. The paths
|
||||
in entry_64.S that return to userspace are sometimes separate
|
||||
from the ones that return to the kernel.
|
||||
* Double faults: overflowing the kernel stack because of page
|
||||
faults upon page faults. Caused by touching non-pti-mapped
|
||||
data in the entry code, or forgetting to switch to kernel
|
||||
CR3 before calling into C functions which are not pti-mapped.
|
||||
* Userspace segfaults early in boot, sometimes manifesting
|
||||
as mount(8) failing to mount the rootfs. These have
|
||||
tended to be TLB invalidation issues. Usually invalidating
|
||||
the wrong PCID, or otherwise missing an invalidation.
|
||||
|
||||
1. https://gruss.cc/files/kaiser.pdf
|
||||
2. https://meltdownattack.com/meltdown.pdf
|
||||
103
Makefile
103
Makefile
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 76
|
||||
SUBLEVEL = 93
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
@@ -87,10 +87,12 @@ endif
|
||||
ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
|
||||
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
|
||||
quiet=silent_
|
||||
tools_silent=s
|
||||
endif
|
||||
else # make-3.8x
|
||||
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
|
||||
quiet=silent_
|
||||
tools_silent=-s
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -346,6 +348,7 @@ include scripts/Kbuild.include
|
||||
# Make variables (CC, etc...)
|
||||
AS = $(CROSS_COMPILE)as
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
LDGOLD = $(CROSS_COMPILE)ld.gold
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
CPP = $(CC) -E
|
||||
AR = $(CROSS_COMPILE)ar
|
||||
@@ -628,6 +631,20 @@ CFLAGS_GCOV := -fprofile-arcs -ftest-coverage -fno-tree-loop-im $(call cc-disabl
|
||||
CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
|
||||
export CFLAGS_GCOV CFLAGS_KCOV
|
||||
|
||||
# Make toolchain changes before including arch/$(SRCARCH)/Makefile to ensure
|
||||
# ar/cc/ld-* macros return correct values.
|
||||
ifdef CONFIG_LTO_CLANG
|
||||
# use GNU gold with LLVMgold for LTO linking, and LD for vmlinux_link
|
||||
LDFINAL_vmlinux := $(LD)
|
||||
LD := $(LDGOLD)
|
||||
LDFLAGS += -plugin LLVMgold.so
|
||||
# use llvm-ar for building symbol tables from IR files, and llvm-dis instead
|
||||
# of objdump for processing symbol versions and exports
|
||||
LLVM_AR := llvm-ar
|
||||
LLVM_DIS := llvm-dis
|
||||
export LLVM_AR LLVM_DIS
|
||||
endif
|
||||
|
||||
# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
|
||||
# values of the respective KBUILD_* variables
|
||||
ARCH_CPPFLAGS :=
|
||||
@@ -646,6 +663,53 @@ KBUILD_CFLAGS += $(call cc-option,-ffunction-sections,)
|
||||
KBUILD_CFLAGS += $(call cc-option,-fdata-sections,)
|
||||
endif
|
||||
|
||||
ifdef CONFIG_LTO_CLANG
|
||||
lto-clang-flags := -flto -fvisibility=hidden
|
||||
|
||||
# allow disabling only clang LTO where needed
|
||||
DISABLE_LTO_CLANG := -fno-lto -fvisibility=default
|
||||
export DISABLE_LTO_CLANG
|
||||
endif
|
||||
|
||||
ifdef CONFIG_LTO
|
||||
lto-flags := $(lto-clang-flags)
|
||||
KBUILD_CFLAGS += $(lto-flags)
|
||||
|
||||
DISABLE_LTO := $(DISABLE_LTO_CLANG)
|
||||
export DISABLE_LTO
|
||||
|
||||
# LDFINAL_vmlinux and LDFLAGS_FINAL_vmlinux can be set to override
|
||||
# the linker and flags for vmlinux_link.
|
||||
export LDFINAL_vmlinux LDFLAGS_FINAL_vmlinux
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CFI_CLANG
|
||||
cfi-clang-flags += -fsanitize=cfi
|
||||
DISABLE_CFI_CLANG := -fno-sanitize=cfi
|
||||
ifdef CONFIG_MODULES
|
||||
cfi-clang-flags += -fsanitize-cfi-cross-dso
|
||||
DISABLE_CFI_CLANG += -fno-sanitize-cfi-cross-dso
|
||||
endif
|
||||
ifdef CONFIG_CFI_PERMISSIVE
|
||||
cfi-clang-flags += -fsanitize-recover=cfi -fno-sanitize-trap=cfi
|
||||
endif
|
||||
|
||||
# also disable CFI when LTO is disabled
|
||||
DISABLE_LTO_CLANG += $(DISABLE_CFI_CLANG)
|
||||
# allow disabling only clang CFI where needed
|
||||
export DISABLE_CFI_CLANG
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CFI
|
||||
# cfi-flags are re-tested in prepare-compiler-check
|
||||
cfi-flags := $(cfi-clang-flags)
|
||||
KBUILD_CFLAGS += $(cfi-flags)
|
||||
|
||||
DISABLE_CFI := $(DISABLE_CFI_CLANG)
|
||||
DISABLE_LTO += $(DISABLE_CFI)
|
||||
export DISABLE_CFI
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||
KBUILD_CFLAGS += $(call cc-option,-Oz,-Os)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning,maybe-uninitialized,)
|
||||
@@ -809,6 +873,15 @@ KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign)
|
||||
# disable invalid "can't wrap" optimizations for signed / pointers
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
|
||||
|
||||
# clang sets -fmerge-all-constants by default as optimization, but this
|
||||
# is non-conforming behavior for C and in fact breaks the kernel, so we
|
||||
# need to disable it here generally.
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-merge-all-constants)
|
||||
|
||||
# for gcc -fno-merge-all-constants disables everything, but it is fine
|
||||
# to have actual conforming behavior enabled.
|
||||
KBUILD_CFLAGS += $(call cc-option,-fmerge-constants)
|
||||
|
||||
# Make sure -fstack-check isn't enabled (like gentoo apparently did)
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-stack-check,)
|
||||
|
||||
@@ -1096,6 +1169,22 @@ prepare-objtool: $(objtool_target)
|
||||
# CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!")
|
||||
PHONY += prepare-compiler-check
|
||||
prepare-compiler-check: FORCE
|
||||
# Make sure we're using a supported toolchain with LTO_CLANG
|
||||
ifdef CONFIG_LTO_CLANG
|
||||
ifneq ($(call clang-ifversion, -ge, 0500, y), y)
|
||||
@echo Cannot use CONFIG_LTO_CLANG: requires clang 5.0 or later >&2 && exit 1
|
||||
endif
|
||||
ifneq ($(call gold-ifversion, -ge, 112000000, y), y)
|
||||
@echo Cannot use CONFIG_LTO_CLANG: requires GNU gold 1.12 or later >&2 && exit 1
|
||||
endif
|
||||
endif
|
||||
# Make sure compiler supports LTO flags
|
||||
ifdef lto-flags
|
||||
ifeq ($(call cc-option, $(lto-flags)),)
|
||||
@echo Cannot use CONFIG_LTO: $(lto-flags) not supported by compiler \
|
||||
>&2 && exit 1
|
||||
endif
|
||||
endif
|
||||
# Make sure compiler supports requested stack protector flag.
|
||||
ifdef stackp-name
|
||||
ifeq ($(call cc-option, $(stackp-flag)),)
|
||||
@@ -1109,6 +1198,11 @@ ifdef stackp-check
|
||||
@echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
|
||||
$(stackp-flag) available but compiler is broken >&2 && exit 1
|
||||
endif
|
||||
endif
|
||||
ifdef cfi-flags
|
||||
ifeq ($(call cc-option, $(cfi-flags)),)
|
||||
@echo Cannot use CONFIG_CFI: $(cfi-flags) not supported by compiler >&2 && exit 1
|
||||
endif
|
||||
endif
|
||||
@:
|
||||
|
||||
@@ -1583,7 +1677,8 @@ clean: $(clean-dirs)
|
||||
-o -name modules.builtin -o -name '.tmp_*.o.*' \
|
||||
-o -name '*.c.[012]*.*' \
|
||||
-o -name '*.ll' \
|
||||
-o -name '*.gcno' \) -type f -print | xargs rm -f
|
||||
-o -name '*.gcno' \
|
||||
-o -name '*.*.symversions' \) -type f -print | xargs rm -f
|
||||
|
||||
# Generate tags for editors
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -1647,11 +1742,11 @@ image_name:
|
||||
# Clear a bunch of variables before executing the submake
|
||||
tools/: FORCE
|
||||
$(Q)mkdir -p $(objtree)/tools
|
||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
|
||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
|
||||
|
||||
tools/%: FORCE
|
||||
$(Q)mkdir -p $(objtree)/tools
|
||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*
|
||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*
|
||||
|
||||
# Single targets
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
68
arch/Kconfig
68
arch/Kconfig
@@ -489,6 +489,74 @@ config LD_DEAD_CODE_DATA_ELIMINATION
|
||||
sections (e.g., '.text.init'). Typically '.' in section names
|
||||
is used to distinguish them from label names / C identifiers.
|
||||
|
||||
config LTO
|
||||
def_bool n
|
||||
|
||||
config ARCH_SUPPORTS_LTO_CLANG
|
||||
bool
|
||||
help
|
||||
An architecture should select this option it supports:
|
||||
- compiling with clang,
|
||||
- compiling inline assembly with clang's integrated assembler,
|
||||
- and linking with either lld or GNU gold w/ LLVMgold.
|
||||
|
||||
choice
|
||||
prompt "Link-Time Optimization (LTO) (EXPERIMENTAL)"
|
||||
default LTO_NONE
|
||||
help
|
||||
This option turns on Link-Time Optimization (LTO).
|
||||
|
||||
config LTO_NONE
|
||||
bool "None"
|
||||
|
||||
config LTO_CLANG
|
||||
bool "Use clang Link Time Optimization (LTO) (EXPERIMENTAL)"
|
||||
depends on ARCH_SUPPORTS_LTO_CLANG
|
||||
depends on !FTRACE_MCOUNT_RECORD || HAVE_C_RECORDMCOUNT
|
||||
select LTO
|
||||
select THIN_ARCHIVES
|
||||
select LD_DEAD_CODE_DATA_ELIMINATION
|
||||
help
|
||||
This option enables clang's Link Time Optimization (LTO), which allows
|
||||
the compiler to optimize the kernel globally at link time. If you
|
||||
enable this option, the compiler generates LLVM IR instead of object
|
||||
files, and the actual compilation from IR occurs at the LTO link step,
|
||||
which may take several minutes.
|
||||
|
||||
If you select this option, you must compile the kernel with clang >=
|
||||
5.0 (make CC=clang) and GNU gold from binutils >= 2.27, and have the
|
||||
LLVMgold plug-in in LD_LIBRARY_PATH.
|
||||
|
||||
endchoice
|
||||
|
||||
config CFI
|
||||
bool
|
||||
|
||||
config CFI_PERMISSIVE
|
||||
bool "Use CFI in permissive mode"
|
||||
depends on CFI
|
||||
help
|
||||
When selected, Control Flow Integrity (CFI) violations result in a
|
||||
warning instead of a kernel panic. This option is useful for finding
|
||||
CFI violations in drivers during development.
|
||||
|
||||
config CFI_CLANG
|
||||
bool "Use clang Control Flow Integrity (CFI) (EXPERIMENTAL)"
|
||||
depends on LTO_CLANG
|
||||
depends on KALLSYMS
|
||||
select CFI
|
||||
help
|
||||
This option enables clang Control Flow Integrity (CFI), which adds
|
||||
runtime checking for indirect function calls.
|
||||
|
||||
config CFI_CLANG_SHADOW
|
||||
bool "Use CFI shadow to speed up cross-module checks"
|
||||
default y
|
||||
depends on CFI_CLANG
|
||||
help
|
||||
If you select this option, the kernel builds a fast look-up table of
|
||||
CFI check functions in loaded modules to reduce overhead.
|
||||
|
||||
config HAVE_ARCH_WITHIN_STACK_FRAMES
|
||||
bool
|
||||
help
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
struct pci_controller *pci_vga_hose;
|
||||
static struct resource alpha_vga = {
|
||||
.name = "alpha-vga+",
|
||||
.flags = IORESOURCE_IO,
|
||||
.start = 0x3C0,
|
||||
.end = 0x3DF
|
||||
};
|
||||
|
||||
@@ -143,7 +143,8 @@ struct pci_iommu_arena
|
||||
};
|
||||
|
||||
#if defined(CONFIG_ALPHA_SRM) && \
|
||||
(defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA))
|
||||
(defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA) || \
|
||||
defined(CONFIG_ALPHA_AVANTI))
|
||||
# define NEED_SRM_SAVE_RESTORE
|
||||
#else
|
||||
# undef NEED_SRM_SAVE_RESTORE
|
||||
|
||||
@@ -265,12 +265,13 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||
application calling fork. */
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
childti->pcb.unique = regs->r20;
|
||||
else
|
||||
regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */
|
||||
childti->pcb.usp = usp ?: rdusp();
|
||||
*childregs = *regs;
|
||||
childregs->r0 = 0;
|
||||
childregs->r19 = 0;
|
||||
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
|
||||
regs->r20 = 0;
|
||||
stack = ((struct switch_stack *) regs) - 1;
|
||||
*childstack = *stack;
|
||||
childstack->r26 = (unsigned long) ret_from_fork;
|
||||
|
||||
@@ -158,11 +158,16 @@ void show_stack(struct task_struct *task, unsigned long *sp)
|
||||
for(i=0; i < kstack_depth_to_print; i++) {
|
||||
if (((long) stack & (THREAD_SIZE-1)) == 0)
|
||||
break;
|
||||
if (i && ((i % 4) == 0))
|
||||
printk("\n ");
|
||||
printk("%016lx ", *stack++);
|
||||
if ((i % 4) == 0) {
|
||||
if (i)
|
||||
pr_cont("\n");
|
||||
printk(" ");
|
||||
} else {
|
||||
pr_cont(" ");
|
||||
}
|
||||
pr_cont("%016lx", *stack++);
|
||||
}
|
||||
printk("\n");
|
||||
pr_cont("\n");
|
||||
dik_show_trace(sp);
|
||||
}
|
||||
|
||||
|
||||
@@ -926,7 +926,8 @@
|
||||
reg = <0x48038000 0x2000>,
|
||||
<0x46000000 0x400000>;
|
||||
reg-names = "mpu", "dat";
|
||||
interrupts = <80>, <81>;
|
||||
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "tx", "rx";
|
||||
status = "disabled";
|
||||
dmas = <&edma 8 2>,
|
||||
@@ -940,7 +941,8 @@
|
||||
reg = <0x4803C000 0x2000>,
|
||||
<0x46400000 0x400000>;
|
||||
reg-names = "mpu", "dat";
|
||||
interrupts = <82>, <83>;
|
||||
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "tx", "rx";
|
||||
status = "disabled";
|
||||
dmas = <&edma 10 2>,
|
||||
|
||||
@@ -301,8 +301,8 @@
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi0_pins>;
|
||||
dmas = <&edma 16
|
||||
&edma 17>;
|
||||
dmas = <&edma 16 0
|
||||
&edma 17 0>;
|
||||
dma-names = "tx0", "rx0";
|
||||
|
||||
flash: w25q64cvzpig@0 {
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
interrupt-controller;
|
||||
|
||||
ti,system-power-controller;
|
||||
ti,palmas-override-powerhold;
|
||||
|
||||
tps659038_pmic {
|
||||
compatible = "ti,tps659038-pmic";
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
ti,system-power-controller;
|
||||
ti,palmas-override-powerhold;
|
||||
|
||||
tps659038_pmic {
|
||||
compatible = "ti,tps659038-pmic";
|
||||
|
||||
@@ -150,11 +150,6 @@
|
||||
interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
&charlcd {
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
&serial0 {
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
bootargs = "console=ttyS4,115200 earlyprintk";
|
||||
};
|
||||
|
||||
memory {
|
||||
memory@80000000 {
|
||||
reg = <0x80000000 0x20000000>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
timer@20200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0x20200 0x100>;
|
||||
interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&periph_clk>;
|
||||
};
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
compatible = "arm,cortex-a9-twd-timer";
|
||||
reg = <0x20600 0x20>;
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
|
||||
IRQ_TYPE_LEVEL_HIGH)>;
|
||||
IRQ_TYPE_EDGE_RISING)>;
|
||||
clocks = <&periph_clk>;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/ {
|
||||
aliases {
|
||||
ethernet = ðernet;
|
||||
ethernet0 = ðernet;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/ {
|
||||
aliases {
|
||||
ethernet = ðernet;
|
||||
ethernet0 = ðernet;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -398,6 +398,8 @@
|
||||
tps659038: tps659038@58 {
|
||||
compatible = "ti,tps659038";
|
||||
reg = <0x58>;
|
||||
ti,palmas-override-powerhold;
|
||||
ti,system-power-controller;
|
||||
|
||||
tps659038_pmic {
|
||||
compatible = "ti,tps659038-pmic";
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
reg = <0>;
|
||||
vdd3-supply = <&lcd_vdd3_reg>;
|
||||
vci-supply = <&ldo25_reg>;
|
||||
reset-gpios = <&gpy4 5 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpf2 1 GPIO_ACTIVE_HIGH>;
|
||||
power-on-delay= <50>;
|
||||
reset-delay = <100>;
|
||||
init-delay = <100>;
|
||||
|
||||
@@ -274,7 +274,6 @@
|
||||
&rtc {
|
||||
clocks = <&clock CLK_RTC>;
|
||||
clock-names = "rtc";
|
||||
interrupt-parent = <&pmu_system_controller>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
};
|
||||
|
||||
pinctrl: pin-controller@10000 {
|
||||
pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header>;
|
||||
pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header
|
||||
&pmx_gpio_header_gpo>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
pmx_uart0: pmx-uart0 {
|
||||
@@ -85,11 +86,16 @@
|
||||
* ground.
|
||||
*/
|
||||
pmx_gpio_header: pmx-gpio-header {
|
||||
marvell,pins = "mpp17", "mpp7", "mpp29", "mpp28",
|
||||
marvell,pins = "mpp17", "mpp29", "mpp28",
|
||||
"mpp35", "mpp34", "mpp40";
|
||||
marvell,function = "gpio";
|
||||
};
|
||||
|
||||
pmx_gpio_header_gpo: pxm-gpio-header-gpo {
|
||||
marvell,pins = "mpp7";
|
||||
marvell,function = "gpo";
|
||||
};
|
||||
|
||||
pmx_gpio_init: pmx-init {
|
||||
marvell,pins = "mpp38";
|
||||
marvell,function = "gpio";
|
||||
|
||||
@@ -72,7 +72,8 @@
|
||||
};
|
||||
|
||||
&gpmc {
|
||||
ranges = <1 0 0x08000000 0x1000000>; /* CS1: 16MB for LAN9221 */
|
||||
ranges = <0 0 0x30000000 0x1000000 /* CS0: 16MB for NAND */
|
||||
1 0 0x2c000000 0x1000000>; /* CS1: 16MB for LAN9221 */
|
||||
|
||||
ethernet@gpmc {
|
||||
pinctrl-names = "default";
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
};
|
||||
|
||||
&gpmc {
|
||||
ranges = <0 0 0x00000000 0x1000000>; /* CS0: 16MB for NAND */
|
||||
ranges = <0 0 0x30000000 0x1000000>; /* CS0: 16MB for NAND */
|
||||
|
||||
nand@0,0 {
|
||||
compatible = "ti,omap2-nand";
|
||||
@@ -97,6 +97,8 @@
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins>;
|
||||
clock-frequency = <2600000>;
|
||||
|
||||
twl: twl@48 {
|
||||
@@ -121,7 +123,7 @@
|
||||
|
||||
&mmc3 {
|
||||
interrupts-extended = <&intc 94 &omap3_pmx_core2 0x46>;
|
||||
pinctrl-0 = <&mmc3_pins>;
|
||||
pinctrl-0 = <&mmc3_pins &wl127x_gpio>;
|
||||
pinctrl-names = "default";
|
||||
vmmc-supply = <&wl12xx_vmmc>;
|
||||
non-removable;
|
||||
@@ -132,8 +134,8 @@
|
||||
wlcore: wlcore@2 {
|
||||
compatible = "ti,wl1273";
|
||||
reg = <2>;
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <24 IRQ_TYPE_LEVEL_HIGH>; /* gpio 152 */
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; /* gpio 2 */
|
||||
ref-clock-frequency = <26000000>;
|
||||
};
|
||||
};
|
||||
@@ -157,8 +159,6 @@
|
||||
OMAP3_CORE1_IOPAD(0x2166, PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc2_dat5.sdmmc3_dat1 */
|
||||
OMAP3_CORE1_IOPAD(0x2168, PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc2_dat6.sdmmc3_dat2 */
|
||||
OMAP3_CORE1_IOPAD(0x216a, PIN_INPUT_PULLUP | MUX_MODE3) /* sdmmc2_dat6.sdmmc3_dat3 */
|
||||
OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT_PULLUP | MUX_MODE4) /* mcbsp4_clkx.gpio_152 */
|
||||
OMAP3_CORE1_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE4) /* sys_boot1.gpio_3 */
|
||||
OMAP3_CORE1_IOPAD(0x21d0, PIN_INPUT_PULLUP | MUX_MODE3) /* mcspi1_cs1.sdmmc3_cmd */
|
||||
OMAP3_CORE1_IOPAD(0x21d2, PIN_INPUT_PULLUP | MUX_MODE3) /* mcspi1_cs2.sdmmc_clk */
|
||||
>;
|
||||
@@ -217,7 +217,12 @@
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
i2c1_pins: pinmux_i2c1_pins {
|
||||
pinctrl-single,pins = <
|
||||
OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */
|
||||
OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&omap3_pmx_wkup {
|
||||
@@ -228,6 +233,12 @@
|
||||
OMAP3_WKUP_IOPAD(0x2a0e, PIN_OUTPUT | MUX_MODE4) /* sys_boot2.gpio_4 */
|
||||
>;
|
||||
};
|
||||
wl127x_gpio: pinmux_wl127x_gpio_pin {
|
||||
pinctrl-single,pins = <
|
||||
OMAP3_WKUP_IOPAD(0x2a0c, PIN_INPUT | MUX_MODE4) /* sys_boot0.gpio_2 */
|
||||
OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE4) /* sys_boot1.gpio_3 */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&omap3_pmx_core2 {
|
||||
|
||||
@@ -100,6 +100,8 @@
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins>;
|
||||
clock-frequency = <2600000>;
|
||||
|
||||
twl: twl@48 {
|
||||
@@ -207,6 +209,12 @@
|
||||
OMAP3_CORE1_IOPAD(0x21b8, PIN_INPUT | MUX_MODE0) /* hsusb0_data7.hsusb0_data7 */
|
||||
>;
|
||||
};
|
||||
i2c1_pins: pinmux_i2c1_pins {
|
||||
pinctrl-single,pins = <
|
||||
OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */
|
||||
OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
|
||||
@@ -156,8 +156,8 @@
|
||||
uda1380: uda1380@18 {
|
||||
compatible = "nxp,uda1380";
|
||||
reg = <0x18>;
|
||||
power-gpio = <&gpio 0x59 0>;
|
||||
reset-gpio = <&gpio 0x51 0>;
|
||||
power-gpio = <&gpio 3 10 0>;
|
||||
reset-gpio = <&gpio 3 2 0>;
|
||||
dac-clk = "wspll";
|
||||
};
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@
|
||||
uda1380: uda1380@18 {
|
||||
compatible = "nxp,uda1380";
|
||||
reg = <0x18>;
|
||||
power-gpio = <&gpio 0x59 0>;
|
||||
reset-gpio = <&gpio 0x51 0>;
|
||||
power-gpio = <&gpio 3 10 0>;
|
||||
reset-gpio = <&gpio 3 2 0>;
|
||||
dac-clk = "wspll";
|
||||
};
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
reg = <0x2a>;
|
||||
VDDA-supply = <®_3p3v>;
|
||||
VDDIO-supply = <®_3p3v>;
|
||||
clocks = <&sys_mclk 1>;
|
||||
clocks = <&sys_mclk>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
reg = <0x0a>;
|
||||
VDDA-supply = <®_3p3v>;
|
||||
VDDIO-supply = <®_3p3v>;
|
||||
clocks = <&sys_mclk 1>;
|
||||
clocks = <&sys_mclk>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "moxart.dtsi"
|
||||
#include "moxart.dtsi"
|
||||
|
||||
/ {
|
||||
model = "MOXA UC-7112-LX";
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
/include/ "skeleton.dtsi"
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
/ {
|
||||
compatible = "moxa,moxart";
|
||||
@@ -36,8 +37,8 @@
|
||||
ranges;
|
||||
|
||||
intc: interrupt-controller@98800000 {
|
||||
compatible = "moxa,moxart-ic";
|
||||
reg = <0x98800000 0x38>;
|
||||
compatible = "moxa,moxart-ic", "faraday,ftintc010";
|
||||
reg = <0x98800000 0x100>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-mask = <0x00080000>;
|
||||
@@ -59,7 +60,7 @@
|
||||
timer: timer@98400000 {
|
||||
compatible = "moxa,moxart-timer";
|
||||
reg = <0x98400000 0x42>;
|
||||
interrupts = <19 1>;
|
||||
interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
|
||||
clocks = <&clk_apb>;
|
||||
};
|
||||
|
||||
@@ -80,7 +81,7 @@
|
||||
dma: dma@90500000 {
|
||||
compatible = "moxa,moxart-dma";
|
||||
reg = <0x90500080 0x40>;
|
||||
interrupts = <24 0>;
|
||||
interrupts = <24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#dma-cells = <1>;
|
||||
};
|
||||
|
||||
@@ -93,7 +94,7 @@
|
||||
sdhci: sdhci@98e00000 {
|
||||
compatible = "moxa,moxart-sdhci";
|
||||
reg = <0x98e00000 0x5C>;
|
||||
interrupts = <5 0>;
|
||||
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clk_apb>;
|
||||
dmas = <&dma 5>,
|
||||
<&dma 5>;
|
||||
@@ -120,7 +121,7 @@
|
||||
mac0: mac@90900000 {
|
||||
compatible = "moxa,moxart-mac";
|
||||
reg = <0x90900000 0x90>;
|
||||
interrupts = <25 0>;
|
||||
interrupts = <25 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phy-handle = <ðphy0>;
|
||||
phy-mode = "mii";
|
||||
status = "disabled";
|
||||
@@ -129,7 +130,7 @@
|
||||
mac1: mac@92000000 {
|
||||
compatible = "moxa,moxart-mac";
|
||||
reg = <0x92000000 0x90>;
|
||||
interrupts = <27 0>;
|
||||
interrupts = <27 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phy-handle = <ðphy1>;
|
||||
phy-mode = "mii";
|
||||
status = "disabled";
|
||||
@@ -138,7 +139,7 @@
|
||||
uart0: uart@98200000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x98200000 0x20>;
|
||||
interrupts = <31 8>;
|
||||
interrupts = <31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
clock-frequency = <14745600>;
|
||||
|
||||
@@ -197,12 +197,14 @@
|
||||
compatible = "mediatek,mt2701-hifsys", "syscon";
|
||||
reg = <0 0x1a000000 0 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
ethsys: syscon@1b000000 {
|
||||
compatible = "mediatek,mt2701-ethsys", "syscon";
|
||||
reg = <0 0x1b000000 0 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
bdpsys: syscon@1c000000 {
|
||||
|
||||
@@ -352,7 +352,7 @@
|
||||
elm: elm@48078000 {
|
||||
compatible = "ti,am3352-elm";
|
||||
reg = <0x48078000 0x2000>;
|
||||
interrupts = <4>;
|
||||
interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "elm";
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -859,14 +859,12 @@
|
||||
usbhsohci: ohci@4a064800 {
|
||||
compatible = "ti,ohci-omap3";
|
||||
reg = <0x4a064800 0x400>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
usbhsehci: ehci@4a064c00 {
|
||||
compatible = "ti,ehci-omap";
|
||||
reg = <0x4a064c00 0x400>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
#clock-cells = <1>;
|
||||
compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
|
||||
reg = <0xfcfe0430 4>;
|
||||
clocks = <&p0_clk>;
|
||||
clocks = <&b_clk>;
|
||||
clock-indices = <R7S72100_CLK_ETHER>;
|
||||
clock-output-names = "ether";
|
||||
};
|
||||
|
||||
@@ -1437,8 +1437,11 @@
|
||||
compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
|
||||
reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
|
||||
clocks = <&p_clk>,
|
||||
<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
|
||||
<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
|
||||
<&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
|
||||
<&p_clk>,
|
||||
<&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
|
||||
<&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
x2_clk: x2-clock {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <148500000>;
|
||||
clock-frequency = <74250000>;
|
||||
};
|
||||
|
||||
x13_clk: x13-clock {
|
||||
|
||||
@@ -74,9 +74,8 @@
|
||||
next-level-cache = <&L2_CA15>;
|
||||
};
|
||||
|
||||
L2_CA15: cache-controller@0 {
|
||||
L2_CA15: cache-controller-0 {
|
||||
compatible = "cache";
|
||||
reg = <0>;
|
||||
power-domains = <&sysc R8A7791_PD_CA15_SCU>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
@@ -1438,8 +1437,11 @@
|
||||
compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
|
||||
reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
|
||||
clocks = <&p_clk>,
|
||||
<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
|
||||
<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
|
||||
<&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
|
||||
<&p_clk>,
|
||||
<&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
|
||||
<&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
|
||||
|
||||
@@ -58,9 +58,8 @@
|
||||
next-level-cache = <&L2_CA15>;
|
||||
};
|
||||
|
||||
L2_CA15: cache-controller@0 {
|
||||
L2_CA15: cache-controller-0 {
|
||||
compatible = "cache";
|
||||
reg = <0>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
power-domains = <&sysc R8A7792_PD_CA15_SCU>;
|
||||
|
||||
@@ -65,9 +65,8 @@
|
||||
power-domains = <&sysc R8A7793_PD_CA15_CPU1>;
|
||||
};
|
||||
|
||||
L2_CA15: cache-controller@0 {
|
||||
L2_CA15: cache-controller-0 {
|
||||
compatible = "cache";
|
||||
reg = <0>;
|
||||
power-domains = <&sysc R8A7793_PD_CA15_SCU>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
@@ -1235,8 +1234,11 @@
|
||||
compatible = "renesas,r8a7793-mstp-clocks", "renesas,cpg-mstp-clocks";
|
||||
reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
|
||||
clocks = <&p_clk>,
|
||||
<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
|
||||
<&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
|
||||
<&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
|
||||
<&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
|
||||
<&p_clk>,
|
||||
<&mstp10_clks R8A7793_CLK_SCU_ALL>, <&mstp10_clks R8A7793_CLK_SCU_ALL>,
|
||||
<&mstp10_clks R8A7793_CLK_SCU_ALL>, <&mstp10_clks R8A7793_CLK_SCU_ALL>,
|
||||
|
||||
@@ -425,7 +425,7 @@
|
||||
status = "okay";
|
||||
|
||||
clocks = <&mstp7_clks R8A7794_CLK_DU0>,
|
||||
<&mstp7_clks R8A7794_CLK_DU0>,
|
||||
<&mstp7_clks R8A7794_CLK_DU1>,
|
||||
<&x2_clk>, <&x3_clk>;
|
||||
clock-names = "du.0", "du.1", "dclkin.0", "dclkin.1";
|
||||
|
||||
|
||||
@@ -56,9 +56,8 @@
|
||||
next-level-cache = <&L2_CA7>;
|
||||
};
|
||||
|
||||
L2_CA7: cache-controller@0 {
|
||||
L2_CA7: cache-controller-0 {
|
||||
compatible = "cache";
|
||||
reg = <0>;
|
||||
power-domains = <&sysc R8A7794_PD_CA7_SCU>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
@@ -917,7 +916,7 @@
|
||||
interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&mstp7_clks R8A7794_CLK_DU0>,
|
||||
<&mstp7_clks R8A7794_CLK_DU0>;
|
||||
<&mstp7_clks R8A7794_CLK_DU1>;
|
||||
clock-names = "du.0", "du.1";
|
||||
status = "disabled";
|
||||
|
||||
@@ -1262,19 +1261,21 @@
|
||||
clocks = <&mp_clk>, <&hp_clk>,
|
||||
<&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>,
|
||||
<&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
|
||||
<&zx_clk>;
|
||||
<&zx_clk>, <&zx_clk>;
|
||||
#clock-cells = <1>;
|
||||
clock-indices = <
|
||||
R8A7794_CLK_EHCI R8A7794_CLK_HSUSB
|
||||
R8A7794_CLK_HSCIF2 R8A7794_CLK_SCIF5
|
||||
R8A7794_CLK_SCIF4 R8A7794_CLK_HSCIF1 R8A7794_CLK_HSCIF0
|
||||
R8A7794_CLK_SCIF3 R8A7794_CLK_SCIF2 R8A7794_CLK_SCIF1
|
||||
R8A7794_CLK_SCIF0 R8A7794_CLK_DU0
|
||||
R8A7794_CLK_SCIF0
|
||||
R8A7794_CLK_DU1 R8A7794_CLK_DU0
|
||||
>;
|
||||
clock-output-names =
|
||||
"ehci", "hsusb",
|
||||
"hscif2", "scif5", "scif4", "hscif1", "hscif0",
|
||||
"scif3", "scif2", "scif1", "scif0", "du0";
|
||||
"scif3", "scif2", "scif1", "scif0",
|
||||
"du1", "du0";
|
||||
};
|
||||
mstp8_clks: mstp8_clks@e6150990 {
|
||||
compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
|
||||
|
||||
@@ -463,6 +463,7 @@
|
||||
compatible = "samsung,exynos4210-ohci";
|
||||
reg = <0xec300000 0x100>;
|
||||
interrupts = <23>;
|
||||
interrupt-parent = <&vic1>;
|
||||
clocks = <&clocks CLK_USB_HOST>;
|
||||
clock-names = "usbhost";
|
||||
#address-cells = <1>;
|
||||
|
||||
@@ -349,7 +349,7 @@
|
||||
spi0: spi@e0100000 {
|
||||
status = "okay";
|
||||
num-cs = <3>;
|
||||
cs-gpios = <&gpio1 7 0>, <&spics 0>, <&spics 1>;
|
||||
cs-gpios = <&gpio1 7 0>, <&spics 0 0>, <&spics 1 0>;
|
||||
|
||||
stmpe610@0 {
|
||||
compatible = "st,stmpe610";
|
||||
|
||||
@@ -141,8 +141,8 @@
|
||||
reg = <0xb4100000 0x1000>;
|
||||
interrupts = <0 105 0x4>;
|
||||
status = "disabled";
|
||||
dmas = <&dwdma0 0x600 0 0 1>, /* 0xC << 11 */
|
||||
<&dwdma0 0x680 0 1 0>; /* 0xD << 7 */
|
||||
dmas = <&dwdma0 12 0 1>,
|
||||
<&dwdma0 13 1 0>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
reg = <0xb2800000 0x1000>;
|
||||
interrupts = <0 29 0x4>;
|
||||
status = "disabled";
|
||||
dmas = <&dwdma0 0 0 0 0>;
|
||||
dmas = <&dwdma0 0 0 0>;
|
||||
dma-names = "data";
|
||||
};
|
||||
|
||||
@@ -288,8 +288,8 @@
|
||||
#size-cells = <0>;
|
||||
interrupts = <0 31 0x4>;
|
||||
status = "disabled";
|
||||
dmas = <&dwdma0 0x2000 0 0 0>, /* 0x4 << 11 */
|
||||
<&dwdma0 0x0280 0 0 0>; /* 0x5 << 7 */
|
||||
dmas = <&dwdma0 4 0 0>,
|
||||
<&dwdma0 5 0 0>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
|
||||
@@ -194,6 +194,7 @@
|
||||
rtc@fc900000 {
|
||||
compatible = "st,spear600-rtc";
|
||||
reg = <0xfc900000 0x1000>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <10>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -749,6 +749,7 @@
|
||||
reg = <0x10120000 0x1000>;
|
||||
interrupt-names = "combined";
|
||||
interrupts = <14>;
|
||||
interrupt-parent = <&vica>;
|
||||
clocks = <&clcdclk>, <&hclkclcd>;
|
||||
clock-names = "clcdclk", "apb_pclk";
|
||||
status = "disabled";
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#include "stih407-clock.dtsi"
|
||||
#include "stih407-family.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
/ {
|
||||
soc {
|
||||
sti-display-subsystem {
|
||||
@@ -122,7 +123,7 @@
|
||||
<&clk_s_d2_quadfs 0>,
|
||||
<&clk_s_d2_quadfs 1>;
|
||||
|
||||
hdmi,hpd-gpio = <&pio5 3>;
|
||||
hdmi,hpd-gpio = <&pio5 3 GPIO_ACTIVE_LOW>;
|
||||
reset-names = "hdmi";
|
||||
resets = <&softreset STIH407_HDMI_TX_PHY_SOFTRESET>;
|
||||
ddc = <&hdmiddc>;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "stih410-clock.dtsi"
|
||||
#include "stih407-family.dtsi"
|
||||
#include "stih410-pinctrl.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
/ {
|
||||
aliases {
|
||||
bdisp0 = &bdisp0;
|
||||
@@ -213,7 +214,7 @@
|
||||
<&clk_s_d2_quadfs 0>,
|
||||
<&clk_s_d2_quadfs 1>;
|
||||
|
||||
hdmi,hpd-gpio = <&pio5 3>;
|
||||
hdmi,hpd-gpio = <&pio5 3 GPIO_ACTIVE_LOW>;
|
||||
reset-names = "hdmi";
|
||||
resets = <&softreset STIH407_HDMI_TX_PHY_SOFTRESET>;
|
||||
ddc = <&hdmiddc>;
|
||||
|
||||
@@ -57,3 +57,7 @@ static struct miscdevice bL_switcher_device = {
|
||||
&bL_switcher_fops
|
||||
};
|
||||
module_misc_device(bL_switcher_device);
|
||||
|
||||
MODULE_AUTHOR("Nicolas Pitre <nico@linaro.org>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("big.LITTLE switcher dummy user interface");
|
||||
|
||||
@@ -120,4 +120,11 @@ config CRYPTO_GHASH_ARM_CE
|
||||
that uses the 64x64 to 128 bit polynomial multiplication (vmull.p64)
|
||||
that is part of the ARMv8 Crypto Extensions
|
||||
|
||||
config CRYPTO_SPECK_NEON
|
||||
tristate "NEON accelerated Speck cipher algorithms"
|
||||
depends on KERNEL_MODE_NEON
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_GF128MUL
|
||||
select CRYPTO_SPECK
|
||||
|
||||
endif
|
||||
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
|
||||
obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
|
||||
obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
|
||||
obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o
|
||||
obj-$(CONFIG_CRYPTO_SPECK_NEON) += speck-neon.o
|
||||
|
||||
ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
|
||||
ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
|
||||
@@ -36,6 +37,7 @@ sha1-arm-ce-y := sha1-ce-core.o sha1-ce-glue.o
|
||||
sha2-arm-ce-y := sha2-ce-core.o sha2-ce-glue.o
|
||||
aes-arm-ce-y := aes-ce-core.o aes-ce-glue.o
|
||||
ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o
|
||||
speck-neon-y := speck-neon-core.o speck-neon-glue.o
|
||||
|
||||
quiet_cmd_perl = PERL $@
|
||||
cmd_perl = $(PERL) $(<) > $(@)
|
||||
|
||||
432
arch/arm/crypto/speck-neon-core.S
Normal file
432
arch/arm/crypto/speck-neon-core.S
Normal file
@@ -0,0 +1,432 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* NEON-accelerated implementation of Speck128-XTS and Speck64-XTS
|
||||
*
|
||||
* Copyright (c) 2018 Google, Inc
|
||||
*
|
||||
* Author: Eric Biggers <ebiggers@google.com>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.text
|
||||
.fpu neon
|
||||
|
||||
// arguments
|
||||
ROUND_KEYS .req r0 // const {u64,u32} *round_keys
|
||||
NROUNDS .req r1 // int nrounds
|
||||
DST .req r2 // void *dst
|
||||
SRC .req r3 // const void *src
|
||||
NBYTES .req r4 // unsigned int nbytes
|
||||
TWEAK .req r5 // void *tweak
|
||||
|
||||
// registers which hold the data being encrypted/decrypted
|
||||
X0 .req q0
|
||||
X0_L .req d0
|
||||
X0_H .req d1
|
||||
Y0 .req q1
|
||||
Y0_H .req d3
|
||||
X1 .req q2
|
||||
X1_L .req d4
|
||||
X1_H .req d5
|
||||
Y1 .req q3
|
||||
Y1_H .req d7
|
||||
X2 .req q4
|
||||
X2_L .req d8
|
||||
X2_H .req d9
|
||||
Y2 .req q5
|
||||
Y2_H .req d11
|
||||
X3 .req q6
|
||||
X3_L .req d12
|
||||
X3_H .req d13
|
||||
Y3 .req q7
|
||||
Y3_H .req d15
|
||||
|
||||
// the round key, duplicated in all lanes
|
||||
ROUND_KEY .req q8
|
||||
ROUND_KEY_L .req d16
|
||||
ROUND_KEY_H .req d17
|
||||
|
||||
// index vector for vtbl-based 8-bit rotates
|
||||
ROTATE_TABLE .req d18
|
||||
|
||||
// multiplication table for updating XTS tweaks
|
||||
GF128MUL_TABLE .req d19
|
||||
GF64MUL_TABLE .req d19
|
||||
|
||||
// current XTS tweak value(s)
|
||||
TWEAKV .req q10
|
||||
TWEAKV_L .req d20
|
||||
TWEAKV_H .req d21
|
||||
|
||||
TMP0 .req q12
|
||||
TMP0_L .req d24
|
||||
TMP0_H .req d25
|
||||
TMP1 .req q13
|
||||
TMP2 .req q14
|
||||
TMP3 .req q15
|
||||
|
||||
.align 4
|
||||
.Lror64_8_table:
|
||||
.byte 1, 2, 3, 4, 5, 6, 7, 0
|
||||
.Lror32_8_table:
|
||||
.byte 1, 2, 3, 0, 5, 6, 7, 4
|
||||
.Lrol64_8_table:
|
||||
.byte 7, 0, 1, 2, 3, 4, 5, 6
|
||||
.Lrol32_8_table:
|
||||
.byte 3, 0, 1, 2, 7, 4, 5, 6
|
||||
.Lgf128mul_table:
|
||||
.byte 0, 0x87
|
||||
.fill 14
|
||||
.Lgf64mul_table:
|
||||
.byte 0, 0x1b, (0x1b << 1), (0x1b << 1) ^ 0x1b
|
||||
.fill 12
|
||||
|
||||
/*
|
||||
* _speck_round_128bytes() - Speck encryption round on 128 bytes at a time
|
||||
*
|
||||
* Do one Speck encryption round on the 128 bytes (8 blocks for Speck128, 16 for
|
||||
* Speck64) stored in X0-X3 and Y0-Y3, using the round key stored in all lanes
|
||||
* of ROUND_KEY. 'n' is the lane size: 64 for Speck128, or 32 for Speck64.
|
||||
*
|
||||
* The 8-bit rotates are implemented using vtbl instead of vshr + vsli because
|
||||
* the vtbl approach is faster on some processors and the same speed on others.
|
||||
*/
|
||||
.macro _speck_round_128bytes n
|
||||
|
||||
// x = ror(x, 8)
|
||||
vtbl.8 X0_L, {X0_L}, ROTATE_TABLE
|
||||
vtbl.8 X0_H, {X0_H}, ROTATE_TABLE
|
||||
vtbl.8 X1_L, {X1_L}, ROTATE_TABLE
|
||||
vtbl.8 X1_H, {X1_H}, ROTATE_TABLE
|
||||
vtbl.8 X2_L, {X2_L}, ROTATE_TABLE
|
||||
vtbl.8 X2_H, {X2_H}, ROTATE_TABLE
|
||||
vtbl.8 X3_L, {X3_L}, ROTATE_TABLE
|
||||
vtbl.8 X3_H, {X3_H}, ROTATE_TABLE
|
||||
|
||||
// x += y
|
||||
vadd.u\n X0, Y0
|
||||
vadd.u\n X1, Y1
|
||||
vadd.u\n X2, Y2
|
||||
vadd.u\n X3, Y3
|
||||
|
||||
// x ^= k
|
||||
veor X0, ROUND_KEY
|
||||
veor X1, ROUND_KEY
|
||||
veor X2, ROUND_KEY
|
||||
veor X3, ROUND_KEY
|
||||
|
||||
// y = rol(y, 3)
|
||||
vshl.u\n TMP0, Y0, #3
|
||||
vshl.u\n TMP1, Y1, #3
|
||||
vshl.u\n TMP2, Y2, #3
|
||||
vshl.u\n TMP3, Y3, #3
|
||||
vsri.u\n TMP0, Y0, #(\n - 3)
|
||||
vsri.u\n TMP1, Y1, #(\n - 3)
|
||||
vsri.u\n TMP2, Y2, #(\n - 3)
|
||||
vsri.u\n TMP3, Y3, #(\n - 3)
|
||||
|
||||
// y ^= x
|
||||
veor Y0, TMP0, X0
|
||||
veor Y1, TMP1, X1
|
||||
veor Y2, TMP2, X2
|
||||
veor Y3, TMP3, X3
|
||||
.endm
|
||||
|
||||
/*
|
||||
* _speck_unround_128bytes() - Speck decryption round on 128 bytes at a time
|
||||
*
|
||||
* This is the inverse of _speck_round_128bytes().
|
||||
*/
|
||||
.macro _speck_unround_128bytes n
|
||||
|
||||
// y ^= x
|
||||
veor TMP0, Y0, X0
|
||||
veor TMP1, Y1, X1
|
||||
veor TMP2, Y2, X2
|
||||
veor TMP3, Y3, X3
|
||||
|
||||
// y = ror(y, 3)
|
||||
vshr.u\n Y0, TMP0, #3
|
||||
vshr.u\n Y1, TMP1, #3
|
||||
vshr.u\n Y2, TMP2, #3
|
||||
vshr.u\n Y3, TMP3, #3
|
||||
vsli.u\n Y0, TMP0, #(\n - 3)
|
||||
vsli.u\n Y1, TMP1, #(\n - 3)
|
||||
vsli.u\n Y2, TMP2, #(\n - 3)
|
||||
vsli.u\n Y3, TMP3, #(\n - 3)
|
||||
|
||||
// x ^= k
|
||||
veor X0, ROUND_KEY
|
||||
veor X1, ROUND_KEY
|
||||
veor X2, ROUND_KEY
|
||||
veor X3, ROUND_KEY
|
||||
|
||||
// x -= y
|
||||
vsub.u\n X0, Y0
|
||||
vsub.u\n X1, Y1
|
||||
vsub.u\n X2, Y2
|
||||
vsub.u\n X3, Y3
|
||||
|
||||
// x = rol(x, 8);
|
||||
vtbl.8 X0_L, {X0_L}, ROTATE_TABLE
|
||||
vtbl.8 X0_H, {X0_H}, ROTATE_TABLE
|
||||
vtbl.8 X1_L, {X1_L}, ROTATE_TABLE
|
||||
vtbl.8 X1_H, {X1_H}, ROTATE_TABLE
|
||||
vtbl.8 X2_L, {X2_L}, ROTATE_TABLE
|
||||
vtbl.8 X2_H, {X2_H}, ROTATE_TABLE
|
||||
vtbl.8 X3_L, {X3_L}, ROTATE_TABLE
|
||||
vtbl.8 X3_H, {X3_H}, ROTATE_TABLE
|
||||
.endm
|
||||
|
||||
.macro _xts128_precrypt_one dst_reg, tweak_buf, tmp
|
||||
|
||||
// Load the next source block
|
||||
vld1.8 {\dst_reg}, [SRC]!
|
||||
|
||||
// Save the current tweak in the tweak buffer
|
||||
vst1.8 {TWEAKV}, [\tweak_buf:128]!
|
||||
|
||||
// XOR the next source block with the current tweak
|
||||
veor \dst_reg, TWEAKV
|
||||
|
||||
/*
|
||||
* Calculate the next tweak by multiplying the current one by x,
|
||||
* modulo p(x) = x^128 + x^7 + x^2 + x + 1.
|
||||
*/
|
||||
vshr.u64 \tmp, TWEAKV, #63
|
||||
vshl.u64 TWEAKV, #1
|
||||
veor TWEAKV_H, \tmp\()_L
|
||||
vtbl.8 \tmp\()_H, {GF128MUL_TABLE}, \tmp\()_H
|
||||
veor TWEAKV_L, \tmp\()_H
|
||||
.endm
|
||||
|
||||
.macro _xts64_precrypt_two dst_reg, tweak_buf, tmp
|
||||
|
||||
// Load the next two source blocks
|
||||
vld1.8 {\dst_reg}, [SRC]!
|
||||
|
||||
// Save the current two tweaks in the tweak buffer
|
||||
vst1.8 {TWEAKV}, [\tweak_buf:128]!
|
||||
|
||||
// XOR the next two source blocks with the current two tweaks
|
||||
veor \dst_reg, TWEAKV
|
||||
|
||||
/*
|
||||
* Calculate the next two tweaks by multiplying the current ones by x^2,
|
||||
* modulo p(x) = x^64 + x^4 + x^3 + x + 1.
|
||||
*/
|
||||
vshr.u64 \tmp, TWEAKV, #62
|
||||
vshl.u64 TWEAKV, #2
|
||||
vtbl.8 \tmp\()_L, {GF64MUL_TABLE}, \tmp\()_L
|
||||
vtbl.8 \tmp\()_H, {GF64MUL_TABLE}, \tmp\()_H
|
||||
veor TWEAKV, \tmp
|
||||
.endm
|
||||
|
||||
/*
|
||||
* _speck_xts_crypt() - Speck-XTS encryption/decryption
|
||||
*
|
||||
* Encrypt or decrypt NBYTES bytes of data from the SRC buffer to the DST buffer
|
||||
* using Speck-XTS, specifically the variant with a block size of '2n' and round
|
||||
* count given by NROUNDS. The expanded round keys are given in ROUND_KEYS, and
|
||||
* the current XTS tweak value is given in TWEAK. It's assumed that NBYTES is a
|
||||
* nonzero multiple of 128.
|
||||
*/
|
||||
.macro _speck_xts_crypt n, decrypting
|
||||
push {r4-r7}
|
||||
mov r7, sp
|
||||
|
||||
/*
|
||||
* The first four parameters were passed in registers r0-r3. Load the
|
||||
* additional parameters, which were passed on the stack.
|
||||
*/
|
||||
ldr NBYTES, [sp, #16]
|
||||
ldr TWEAK, [sp, #20]
|
||||
|
||||
/*
|
||||
* If decrypting, modify the ROUND_KEYS parameter to point to the last
|
||||
* round key rather than the first, since for decryption the round keys
|
||||
* are used in reverse order.
|
||||
*/
|
||||
.if \decrypting
|
||||
.if \n == 64
|
||||
add ROUND_KEYS, ROUND_KEYS, NROUNDS, lsl #3
|
||||
sub ROUND_KEYS, #8
|
||||
.else
|
||||
add ROUND_KEYS, ROUND_KEYS, NROUNDS, lsl #2
|
||||
sub ROUND_KEYS, #4
|
||||
.endif
|
||||
.endif
|
||||
|
||||
// Load the index vector for vtbl-based 8-bit rotates
|
||||
.if \decrypting
|
||||
ldr r12, =.Lrol\n\()_8_table
|
||||
.else
|
||||
ldr r12, =.Lror\n\()_8_table
|
||||
.endif
|
||||
vld1.8 {ROTATE_TABLE}, [r12:64]
|
||||
|
||||
// One-time XTS preparation
|
||||
|
||||
/*
|
||||
* Allocate stack space to store 128 bytes worth of tweaks. For
|
||||
* performance, this space is aligned to a 16-byte boundary so that we
|
||||
* can use the load/store instructions that declare 16-byte alignment.
|
||||
*/
|
||||
sub sp, #128
|
||||
bic sp, #0xf
|
||||
|
||||
.if \n == 64
|
||||
// Load first tweak
|
||||
vld1.8 {TWEAKV}, [TWEAK]
|
||||
|
||||
// Load GF(2^128) multiplication table
|
||||
ldr r12, =.Lgf128mul_table
|
||||
vld1.8 {GF128MUL_TABLE}, [r12:64]
|
||||
.else
|
||||
// Load first tweak
|
||||
vld1.8 {TWEAKV_L}, [TWEAK]
|
||||
|
||||
// Load GF(2^64) multiplication table
|
||||
ldr r12, =.Lgf64mul_table
|
||||
vld1.8 {GF64MUL_TABLE}, [r12:64]
|
||||
|
||||
// Calculate second tweak, packing it together with the first
|
||||
vshr.u64 TMP0_L, TWEAKV_L, #63
|
||||
vtbl.u8 TMP0_L, {GF64MUL_TABLE}, TMP0_L
|
||||
vshl.u64 TWEAKV_H, TWEAKV_L, #1
|
||||
veor TWEAKV_H, TMP0_L
|
||||
.endif
|
||||
|
||||
.Lnext_128bytes_\@:
|
||||
|
||||
/*
|
||||
* Load the source blocks into {X,Y}[0-3], XOR them with their XTS tweak
|
||||
* values, and save the tweaks on the stack for later. Then
|
||||
* de-interleave the 'x' and 'y' elements of each block, i.e. make it so
|
||||
* that the X[0-3] registers contain only the second halves of blocks,
|
||||
* and the Y[0-3] registers contain only the first halves of blocks.
|
||||
* (Speck uses the order (y, x) rather than the more intuitive (x, y).)
|
||||
*/
|
||||
mov r12, sp
|
||||
.if \n == 64
|
||||
_xts128_precrypt_one X0, r12, TMP0
|
||||
_xts128_precrypt_one Y0, r12, TMP0
|
||||
_xts128_precrypt_one X1, r12, TMP0
|
||||
_xts128_precrypt_one Y1, r12, TMP0
|
||||
_xts128_precrypt_one X2, r12, TMP0
|
||||
_xts128_precrypt_one Y2, r12, TMP0
|
||||
_xts128_precrypt_one X3, r12, TMP0
|
||||
_xts128_precrypt_one Y3, r12, TMP0
|
||||
vswp X0_L, Y0_H
|
||||
vswp X1_L, Y1_H
|
||||
vswp X2_L, Y2_H
|
||||
vswp X3_L, Y3_H
|
||||
.else
|
||||
_xts64_precrypt_two X0, r12, TMP0
|
||||
_xts64_precrypt_two Y0, r12, TMP0
|
||||
_xts64_precrypt_two X1, r12, TMP0
|
||||
_xts64_precrypt_two Y1, r12, TMP0
|
||||
_xts64_precrypt_two X2, r12, TMP0
|
||||
_xts64_precrypt_two Y2, r12, TMP0
|
||||
_xts64_precrypt_two X3, r12, TMP0
|
||||
_xts64_precrypt_two Y3, r12, TMP0
|
||||
vuzp.32 Y0, X0
|
||||
vuzp.32 Y1, X1
|
||||
vuzp.32 Y2, X2
|
||||
vuzp.32 Y3, X3
|
||||
.endif
|
||||
|
||||
// Do the cipher rounds
|
||||
|
||||
mov r12, ROUND_KEYS
|
||||
mov r6, NROUNDS
|
||||
|
||||
.Lnext_round_\@:
|
||||
.if \decrypting
|
||||
.if \n == 64
|
||||
vld1.64 ROUND_KEY_L, [r12]
|
||||
sub r12, #8
|
||||
vmov ROUND_KEY_H, ROUND_KEY_L
|
||||
.else
|
||||
vld1.32 {ROUND_KEY_L[],ROUND_KEY_H[]}, [r12]
|
||||
sub r12, #4
|
||||
.endif
|
||||
_speck_unround_128bytes \n
|
||||
.else
|
||||
.if \n == 64
|
||||
vld1.64 ROUND_KEY_L, [r12]!
|
||||
vmov ROUND_KEY_H, ROUND_KEY_L
|
||||
.else
|
||||
vld1.32 {ROUND_KEY_L[],ROUND_KEY_H[]}, [r12]!
|
||||
.endif
|
||||
_speck_round_128bytes \n
|
||||
.endif
|
||||
subs r6, r6, #1
|
||||
bne .Lnext_round_\@
|
||||
|
||||
// Re-interleave the 'x' and 'y' elements of each block
|
||||
.if \n == 64
|
||||
vswp X0_L, Y0_H
|
||||
vswp X1_L, Y1_H
|
||||
vswp X2_L, Y2_H
|
||||
vswp X3_L, Y3_H
|
||||
.else
|
||||
vzip.32 Y0, X0
|
||||
vzip.32 Y1, X1
|
||||
vzip.32 Y2, X2
|
||||
vzip.32 Y3, X3
|
||||
.endif
|
||||
|
||||
// XOR the encrypted/decrypted blocks with the tweaks we saved earlier
|
||||
mov r12, sp
|
||||
vld1.8 {TMP0, TMP1}, [r12:128]!
|
||||
vld1.8 {TMP2, TMP3}, [r12:128]!
|
||||
veor X0, TMP0
|
||||
veor Y0, TMP1
|
||||
veor X1, TMP2
|
||||
veor Y1, TMP3
|
||||
vld1.8 {TMP0, TMP1}, [r12:128]!
|
||||
vld1.8 {TMP2, TMP3}, [r12:128]!
|
||||
veor X2, TMP0
|
||||
veor Y2, TMP1
|
||||
veor X3, TMP2
|
||||
veor Y3, TMP3
|
||||
|
||||
// Store the ciphertext in the destination buffer
|
||||
vst1.8 {X0, Y0}, [DST]!
|
||||
vst1.8 {X1, Y1}, [DST]!
|
||||
vst1.8 {X2, Y2}, [DST]!
|
||||
vst1.8 {X3, Y3}, [DST]!
|
||||
|
||||
// Continue if there are more 128-byte chunks remaining, else return
|
||||
subs NBYTES, #128
|
||||
bne .Lnext_128bytes_\@
|
||||
|
||||
// Store the next tweak
|
||||
.if \n == 64
|
||||
vst1.8 {TWEAKV}, [TWEAK]
|
||||
.else
|
||||
vst1.8 {TWEAKV_L}, [TWEAK]
|
||||
.endif
|
||||
|
||||
mov sp, r7
|
||||
pop {r4-r7}
|
||||
bx lr
|
||||
.endm
|
||||
|
||||
ENTRY(speck128_xts_encrypt_neon)
|
||||
_speck_xts_crypt n=64, decrypting=0
|
||||
ENDPROC(speck128_xts_encrypt_neon)
|
||||
|
||||
ENTRY(speck128_xts_decrypt_neon)
|
||||
_speck_xts_crypt n=64, decrypting=1
|
||||
ENDPROC(speck128_xts_decrypt_neon)
|
||||
|
||||
ENTRY(speck64_xts_encrypt_neon)
|
||||
_speck_xts_crypt n=32, decrypting=0
|
||||
ENDPROC(speck64_xts_encrypt_neon)
|
||||
|
||||
ENTRY(speck64_xts_decrypt_neon)
|
||||
_speck_xts_crypt n=32, decrypting=1
|
||||
ENDPROC(speck64_xts_decrypt_neon)
|
||||
314
arch/arm/crypto/speck-neon-glue.c
Normal file
314
arch/arm/crypto/speck-neon-glue.c
Normal file
@@ -0,0 +1,314 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* NEON-accelerated implementation of Speck128-XTS and Speck64-XTS
|
||||
*
|
||||
* Copyright (c) 2018 Google, Inc
|
||||
*
|
||||
* Note: the NIST recommendation for XTS only specifies a 128-bit block size,
|
||||
* but a 64-bit version (needed for Speck64) is fairly straightforward; the math
|
||||
* is just done in GF(2^64) instead of GF(2^128), with the reducing polynomial
|
||||
* x^64 + x^4 + x^3 + x + 1 from the original XEX paper (Rogaway, 2004:
|
||||
* "Efficient Instantiations of Tweakable Blockciphers and Refinements to Modes
|
||||
* OCB and PMAC"), represented as 0x1B.
|
||||
*/
|
||||
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/gf128mul.h>
|
||||
#include <crypto/speck.h>
|
||||
#include <crypto/xts.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/* The assembly functions only handle multiples of 128 bytes */
|
||||
#define SPECK_NEON_CHUNK_SIZE 128
|
||||
|
||||
/* Speck128 */
|
||||
|
||||
struct speck128_xts_tfm_ctx {
|
||||
struct speck128_tfm_ctx main_key;
|
||||
struct speck128_tfm_ctx tweak_key;
|
||||
};
|
||||
|
||||
asmlinkage void speck128_xts_encrypt_neon(const u64 *round_keys, int nrounds,
|
||||
void *dst, const void *src,
|
||||
unsigned int nbytes, void *tweak);
|
||||
|
||||
asmlinkage void speck128_xts_decrypt_neon(const u64 *round_keys, int nrounds,
|
||||
void *dst, const void *src,
|
||||
unsigned int nbytes, void *tweak);
|
||||
|
||||
typedef void (*speck128_crypt_one_t)(const struct speck128_tfm_ctx *,
|
||||
u8 *, const u8 *);
|
||||
typedef void (*speck128_xts_crypt_many_t)(const u64 *, int, void *,
|
||||
const void *, unsigned int, void *);
|
||||
|
||||
static __always_inline int
|
||||
__speck128_xts_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes,
|
||||
speck128_crypt_one_t crypt_one,
|
||||
speck128_xts_crypt_many_t crypt_many)
|
||||
{
|
||||
struct crypto_blkcipher *tfm = desc->tfm;
|
||||
const struct speck128_xts_tfm_ctx *ctx = crypto_blkcipher_ctx(tfm);
|
||||
struct blkcipher_walk walk;
|
||||
le128 tweak;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt_block(desc, &walk, SPECK_NEON_CHUNK_SIZE);
|
||||
|
||||
crypto_speck128_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv);
|
||||
|
||||
while (walk.nbytes > 0) {
|
||||
unsigned int nbytes = walk.nbytes;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
|
||||
if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) {
|
||||
unsigned int count;
|
||||
|
||||
count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE);
|
||||
kernel_neon_begin();
|
||||
(*crypt_many)(ctx->main_key.round_keys,
|
||||
ctx->main_key.nrounds,
|
||||
dst, src, count, &tweak);
|
||||
kernel_neon_end();
|
||||
dst += count;
|
||||
src += count;
|
||||
nbytes -= count;
|
||||
}
|
||||
|
||||
/* Handle any remainder with generic code */
|
||||
while (nbytes >= sizeof(tweak)) {
|
||||
le128_xor((le128 *)dst, (const le128 *)src, &tweak);
|
||||
(*crypt_one)(&ctx->main_key, dst, dst);
|
||||
le128_xor((le128 *)dst, (const le128 *)dst, &tweak);
|
||||
gf128mul_x_ble((be128 *)&tweak, (const be128 *)&tweak);
|
||||
|
||||
dst += sizeof(tweak);
|
||||
src += sizeof(tweak);
|
||||
nbytes -= sizeof(tweak);
|
||||
}
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int speck128_xts_encrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return __speck128_xts_crypt(desc, dst, src, nbytes,
|
||||
crypto_speck128_encrypt,
|
||||
speck128_xts_encrypt_neon);
|
||||
}
|
||||
|
||||
static int speck128_xts_decrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return __speck128_xts_crypt(desc, dst, src, nbytes,
|
||||
crypto_speck128_decrypt,
|
||||
speck128_xts_decrypt_neon);
|
||||
}
|
||||
|
||||
static int speck128_xts_setkey(struct crypto_tfm *tfm, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct speck128_xts_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
int err;
|
||||
|
||||
if (keylen % 2)
|
||||
return -EINVAL;
|
||||
|
||||
keylen /= 2;
|
||||
|
||||
err = crypto_speck128_setkey(&ctx->main_key, key, keylen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return crypto_speck128_setkey(&ctx->tweak_key, key + keylen, keylen);
|
||||
}
|
||||
|
||||
/* Speck64 */
|
||||
|
||||
struct speck64_xts_tfm_ctx {
|
||||
struct speck64_tfm_ctx main_key;
|
||||
struct speck64_tfm_ctx tweak_key;
|
||||
};
|
||||
|
||||
asmlinkage void speck64_xts_encrypt_neon(const u32 *round_keys, int nrounds,
|
||||
void *dst, const void *src,
|
||||
unsigned int nbytes, void *tweak);
|
||||
|
||||
asmlinkage void speck64_xts_decrypt_neon(const u32 *round_keys, int nrounds,
|
||||
void *dst, const void *src,
|
||||
unsigned int nbytes, void *tweak);
|
||||
|
||||
typedef void (*speck64_crypt_one_t)(const struct speck64_tfm_ctx *,
|
||||
u8 *, const u8 *);
|
||||
typedef void (*speck64_xts_crypt_many_t)(const u32 *, int, void *,
|
||||
const void *, unsigned int, void *);
|
||||
|
||||
static __always_inline int
|
||||
__speck64_xts_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes,
|
||||
speck64_crypt_one_t crypt_one,
|
||||
speck64_xts_crypt_many_t crypt_many)
|
||||
{
|
||||
struct crypto_blkcipher *tfm = desc->tfm;
|
||||
const struct speck64_xts_tfm_ctx *ctx = crypto_blkcipher_ctx(tfm);
|
||||
struct blkcipher_walk walk;
|
||||
__le64 tweak;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt_block(desc, &walk, SPECK_NEON_CHUNK_SIZE);
|
||||
|
||||
crypto_speck64_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv);
|
||||
|
||||
while (walk.nbytes > 0) {
|
||||
unsigned int nbytes = walk.nbytes;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
|
||||
if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) {
|
||||
unsigned int count;
|
||||
|
||||
count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE);
|
||||
kernel_neon_begin();
|
||||
(*crypt_many)(ctx->main_key.round_keys,
|
||||
ctx->main_key.nrounds,
|
||||
dst, src, count, &tweak);
|
||||
kernel_neon_end();
|
||||
dst += count;
|
||||
src += count;
|
||||
nbytes -= count;
|
||||
}
|
||||
|
||||
/* Handle any remainder with generic code */
|
||||
while (nbytes >= sizeof(tweak)) {
|
||||
*(__le64 *)dst = *(__le64 *)src ^ tweak;
|
||||
(*crypt_one)(&ctx->main_key, dst, dst);
|
||||
*(__le64 *)dst ^= tweak;
|
||||
tweak = cpu_to_le64((le64_to_cpu(tweak) << 1) ^
|
||||
((tweak & cpu_to_le64(1ULL << 63)) ?
|
||||
0x1B : 0));
|
||||
dst += sizeof(tweak);
|
||||
src += sizeof(tweak);
|
||||
nbytes -= sizeof(tweak);
|
||||
}
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int speck64_xts_encrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return __speck64_xts_crypt(desc, dst, src, nbytes,
|
||||
crypto_speck64_encrypt,
|
||||
speck64_xts_encrypt_neon);
|
||||
}
|
||||
|
||||
static int speck64_xts_decrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return __speck64_xts_crypt(desc, dst, src, nbytes,
|
||||
crypto_speck64_decrypt,
|
||||
speck64_xts_decrypt_neon);
|
||||
}
|
||||
|
||||
static int speck64_xts_setkey(struct crypto_tfm *tfm, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct speck64_xts_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
int err;
|
||||
|
||||
if (keylen % 2)
|
||||
return -EINVAL;
|
||||
|
||||
keylen /= 2;
|
||||
|
||||
err = crypto_speck64_setkey(&ctx->main_key, key, keylen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return crypto_speck64_setkey(&ctx->tweak_key, key + keylen, keylen);
|
||||
}
|
||||
|
||||
static struct crypto_alg speck_algs[] = {
|
||||
{
|
||||
.cra_name = "xts(speck128)",
|
||||
.cra_driver_name = "xts-speck128-neon",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = SPECK128_BLOCK_SIZE,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_ctxsize = sizeof(struct speck128_xts_tfm_ctx),
|
||||
.cra_alignmask = 7,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = 2 * SPECK128_128_KEY_SIZE,
|
||||
.max_keysize = 2 * SPECK128_256_KEY_SIZE,
|
||||
.ivsize = SPECK128_BLOCK_SIZE,
|
||||
.setkey = speck128_xts_setkey,
|
||||
.encrypt = speck128_xts_encrypt,
|
||||
.decrypt = speck128_xts_decrypt,
|
||||
}
|
||||
}
|
||||
}, {
|
||||
.cra_name = "xts(speck64)",
|
||||
.cra_driver_name = "xts-speck64-neon",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = SPECK64_BLOCK_SIZE,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_ctxsize = sizeof(struct speck64_xts_tfm_ctx),
|
||||
.cra_alignmask = 7,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = 2 * SPECK64_96_KEY_SIZE,
|
||||
.max_keysize = 2 * SPECK64_128_KEY_SIZE,
|
||||
.ivsize = SPECK64_BLOCK_SIZE,
|
||||
.setkey = speck64_xts_setkey,
|
||||
.encrypt = speck64_xts_encrypt,
|
||||
.decrypt = speck64_xts_decrypt,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int __init speck_neon_module_init(void)
|
||||
{
|
||||
if (!(elf_hwcap & HWCAP_NEON))
|
||||
return -ENODEV;
|
||||
return crypto_register_algs(speck_algs, ARRAY_SIZE(speck_algs));
|
||||
}
|
||||
|
||||
static void __exit speck_neon_module_exit(void)
|
||||
{
|
||||
crypto_unregister_algs(speck_algs, ARRAY_SIZE(speck_algs));
|
||||
}
|
||||
|
||||
module_init(speck_neon_module_init);
|
||||
module_exit(speck_neon_module_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Speck block cipher (NEON-accelerated)");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
|
||||
MODULE_ALIAS_CRYPTO("xts(speck128)");
|
||||
MODULE_ALIAS_CRYPTO("xts-speck128-neon");
|
||||
MODULE_ALIAS_CRYPTO("xts(speck64)");
|
||||
MODULE_ALIAS_CRYPTO("xts-speck64-neon");
|
||||
@@ -27,6 +27,8 @@ const struct cpumask *cpu_coregroup_mask(int cpu);
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
#define arch_scale_freq_capacity cpufreq_scale_freq_capacity
|
||||
#define arch_scale_max_freq_capacity cpufreq_scale_max_freq_capacity
|
||||
#define arch_scale_min_freq_capacity cpufreq_scale_min_freq_capacity
|
||||
#endif
|
||||
#define arch_scale_cpu_capacity scale_cpu_capacity
|
||||
extern unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu);
|
||||
|
||||
@@ -29,11 +29,6 @@
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
#ifdef CONFIG_OLD_MCOUNT
|
||||
#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
|
||||
#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
|
||||
|
||||
#define OLD_NOP 0xe1a00000 /* mov r0, r0 */
|
||||
|
||||
static int __ftrace_modify_code(void *data)
|
||||
{
|
||||
@@ -51,6 +46,12 @@ void arch_ftrace_update_code(int command)
|
||||
stop_machine(__ftrace_modify_code, &command, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OLD_MCOUNT
|
||||
#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
|
||||
#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
|
||||
|
||||
#define OLD_NOP 0xe1a00000 /* mov r0, r0 */
|
||||
|
||||
static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
|
||||
{
|
||||
return rec->arch.old_mcount ? OLD_NOP : NOP;
|
||||
|
||||
@@ -129,13 +129,13 @@ static void show_data(unsigned long addr, int nbytes, const char *name)
|
||||
for (j = 0; j < 8; j++) {
|
||||
u32 data;
|
||||
if (probe_kernel_address(p, data)) {
|
||||
printk(" ********");
|
||||
pr_cont(" ********");
|
||||
} else {
|
||||
printk(" %08x", data);
|
||||
pr_cont(" %08x", data);
|
||||
}
|
||||
++p;
|
||||
}
|
||||
printk("\n");
|
||||
pr_cont("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,13 +44,7 @@ static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
|
||||
|
||||
unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu)
|
||||
{
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
unsigned long max_freq_scale = cpufreq_scale_max_freq_capacity(cpu);
|
||||
|
||||
return per_cpu(cpu_scale, cpu) * max_freq_scale >> SCHED_CAPACITY_SHIFT;
|
||||
#else
|
||||
return per_cpu(cpu_scale, cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
|
||||
|
||||
@@ -1165,6 +1165,7 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
|
||||
cpu_hyp_reset();
|
||||
|
||||
return NOTIFY_OK;
|
||||
case CPU_PM_ENTER_FAILED:
|
||||
case CPU_PM_EXIT:
|
||||
if (__this_cpu_read(kvm_arm_hardware_enabled))
|
||||
/* The hardware was enabled before suspend. */
|
||||
|
||||
@@ -38,7 +38,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
|
||||
ret = kvm_psci_call(vcpu);
|
||||
if (ret < 0) {
|
||||
kvm_inject_undefined(vcpu);
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,16 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
|
||||
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
{
|
||||
kvm_inject_undefined(vcpu);
|
||||
/*
|
||||
* "If an SMC instruction executed at Non-secure EL1 is
|
||||
* trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
|
||||
* Trap exception, not a Secure Monitor Call exception [...]"
|
||||
*
|
||||
* We need to advance the PC after the trap, as it would
|
||||
* otherwise return to the same address...
|
||||
*/
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING
|
||||
|
||||
KVM=../../../../virt/kvm
|
||||
|
||||
CFLAGS_ARMV7VE :=$(call cc-option, -march=armv7ve)
|
||||
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v3-sr.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o
|
||||
@@ -14,7 +16,10 @@ obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += vfp.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += banked-sr.o
|
||||
CFLAGS_banked-sr.o += $(CFLAGS_ARMV7VE)
|
||||
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += entry.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += switch.o
|
||||
CFLAGS_switch.o += $(CFLAGS_ARMV7VE)
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
#include <asm/kvm_hyp.h>
|
||||
|
||||
/*
|
||||
* gcc before 4.9 doesn't understand -march=armv7ve, so we have to
|
||||
* trick the assembler.
|
||||
*/
|
||||
__asm__(".arch_extension virt");
|
||||
|
||||
void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt)
|
||||
|
||||
@@ -112,7 +112,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
}
|
||||
|
||||
trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
|
||||
data);
|
||||
&data);
|
||||
data = vcpu_data_host_to_guest(vcpu, data, len);
|
||||
vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data);
|
||||
}
|
||||
@@ -182,14 +182,14 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt),
|
||||
len);
|
||||
|
||||
trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
|
||||
trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, &data);
|
||||
kvm_mmio_write_buf(data_buf, len, data);
|
||||
|
||||
ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
|
||||
data_buf);
|
||||
} else {
|
||||
trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len,
|
||||
fault_ipa, 0);
|
||||
fault_ipa, NULL);
|
||||
|
||||
ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len,
|
||||
data_buf);
|
||||
|
||||
@@ -1284,7 +1284,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (is_vm_hugetlb_page(vma) && !logging_active) {
|
||||
if (vma_kernel_pagesize(vma) == PMD_SIZE && !logging_active) {
|
||||
hugetlb = true;
|
||||
gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT;
|
||||
} else {
|
||||
|
||||
@@ -85,7 +85,11 @@
|
||||
.pushsection .text.fixup,"ax"
|
||||
.align 4
|
||||
9001: mov r4, #-EFAULT
|
||||
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
|
||||
ldr r5, [sp, #9*4] @ *err_ptr
|
||||
#else
|
||||
ldr r5, [sp, #8*4] @ *err_ptr
|
||||
#endif
|
||||
str r4, [r5]
|
||||
ldmia sp, {r1, r2} @ retrieve dst, len
|
||||
add r2, r2, r1
|
||||
|
||||
@@ -199,6 +199,7 @@ config ARCH_BRCMSTB
|
||||
select BRCMSTB_L2_IRQ
|
||||
select BCM7120_L2_IRQ
|
||||
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
|
||||
select ZONE_DMA if ARM_LPAE
|
||||
select SOC_BRCMSTB
|
||||
select SOC_BUS
|
||||
help
|
||||
|
||||
@@ -42,7 +42,7 @@ config MACH_ARMADA_375
|
||||
depends on ARCH_MULTI_V7
|
||||
select ARMADA_370_XP_IRQ
|
||||
select ARM_ERRATA_720789
|
||||
select ARM_ERRATA_753970
|
||||
select PL310_ERRATA_753970
|
||||
select ARM_GIC
|
||||
select ARMADA_375_CLK
|
||||
select HAVE_ARM_SCU
|
||||
@@ -58,7 +58,7 @@ config MACH_ARMADA_38X
|
||||
bool "Marvell Armada 380/385 boards"
|
||||
depends on ARCH_MULTI_V7
|
||||
select ARM_ERRATA_720789
|
||||
select ARM_ERRATA_753970
|
||||
select PL310_ERRATA_753970
|
||||
select ARM_GIC
|
||||
select ARMADA_370_XP_IRQ
|
||||
select ARMADA_38X_CLK
|
||||
|
||||
@@ -524,7 +524,7 @@ static struct clockdomain pcie_7xx_clkdm = {
|
||||
.dep_bit = DRA7XX_PCIE_STATDEP_SHIFT,
|
||||
.wkdep_srcs = pcie_wkup_sleep_deps,
|
||||
.sleepdep_srcs = pcie_wkup_sleep_deps,
|
||||
.flags = CLKDM_CAN_HWSUP_SWSUP,
|
||||
.flags = CLKDM_CAN_SWSUP,
|
||||
};
|
||||
|
||||
static struct clockdomain atl_7xx_clkdm = {
|
||||
|
||||
@@ -73,6 +73,27 @@ phys_addr_t omap_secure_ram_mempool_base(void)
|
||||
return omap_secure_memblock_base;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
|
||||
u32 omap3_save_secure_ram(void __iomem *addr, int size)
|
||||
{
|
||||
u32 ret;
|
||||
u32 param[5];
|
||||
|
||||
if (size != OMAP3_SAVE_SECURE_RAM_SZ)
|
||||
return OMAP3_SAVE_SECURE_RAM_SZ;
|
||||
|
||||
param[0] = 4; /* Number of arguments */
|
||||
param[1] = __pa(addr); /* Physical address for saving */
|
||||
param[2] = 0;
|
||||
param[3] = 1;
|
||||
param[4] = 1;
|
||||
|
||||
ret = save_secure_ram_context(__pa(param));
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* rx51_secure_dispatcher: Routine to dispatch secure PPA API calls
|
||||
* @idx: The PPA API index
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
/* Maximum Secure memory storage size */
|
||||
#define OMAP_SECURE_RAM_STORAGE (88 * SZ_1K)
|
||||
|
||||
#define OMAP3_SAVE_SECURE_RAM_SZ 0x803F
|
||||
|
||||
/* Secure low power HAL API index */
|
||||
#define OMAP4_HAL_SAVESECURERAM_INDEX 0x1a
|
||||
#define OMAP4_HAL_SAVEHW_INDEX 0x1b
|
||||
@@ -65,6 +67,8 @@ extern u32 omap_smc2(u32 id, u32 falg, u32 pargs);
|
||||
extern u32 omap_smc3(u32 id, u32 process, u32 flag, u32 pargs);
|
||||
extern phys_addr_t omap_secure_ram_mempool_base(void);
|
||||
extern int omap_secure_ram_reserve_memblock(void);
|
||||
extern u32 save_secure_ram_context(u32 args_pa);
|
||||
extern u32 omap3_save_secure_ram(void __iomem *save_regs, int size);
|
||||
|
||||
extern u32 rx51_secure_dispatcher(u32 idx, u32 process, u32 flag, u32 nargs,
|
||||
u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
|
||||
@@ -81,10 +81,6 @@ extern unsigned int omap3_do_wfi_sz;
|
||||
/* ... and its pointer from SRAM after copy */
|
||||
extern void (*omap3_do_wfi_sram)(void);
|
||||
|
||||
/* save_secure_ram_context function pointer and size, for copy to SRAM */
|
||||
extern int save_secure_ram_context(u32 *addr);
|
||||
extern unsigned int save_secure_ram_context_sz;
|
||||
|
||||
extern void omap3_save_scratchpad_contents(void);
|
||||
|
||||
#define PM_RTA_ERRATUM_i608 (1 << 0)
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "prm3xxx.h"
|
||||
#include "pm.h"
|
||||
#include "sdrc.h"
|
||||
#include "omap-secure.h"
|
||||
#include "sram.h"
|
||||
#include "control.h"
|
||||
#include "vc.h"
|
||||
@@ -66,7 +67,6 @@ struct power_state {
|
||||
|
||||
static LIST_HEAD(pwrst_list);
|
||||
|
||||
static int (*_omap_save_secure_sram)(u32 *addr);
|
||||
void (*omap3_do_wfi_sram)(void);
|
||||
|
||||
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
|
||||
@@ -121,8 +121,8 @@ static void omap3_save_secure_ram_context(void)
|
||||
* will hang the system.
|
||||
*/
|
||||
pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
|
||||
ret = _omap_save_secure_sram((u32 *)(unsigned long)
|
||||
__pa(omap3_secure_ram_storage));
|
||||
ret = omap3_save_secure_ram(omap3_secure_ram_storage,
|
||||
OMAP3_SAVE_SECURE_RAM_SZ);
|
||||
pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
|
||||
/* Following is for error tracking, it should not happen */
|
||||
if (ret) {
|
||||
@@ -434,15 +434,10 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
|
||||
*
|
||||
* The minimum set of functions is pushed to SRAM for execution:
|
||||
* - omap3_do_wfi for erratum i581 WA,
|
||||
* - save_secure_ram_context for security extensions.
|
||||
*/
|
||||
void omap_push_sram_idle(void)
|
||||
{
|
||||
omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
|
||||
|
||||
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
|
||||
_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
|
||||
save_secure_ram_context_sz);
|
||||
}
|
||||
|
||||
static void __init pm_errata_configure(void)
|
||||
@@ -554,7 +549,7 @@ int __init omap3_pm_init(void)
|
||||
clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
|
||||
if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
|
||||
omap3_secure_ram_storage =
|
||||
kmalloc(0x803F, GFP_KERNEL);
|
||||
kmalloc(OMAP3_SAVE_SECURE_RAM_SZ, GFP_KERNEL);
|
||||
if (!omap3_secure_ram_storage)
|
||||
pr_err("Memory allocation failed when allocating for secure sram context\n");
|
||||
|
||||
|
||||
@@ -176,17 +176,6 @@ static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
||||
return v;
|
||||
}
|
||||
|
||||
static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
||||
v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
|
||||
v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
|
||||
{
|
||||
am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
|
||||
@@ -357,7 +346,6 @@ struct pwrdm_ops am33xx_pwrdm_operations = {
|
||||
.pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
|
||||
.pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
|
||||
.pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
|
||||
.pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
|
||||
.pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
|
||||
.pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
|
||||
.pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
|
||||
|
||||
@@ -93,20 +93,13 @@ ENTRY(enable_omap3630_toggle_l2_on_restore)
|
||||
ENDPROC(enable_omap3630_toggle_l2_on_restore)
|
||||
|
||||
/*
|
||||
* Function to call rom code to save secure ram context. This gets
|
||||
* relocated to SRAM, so it can be all in .data section. Otherwise
|
||||
* we need to initialize api_params separately.
|
||||
* Function to call rom code to save secure ram context.
|
||||
*
|
||||
* r0 = physical address of the parameters
|
||||
*/
|
||||
.data
|
||||
.align 3
|
||||
ENTRY(save_secure_ram_context)
|
||||
stmfd sp!, {r4 - r11, lr} @ save registers on stack
|
||||
adr r3, api_params @ r3 points to parameters
|
||||
str r0, [r3,#0x4] @ r0 has sdram address
|
||||
ldr r12, high_mask
|
||||
and r3, r3, r12
|
||||
ldr r12, sram_phy_addr_mask
|
||||
orr r3, r3, r12
|
||||
mov r3, r0 @ physical address of parameters
|
||||
mov r0, #25 @ set service ID for PPA
|
||||
mov r12, r0 @ copy secure service ID in r12
|
||||
mov r1, #0 @ set task id for ROM code in r1
|
||||
@@ -120,18 +113,7 @@ ENTRY(save_secure_ram_context)
|
||||
nop
|
||||
nop
|
||||
ldmfd sp!, {r4 - r11, pc}
|
||||
.align
|
||||
sram_phy_addr_mask:
|
||||
.word SRAM_BASE_P
|
||||
high_mask:
|
||||
.word 0xffff
|
||||
api_params:
|
||||
.word 0x4, 0x0, 0x0, 0x1, 0x1
|
||||
ENDPROC(save_secure_ram_context)
|
||||
ENTRY(save_secure_ram_context_sz)
|
||||
.word . - save_secure_ram_context
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* ======================
|
||||
|
||||
@@ -132,3 +132,7 @@ static struct platform_driver tosa_bt_driver = {
|
||||
},
|
||||
};
|
||||
module_platform_driver(tosa_bt_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Dmitry Baryshkov");
|
||||
MODULE_DESCRIPTION("Bluetooth built-in chip control");
|
||||
|
||||
@@ -648,7 +648,7 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp,
|
||||
*/
|
||||
static int vfp_dying_cpu(unsigned int cpu)
|
||||
{
|
||||
vfp_force_reload(cpu, current_thread_info());
|
||||
vfp_current_hw_state[cpu] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ config ARM64
|
||||
select ARCH_HAS_SG_CHAIN
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_USE_CMPXCHG_LOCKREF
|
||||
select ARCH_SUPPORTS_LTO_CLANG
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
|
||||
@@ -417,7 +418,7 @@ config ARM64_ERRATUM_845719
|
||||
|
||||
config ARM64_ERRATUM_843419
|
||||
bool "Cortex-A53: 843419: A load or store might access an incorrect address"
|
||||
default y
|
||||
default y if !LTO_CLANG
|
||||
select ARM64_MODULE_CMODEL_LARGE if MODULES
|
||||
help
|
||||
This option links the kernel with '--fix-cortex-a53-843419' and
|
||||
@@ -945,7 +946,7 @@ config RANDOMIZE_BASE
|
||||
|
||||
config RANDOMIZE_MODULE_REGION_FULL
|
||||
bool "Randomize the module region independently from the core kernel"
|
||||
depends on RANDOMIZE_BASE && !DYNAMIC_FTRACE
|
||||
depends on RANDOMIZE_BASE && !DYNAMIC_FTRACE && !LTO_CLANG
|
||||
default y
|
||||
help
|
||||
Randomizes the location of the module region without considering the
|
||||
@@ -1080,7 +1081,7 @@ source "fs/Kconfig.binfmt"
|
||||
config COMPAT
|
||||
bool "Kernel support for 32-bit EL0"
|
||||
depends on ARM64_4K_PAGES || EXPERT
|
||||
select COMPAT_BINFMT_ELF
|
||||
select COMPAT_BINFMT_ELF if BINFMT_ELF
|
||||
select HAVE_UID16
|
||||
select OLD_SIGSUSPEND3
|
||||
select COMPAT_OLD_SIGACTION
|
||||
|
||||
@@ -2,9 +2,11 @@ menu "Platform selection"
|
||||
|
||||
config ARCH_SUNXI
|
||||
bool "Allwinner sunxi 64-bit SoC Family"
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select GENERIC_IRQ_CHIP
|
||||
select PINCTRL
|
||||
select PINCTRL_SUN50I_A64
|
||||
select RESET_CONTROLLER
|
||||
help
|
||||
This enables support for Allwinner sunxi based SoCs like the A64.
|
||||
|
||||
|
||||
@@ -26,8 +26,17 @@ ifeq ($(CONFIG_ARM64_ERRATUM_843419),y)
|
||||
ifeq ($(call ld-option, --fix-cortex-a53-843419),)
|
||||
$(warning ld does not support --fix-cortex-a53-843419; kernel may be susceptible to erratum)
|
||||
else
|
||||
ifeq ($(call gold-ifversion, -lt, 114000000, y), y)
|
||||
$(warning This version of GNU gold may generate incorrect code with --fix-cortex-a53-843419;\
|
||||
see https://sourceware.org/bugzilla/show_bug.cgi?id=21491)
|
||||
endif
|
||||
LDFLAGS_vmlinux += --fix-cortex-a53-843419
|
||||
endif
|
||||
else
|
||||
ifeq ($(ld-name),gold)
|
||||
# Pass --no-fix-cortex-a53-843419 to ensure the erratum fix is disabled
|
||||
LDFLAGS += --no-fix-cortex-a53-843419
|
||||
endif
|
||||
endif
|
||||
|
||||
KBUILD_DEFCONFIG := defconfig
|
||||
@@ -70,6 +79,10 @@ CHECKFLAGS += -D__aarch64__
|
||||
|
||||
ifeq ($(CONFIG_ARM64_MODULE_CMODEL_LARGE), y)
|
||||
KBUILD_CFLAGS_MODULE += -mcmodel=large
|
||||
ifeq ($(CONFIG_LTO_CLANG), y)
|
||||
# Code model is not stored in LLVM IR, so we need to pass it also to LLVMgold
|
||||
LDFLAGS += -plugin-opt=-code-model=large
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARM64_MODULE_PLTS),y)
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
reg = <0x000>;
|
||||
enable-method = "psci";
|
||||
cpu-idle-states = <&CPU_SLEEP_0>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
@@ -89,6 +90,7 @@
|
||||
reg = <0x100>;
|
||||
enable-method = "psci";
|
||||
cpu-idle-states = <&CPU_SLEEP_0>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
cpu3: cpu@101 {
|
||||
|
||||
@@ -796,6 +796,7 @@
|
||||
"dsi_phy_regulator";
|
||||
|
||||
#clock-cells = <1>;
|
||||
#phy-cells = <0>;
|
||||
|
||||
clocks = <&gcc GCC_MDSS_AHB_CLK>;
|
||||
clock-names = "iface_clk";
|
||||
@@ -906,8 +907,8 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
qcom,ipc-1 = <&apcs 0 13>;
|
||||
qcom,ipc-6 = <&apcs 0 19>;
|
||||
qcom,ipc-1 = <&apcs 8 13>;
|
||||
qcom,ipc-3 = <&apcs 8 19>;
|
||||
|
||||
apps_smsm: apps@0 {
|
||||
reg = <0>;
|
||||
|
||||
@@ -36,9 +36,8 @@
|
||||
enable-method = "psci";
|
||||
};
|
||||
|
||||
L2_CA57: cache-controller@0 {
|
||||
L2_CA57: cache-controller-0 {
|
||||
compatible = "cache";
|
||||
reg = <0>;
|
||||
power-domains = <&sysc R8A7796_PD_CA57_SCU>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
|
||||
@@ -53,4 +53,11 @@ config CRYPTO_CRC32_ARM64
|
||||
tristate "CRC32 and CRC32C using optional ARMv8 instructions"
|
||||
depends on ARM64
|
||||
select CRYPTO_HASH
|
||||
|
||||
config CRYPTO_SPECK_NEON
|
||||
tristate "NEON accelerated Speck cipher algorithms"
|
||||
depends on KERNEL_MODE_NEON
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_GF128MUL
|
||||
select CRYPTO_SPECK
|
||||
endif
|
||||
|
||||
@@ -18,7 +18,8 @@ obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o
|
||||
ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o
|
||||
CFLAGS_aes-ce-cipher.o += -march=armv8-a+crypto
|
||||
aes-ce-cipher-y := aes-ce-cipher-glue.o aes-ce-cipher-core.o
|
||||
CFLAGS_aes-ce-cipher-core.o += -march=armv8-a+crypto -Wa,-march=armv8-a+crypto $(DISABLE_LTO)
|
||||
|
||||
obj-$(CONFIG_CRYPTO_AES_ARM64_CE_CCM) += aes-ce-ccm.o
|
||||
aes-ce-ccm-y := aes-ce-ccm-glue.o aes-ce-ccm-core.o
|
||||
@@ -29,6 +30,9 @@ aes-ce-blk-y := aes-glue-ce.o aes-ce.o
|
||||
obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o
|
||||
aes-neon-blk-y := aes-glue-neon.o aes-neon.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SPECK_NEON) += speck-neon.o
|
||||
speck-neon-y := speck-neon-core.o speck-neon-glue.o
|
||||
|
||||
AFLAGS_aes-ce.o := -DINTERLEAVE=4
|
||||
AFLAGS_aes-neon.o := -DINTERLEAVE=4
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* aes-ce-cipher.c - core AES cipher using ARMv8 Crypto Extensions
|
||||
* aes-ce-cipher-core.c - core AES cipher using ARMv8 Crypto Extensions
|
||||
*
|
||||
* Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
|
||||
*
|
||||
@@ -10,16 +10,10 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "aes-ce-setkey.h"
|
||||
|
||||
MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
|
||||
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
struct aes_block {
|
||||
u8 b[AES_BLOCK_SIZE];
|
||||
};
|
||||
@@ -36,7 +30,7 @@ static int num_rounds(struct crypto_aes_ctx *ctx)
|
||||
return 6 + ctx->key_length / 4;
|
||||
}
|
||||
|
||||
static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
|
||||
void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
|
||||
{
|
||||
struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct aes_block *out = (struct aes_block *)dst;
|
||||
@@ -81,7 +75,7 @@ static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
|
||||
kernel_neon_end();
|
||||
}
|
||||
|
||||
static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
|
||||
void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
|
||||
{
|
||||
struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct aes_block *out = (struct aes_block *)dst;
|
||||
@@ -223,48 +217,3 @@ int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ce_aes_expandkey);
|
||||
|
||||
int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
int ret;
|
||||
|
||||
ret = ce_aes_expandkey(ctx, in_key, key_len);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(ce_aes_setkey);
|
||||
|
||||
static struct crypto_alg aes_alg = {
|
||||
.cra_name = "aes",
|
||||
.cra_driver_name = "aes-ce",
|
||||
.cra_priority = 250,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct crypto_aes_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_cipher = {
|
||||
.cia_min_keysize = AES_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = AES_MAX_KEY_SIZE,
|
||||
.cia_setkey = ce_aes_setkey,
|
||||
.cia_encrypt = aes_cipher_encrypt,
|
||||
.cia_decrypt = aes_cipher_decrypt
|
||||
}
|
||||
};
|
||||
|
||||
static int __init aes_mod_init(void)
|
||||
{
|
||||
return crypto_register_alg(&aes_alg);
|
||||
}
|
||||
|
||||
static void __exit aes_mod_exit(void)
|
||||
{
|
||||
crypto_unregister_alg(&aes_alg);
|
||||
}
|
||||
|
||||
module_cpu_feature_match(AES, aes_mod_init);
|
||||
module_exit(aes_mod_exit);
|
||||
83
arch/arm64/crypto/aes-ce-cipher-glue.c
Normal file
83
arch/arm64/crypto/aes-ce-cipher-glue.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* aes-ce-cipher.c - core AES cipher using ARMv8 Crypto Extensions
|
||||
*
|
||||
* Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <crypto/aes.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "aes-ce-setkey.h"
|
||||
|
||||
MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
|
||||
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
extern void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]);
|
||||
extern void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]);
|
||||
|
||||
#ifdef CONFIG_CFI_CLANG
|
||||
static inline void __cfi_aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
|
||||
{
|
||||
aes_cipher_encrypt(tfm, dst, src);
|
||||
}
|
||||
|
||||
static inline void __cfi_aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
|
||||
{
|
||||
aes_cipher_decrypt(tfm, dst, src);
|
||||
}
|
||||
|
||||
#define aes_cipher_encrypt __cfi_aes_cipher_encrypt
|
||||
#define aes_cipher_decrypt __cfi_aes_cipher_decrypt
|
||||
#endif
|
||||
|
||||
int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
int ret;
|
||||
|
||||
ret = ce_aes_expandkey(ctx, in_key, key_len);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(ce_aes_setkey);
|
||||
|
||||
static struct crypto_alg aes_alg = {
|
||||
.cra_name = "aes",
|
||||
.cra_driver_name = "aes-ce",
|
||||
.cra_priority = 250,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct crypto_aes_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_cipher = {
|
||||
.cia_min_keysize = AES_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = AES_MAX_KEY_SIZE,
|
||||
.cia_setkey = ce_aes_setkey,
|
||||
.cia_encrypt = aes_cipher_encrypt,
|
||||
.cia_decrypt = aes_cipher_decrypt
|
||||
}
|
||||
};
|
||||
|
||||
static int __init aes_mod_init(void)
|
||||
{
|
||||
return crypto_register_alg(&aes_alg);
|
||||
}
|
||||
|
||||
static void __exit aes_mod_exit(void)
|
||||
{
|
||||
crypto_unregister_alg(&aes_alg);
|
||||
}
|
||||
|
||||
module_cpu_feature_match(AES, aes_mod_init);
|
||||
module_exit(aes_mod_exit);
|
||||
@@ -232,6 +232,7 @@ static struct shash_alg crc32_alg = {
|
||||
.cra_name = "crc32",
|
||||
.cra_driver_name = "crc32-arm64-hw",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
|
||||
.cra_blocksize = CHKSUM_BLOCK_SIZE,
|
||||
.cra_alignmask = 0,
|
||||
.cra_ctxsize = sizeof(struct chksum_ctx),
|
||||
@@ -253,6 +254,7 @@ static struct shash_alg crc32c_alg = {
|
||||
.cra_name = "crc32c",
|
||||
.cra_driver_name = "crc32c-arm64-hw",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
|
||||
.cra_blocksize = CHKSUM_BLOCK_SIZE,
|
||||
.cra_alignmask = 0,
|
||||
.cra_ctxsize = sizeof(struct chksum_ctx),
|
||||
|
||||
@@ -28,6 +28,14 @@ struct sha1_ce_state {
|
||||
|
||||
asmlinkage void sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src,
|
||||
int blocks);
|
||||
#ifdef CONFIG_CFI_CLANG
|
||||
static inline void __cfi_sha1_ce_transform(struct sha1_state *sst,
|
||||
u8 const *src, int blocks)
|
||||
{
|
||||
sha1_ce_transform((struct sha1_ce_state *)sst, src, blocks);
|
||||
}
|
||||
#define sha1_ce_transform __cfi_sha1_ce_transform
|
||||
#endif
|
||||
|
||||
const u32 sha1_ce_offsetof_count = offsetof(struct sha1_ce_state, sst.count);
|
||||
const u32 sha1_ce_offsetof_finalize = offsetof(struct sha1_ce_state, finalize);
|
||||
|
||||
@@ -28,6 +28,14 @@ struct sha256_ce_state {
|
||||
|
||||
asmlinkage void sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src,
|
||||
int blocks);
|
||||
#ifdef CONFIG_CFI_CLANG
|
||||
static inline void __cfi_sha2_ce_transform(struct sha256_state *sst,
|
||||
u8 const *src, int blocks)
|
||||
{
|
||||
sha2_ce_transform((struct sha256_ce_state *)sst, src, blocks);
|
||||
}
|
||||
#define sha2_ce_transform __cfi_sha2_ce_transform
|
||||
#endif
|
||||
|
||||
const u32 sha256_ce_offsetof_count = offsetof(struct sha256_ce_state,
|
||||
sst.count);
|
||||
|
||||
352
arch/arm64/crypto/speck-neon-core.S
Normal file
352
arch/arm64/crypto/speck-neon-core.S
Normal file
@@ -0,0 +1,352 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ARM64 NEON-accelerated implementation of Speck128-XTS and Speck64-XTS
|
||||
*
|
||||
* Copyright (c) 2018 Google, Inc
|
||||
*
|
||||
* Author: Eric Biggers <ebiggers@google.com>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.text
|
||||
|
||||
// arguments
|
||||
ROUND_KEYS .req x0 // const {u64,u32} *round_keys
|
||||
NROUNDS .req w1 // int nrounds
|
||||
NROUNDS_X .req x1
|
||||
DST .req x2 // void *dst
|
||||
SRC .req x3 // const void *src
|
||||
NBYTES .req w4 // unsigned int nbytes
|
||||
TWEAK .req x5 // void *tweak
|
||||
|
||||
// registers which hold the data being encrypted/decrypted
|
||||
// (underscores avoid a naming collision with ARM64 registers x0-x3)
|
||||
X_0 .req v0
|
||||
Y_0 .req v1
|
||||
X_1 .req v2
|
||||
Y_1 .req v3
|
||||
X_2 .req v4
|
||||
Y_2 .req v5
|
||||
X_3 .req v6
|
||||
Y_3 .req v7
|
||||
|
||||
// the round key, duplicated in all lanes
|
||||
ROUND_KEY .req v8
|
||||
|
||||
// index vector for tbl-based 8-bit rotates
|
||||
ROTATE_TABLE .req v9
|
||||
ROTATE_TABLE_Q .req q9
|
||||
|
||||
// temporary registers
|
||||
TMP0 .req v10
|
||||
TMP1 .req v11
|
||||
TMP2 .req v12
|
||||
TMP3 .req v13
|
||||
|
||||
// multiplication table for updating XTS tweaks
|
||||
GFMUL_TABLE .req v14
|
||||
GFMUL_TABLE_Q .req q14
|
||||
|
||||
// next XTS tweak value(s)
|
||||
TWEAKV_NEXT .req v15
|
||||
|
||||
// XTS tweaks for the blocks currently being encrypted/decrypted
|
||||
TWEAKV0 .req v16
|
||||
TWEAKV1 .req v17
|
||||
TWEAKV2 .req v18
|
||||
TWEAKV3 .req v19
|
||||
TWEAKV4 .req v20
|
||||
TWEAKV5 .req v21
|
||||
TWEAKV6 .req v22
|
||||
TWEAKV7 .req v23
|
||||
|
||||
.align 4
|
||||
.Lror64_8_table:
|
||||
.octa 0x080f0e0d0c0b0a090007060504030201
|
||||
.Lror32_8_table:
|
||||
.octa 0x0c0f0e0d080b0a090407060500030201
|
||||
.Lrol64_8_table:
|
||||
.octa 0x0e0d0c0b0a09080f0605040302010007
|
||||
.Lrol32_8_table:
|
||||
.octa 0x0e0d0c0f0a09080b0605040702010003
|
||||
.Lgf128mul_table:
|
||||
.octa 0x00000000000000870000000000000001
|
||||
.Lgf64mul_table:
|
||||
.octa 0x0000000000000000000000002d361b00
|
||||
|
||||
/*
|
||||
* _speck_round_128bytes() - Speck encryption round on 128 bytes at a time
|
||||
*
|
||||
* Do one Speck encryption round on the 128 bytes (8 blocks for Speck128, 16 for
|
||||
* Speck64) stored in X0-X3 and Y0-Y3, using the round key stored in all lanes
|
||||
* of ROUND_KEY. 'n' is the lane size: 64 for Speck128, or 32 for Speck64.
|
||||
* 'lanes' is the lane specifier: "2d" for Speck128 or "4s" for Speck64.
|
||||
*/
|
||||
.macro _speck_round_128bytes n, lanes
|
||||
|
||||
// x = ror(x, 8)
|
||||
tbl X_0.16b, {X_0.16b}, ROTATE_TABLE.16b
|
||||
tbl X_1.16b, {X_1.16b}, ROTATE_TABLE.16b
|
||||
tbl X_2.16b, {X_2.16b}, ROTATE_TABLE.16b
|
||||
tbl X_3.16b, {X_3.16b}, ROTATE_TABLE.16b
|
||||
|
||||
// x += y
|
||||
add X_0.\lanes, X_0.\lanes, Y_0.\lanes
|
||||
add X_1.\lanes, X_1.\lanes, Y_1.\lanes
|
||||
add X_2.\lanes, X_2.\lanes, Y_2.\lanes
|
||||
add X_3.\lanes, X_3.\lanes, Y_3.\lanes
|
||||
|
||||
// x ^= k
|
||||
eor X_0.16b, X_0.16b, ROUND_KEY.16b
|
||||
eor X_1.16b, X_1.16b, ROUND_KEY.16b
|
||||
eor X_2.16b, X_2.16b, ROUND_KEY.16b
|
||||
eor X_3.16b, X_3.16b, ROUND_KEY.16b
|
||||
|
||||
// y = rol(y, 3)
|
||||
shl TMP0.\lanes, Y_0.\lanes, #3
|
||||
shl TMP1.\lanes, Y_1.\lanes, #3
|
||||
shl TMP2.\lanes, Y_2.\lanes, #3
|
||||
shl TMP3.\lanes, Y_3.\lanes, #3
|
||||
sri TMP0.\lanes, Y_0.\lanes, #(\n - 3)
|
||||
sri TMP1.\lanes, Y_1.\lanes, #(\n - 3)
|
||||
sri TMP2.\lanes, Y_2.\lanes, #(\n - 3)
|
||||
sri TMP3.\lanes, Y_3.\lanes, #(\n - 3)
|
||||
|
||||
// y ^= x
|
||||
eor Y_0.16b, TMP0.16b, X_0.16b
|
||||
eor Y_1.16b, TMP1.16b, X_1.16b
|
||||
eor Y_2.16b, TMP2.16b, X_2.16b
|
||||
eor Y_3.16b, TMP3.16b, X_3.16b
|
||||
.endm
|
||||
|
||||
/*
|
||||
* _speck_unround_128bytes() - Speck decryption round on 128 bytes at a time
|
||||
*
|
||||
* This is the inverse of _speck_round_128bytes().
|
||||
*/
|
||||
.macro _speck_unround_128bytes n, lanes
|
||||
|
||||
// y ^= x
|
||||
eor TMP0.16b, Y_0.16b, X_0.16b
|
||||
eor TMP1.16b, Y_1.16b, X_1.16b
|
||||
eor TMP2.16b, Y_2.16b, X_2.16b
|
||||
eor TMP3.16b, Y_3.16b, X_3.16b
|
||||
|
||||
// y = ror(y, 3)
|
||||
ushr Y_0.\lanes, TMP0.\lanes, #3
|
||||
ushr Y_1.\lanes, TMP1.\lanes, #3
|
||||
ushr Y_2.\lanes, TMP2.\lanes, #3
|
||||
ushr Y_3.\lanes, TMP3.\lanes, #3
|
||||
sli Y_0.\lanes, TMP0.\lanes, #(\n - 3)
|
||||
sli Y_1.\lanes, TMP1.\lanes, #(\n - 3)
|
||||
sli Y_2.\lanes, TMP2.\lanes, #(\n - 3)
|
||||
sli Y_3.\lanes, TMP3.\lanes, #(\n - 3)
|
||||
|
||||
// x ^= k
|
||||
eor X_0.16b, X_0.16b, ROUND_KEY.16b
|
||||
eor X_1.16b, X_1.16b, ROUND_KEY.16b
|
||||
eor X_2.16b, X_2.16b, ROUND_KEY.16b
|
||||
eor X_3.16b, X_3.16b, ROUND_KEY.16b
|
||||
|
||||
// x -= y
|
||||
sub X_0.\lanes, X_0.\lanes, Y_0.\lanes
|
||||
sub X_1.\lanes, X_1.\lanes, Y_1.\lanes
|
||||
sub X_2.\lanes, X_2.\lanes, Y_2.\lanes
|
||||
sub X_3.\lanes, X_3.\lanes, Y_3.\lanes
|
||||
|
||||
// x = rol(x, 8)
|
||||
tbl X_0.16b, {X_0.16b}, ROTATE_TABLE.16b
|
||||
tbl X_1.16b, {X_1.16b}, ROTATE_TABLE.16b
|
||||
tbl X_2.16b, {X_2.16b}, ROTATE_TABLE.16b
|
||||
tbl X_3.16b, {X_3.16b}, ROTATE_TABLE.16b
|
||||
.endm
|
||||
|
||||
.macro _next_xts_tweak next, cur, tmp, n
|
||||
.if \n == 64
|
||||
/*
|
||||
* Calculate the next tweak by multiplying the current one by x,
|
||||
* modulo p(x) = x^128 + x^7 + x^2 + x + 1.
|
||||
*/
|
||||
sshr \tmp\().2d, \cur\().2d, #63
|
||||
and \tmp\().16b, \tmp\().16b, GFMUL_TABLE.16b
|
||||
shl \next\().2d, \cur\().2d, #1
|
||||
ext \tmp\().16b, \tmp\().16b, \tmp\().16b, #8
|
||||
eor \next\().16b, \next\().16b, \tmp\().16b
|
||||
.else
|
||||
/*
|
||||
* Calculate the next two tweaks by multiplying the current ones by x^2,
|
||||
* modulo p(x) = x^64 + x^4 + x^3 + x + 1.
|
||||
*/
|
||||
ushr \tmp\().2d, \cur\().2d, #62
|
||||
shl \next\().2d, \cur\().2d, #2
|
||||
tbl \tmp\().16b, {GFMUL_TABLE.16b}, \tmp\().16b
|
||||
eor \next\().16b, \next\().16b, \tmp\().16b
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* _speck_xts_crypt() - Speck-XTS encryption/decryption
|
||||
*
|
||||
* Encrypt or decrypt NBYTES bytes of data from the SRC buffer to the DST buffer
|
||||
* using Speck-XTS, specifically the variant with a block size of '2n' and round
|
||||
* count given by NROUNDS. The expanded round keys are given in ROUND_KEYS, and
|
||||
* the current XTS tweak value is given in TWEAK. It's assumed that NBYTES is a
|
||||
* nonzero multiple of 128.
|
||||
*/
|
||||
.macro _speck_xts_crypt n, lanes, decrypting
|
||||
|
||||
/*
|
||||
* If decrypting, modify the ROUND_KEYS parameter to point to the last
|
||||
* round key rather than the first, since for decryption the round keys
|
||||
* are used in reverse order.
|
||||
*/
|
||||
.if \decrypting
|
||||
mov NROUNDS, NROUNDS /* zero the high 32 bits */
|
||||
.if \n == 64
|
||||
add ROUND_KEYS, ROUND_KEYS, NROUNDS_X, lsl #3
|
||||
sub ROUND_KEYS, ROUND_KEYS, #8
|
||||
.else
|
||||
add ROUND_KEYS, ROUND_KEYS, NROUNDS_X, lsl #2
|
||||
sub ROUND_KEYS, ROUND_KEYS, #4
|
||||
.endif
|
||||
.endif
|
||||
|
||||
// Load the index vector for tbl-based 8-bit rotates
|
||||
.if \decrypting
|
||||
ldr ROTATE_TABLE_Q, .Lrol\n\()_8_table
|
||||
.else
|
||||
ldr ROTATE_TABLE_Q, .Lror\n\()_8_table
|
||||
.endif
|
||||
|
||||
// One-time XTS preparation
|
||||
.if \n == 64
|
||||
// Load first tweak
|
||||
ld1 {TWEAKV0.16b}, [TWEAK]
|
||||
|
||||
// Load GF(2^128) multiplication table
|
||||
ldr GFMUL_TABLE_Q, .Lgf128mul_table
|
||||
.else
|
||||
// Load first tweak
|
||||
ld1 {TWEAKV0.8b}, [TWEAK]
|
||||
|
||||
// Load GF(2^64) multiplication table
|
||||
ldr GFMUL_TABLE_Q, .Lgf64mul_table
|
||||
|
||||
// Calculate second tweak, packing it together with the first
|
||||
ushr TMP0.2d, TWEAKV0.2d, #63
|
||||
shl TMP1.2d, TWEAKV0.2d, #1
|
||||
tbl TMP0.8b, {GFMUL_TABLE.16b}, TMP0.8b
|
||||
eor TMP0.8b, TMP0.8b, TMP1.8b
|
||||
mov TWEAKV0.d[1], TMP0.d[0]
|
||||
.endif
|
||||
|
||||
.Lnext_128bytes_\@:
|
||||
|
||||
// Calculate XTS tweaks for next 128 bytes
|
||||
_next_xts_tweak TWEAKV1, TWEAKV0, TMP0, \n
|
||||
_next_xts_tweak TWEAKV2, TWEAKV1, TMP0, \n
|
||||
_next_xts_tweak TWEAKV3, TWEAKV2, TMP0, \n
|
||||
_next_xts_tweak TWEAKV4, TWEAKV3, TMP0, \n
|
||||
_next_xts_tweak TWEAKV5, TWEAKV4, TMP0, \n
|
||||
_next_xts_tweak TWEAKV6, TWEAKV5, TMP0, \n
|
||||
_next_xts_tweak TWEAKV7, TWEAKV6, TMP0, \n
|
||||
_next_xts_tweak TWEAKV_NEXT, TWEAKV7, TMP0, \n
|
||||
|
||||
// Load the next source blocks into {X,Y}[0-3]
|
||||
ld1 {X_0.16b-Y_1.16b}, [SRC], #64
|
||||
ld1 {X_2.16b-Y_3.16b}, [SRC], #64
|
||||
|
||||
// XOR the source blocks with their XTS tweaks
|
||||
eor TMP0.16b, X_0.16b, TWEAKV0.16b
|
||||
eor Y_0.16b, Y_0.16b, TWEAKV1.16b
|
||||
eor TMP1.16b, X_1.16b, TWEAKV2.16b
|
||||
eor Y_1.16b, Y_1.16b, TWEAKV3.16b
|
||||
eor TMP2.16b, X_2.16b, TWEAKV4.16b
|
||||
eor Y_2.16b, Y_2.16b, TWEAKV5.16b
|
||||
eor TMP3.16b, X_3.16b, TWEAKV6.16b
|
||||
eor Y_3.16b, Y_3.16b, TWEAKV7.16b
|
||||
|
||||
/*
|
||||
* De-interleave the 'x' and 'y' elements of each block, i.e. make it so
|
||||
* that the X[0-3] registers contain only the second halves of blocks,
|
||||
* and the Y[0-3] registers contain only the first halves of blocks.
|
||||
* (Speck uses the order (y, x) rather than the more intuitive (x, y).)
|
||||
*/
|
||||
uzp2 X_0.\lanes, TMP0.\lanes, Y_0.\lanes
|
||||
uzp1 Y_0.\lanes, TMP0.\lanes, Y_0.\lanes
|
||||
uzp2 X_1.\lanes, TMP1.\lanes, Y_1.\lanes
|
||||
uzp1 Y_1.\lanes, TMP1.\lanes, Y_1.\lanes
|
||||
uzp2 X_2.\lanes, TMP2.\lanes, Y_2.\lanes
|
||||
uzp1 Y_2.\lanes, TMP2.\lanes, Y_2.\lanes
|
||||
uzp2 X_3.\lanes, TMP3.\lanes, Y_3.\lanes
|
||||
uzp1 Y_3.\lanes, TMP3.\lanes, Y_3.\lanes
|
||||
|
||||
// Do the cipher rounds
|
||||
mov x6, ROUND_KEYS
|
||||
mov w7, NROUNDS
|
||||
.Lnext_round_\@:
|
||||
.if \decrypting
|
||||
ld1r {ROUND_KEY.\lanes}, [x6]
|
||||
sub x6, x6, #( \n / 8 )
|
||||
_speck_unround_128bytes \n, \lanes
|
||||
.else
|
||||
ld1r {ROUND_KEY.\lanes}, [x6], #( \n / 8 )
|
||||
_speck_round_128bytes \n, \lanes
|
||||
.endif
|
||||
subs w7, w7, #1
|
||||
bne .Lnext_round_\@
|
||||
|
||||
// Re-interleave the 'x' and 'y' elements of each block
|
||||
zip1 TMP0.\lanes, Y_0.\lanes, X_0.\lanes
|
||||
zip2 Y_0.\lanes, Y_0.\lanes, X_0.\lanes
|
||||
zip1 TMP1.\lanes, Y_1.\lanes, X_1.\lanes
|
||||
zip2 Y_1.\lanes, Y_1.\lanes, X_1.\lanes
|
||||
zip1 TMP2.\lanes, Y_2.\lanes, X_2.\lanes
|
||||
zip2 Y_2.\lanes, Y_2.\lanes, X_2.\lanes
|
||||
zip1 TMP3.\lanes, Y_3.\lanes, X_3.\lanes
|
||||
zip2 Y_3.\lanes, Y_3.\lanes, X_3.\lanes
|
||||
|
||||
// XOR the encrypted/decrypted blocks with the tweaks calculated earlier
|
||||
eor X_0.16b, TMP0.16b, TWEAKV0.16b
|
||||
eor Y_0.16b, Y_0.16b, TWEAKV1.16b
|
||||
eor X_1.16b, TMP1.16b, TWEAKV2.16b
|
||||
eor Y_1.16b, Y_1.16b, TWEAKV3.16b
|
||||
eor X_2.16b, TMP2.16b, TWEAKV4.16b
|
||||
eor Y_2.16b, Y_2.16b, TWEAKV5.16b
|
||||
eor X_3.16b, TMP3.16b, TWEAKV6.16b
|
||||
eor Y_3.16b, Y_3.16b, TWEAKV7.16b
|
||||
mov TWEAKV0.16b, TWEAKV_NEXT.16b
|
||||
|
||||
// Store the ciphertext in the destination buffer
|
||||
st1 {X_0.16b-Y_1.16b}, [DST], #64
|
||||
st1 {X_2.16b-Y_3.16b}, [DST], #64
|
||||
|
||||
// Continue if there are more 128-byte chunks remaining
|
||||
subs NBYTES, NBYTES, #128
|
||||
bne .Lnext_128bytes_\@
|
||||
|
||||
// Store the next tweak and return
|
||||
.if \n == 64
|
||||
st1 {TWEAKV_NEXT.16b}, [TWEAK]
|
||||
.else
|
||||
st1 {TWEAKV_NEXT.8b}, [TWEAK]
|
||||
.endif
|
||||
ret
|
||||
.endm
|
||||
|
||||
ENTRY(speck128_xts_encrypt_neon)
|
||||
_speck_xts_crypt n=64, lanes=2d, decrypting=0
|
||||
ENDPROC(speck128_xts_encrypt_neon)
|
||||
|
||||
ENTRY(speck128_xts_decrypt_neon)
|
||||
_speck_xts_crypt n=64, lanes=2d, decrypting=1
|
||||
ENDPROC(speck128_xts_decrypt_neon)
|
||||
|
||||
ENTRY(speck64_xts_encrypt_neon)
|
||||
_speck_xts_crypt n=32, lanes=4s, decrypting=0
|
||||
ENDPROC(speck64_xts_encrypt_neon)
|
||||
|
||||
ENTRY(speck64_xts_decrypt_neon)
|
||||
_speck_xts_crypt n=32, lanes=4s, decrypting=1
|
||||
ENDPROC(speck64_xts_decrypt_neon)
|
||||
308
arch/arm64/crypto/speck-neon-glue.c
Normal file
308
arch/arm64/crypto/speck-neon-glue.c
Normal file
@@ -0,0 +1,308 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* NEON-accelerated implementation of Speck128-XTS and Speck64-XTS
|
||||
* (64-bit version; based on the 32-bit version)
|
||||
*
|
||||
* Copyright (c) 2018 Google, Inc
|
||||
*/
|
||||
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/gf128mul.h>
|
||||
#include <crypto/speck.h>
|
||||
#include <crypto/xts.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/* The assembly functions only handle multiples of 128 bytes */
|
||||
#define SPECK_NEON_CHUNK_SIZE 128
|
||||
|
||||
/* Speck128 */
|
||||
|
||||
struct speck128_xts_tfm_ctx {
|
||||
struct speck128_tfm_ctx main_key;
|
||||
struct speck128_tfm_ctx tweak_key;
|
||||
};
|
||||
|
||||
asmlinkage void speck128_xts_encrypt_neon(const u64 *round_keys, int nrounds,
|
||||
void *dst, const void *src,
|
||||
unsigned int nbytes, void *tweak);
|
||||
|
||||
asmlinkage void speck128_xts_decrypt_neon(const u64 *round_keys, int nrounds,
|
||||
void *dst, const void *src,
|
||||
unsigned int nbytes, void *tweak);
|
||||
|
||||
typedef void (*speck128_crypt_one_t)(const struct speck128_tfm_ctx *,
|
||||
u8 *, const u8 *);
|
||||
typedef void (*speck128_xts_crypt_many_t)(const u64 *, int, void *,
|
||||
const void *, unsigned int, void *);
|
||||
|
||||
static __always_inline int
|
||||
__speck128_xts_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes,
|
||||
speck128_crypt_one_t crypt_one,
|
||||
speck128_xts_crypt_many_t crypt_many)
|
||||
{
|
||||
struct crypto_blkcipher *tfm = desc->tfm;
|
||||
const struct speck128_xts_tfm_ctx *ctx = crypto_blkcipher_ctx(tfm);
|
||||
struct blkcipher_walk walk;
|
||||
le128 tweak;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt_block(desc, &walk, SPECK_NEON_CHUNK_SIZE);
|
||||
|
||||
crypto_speck128_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv);
|
||||
|
||||
while (walk.nbytes > 0) {
|
||||
unsigned int nbytes = walk.nbytes;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
|
||||
if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) {
|
||||
unsigned int count;
|
||||
|
||||
count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE);
|
||||
kernel_neon_begin();
|
||||
(*crypt_many)(ctx->main_key.round_keys,
|
||||
ctx->main_key.nrounds,
|
||||
dst, src, count, &tweak);
|
||||
kernel_neon_end();
|
||||
dst += count;
|
||||
src += count;
|
||||
nbytes -= count;
|
||||
}
|
||||
|
||||
/* Handle any remainder with generic code */
|
||||
while (nbytes >= sizeof(tweak)) {
|
||||
le128_xor((le128 *)dst, (const le128 *)src, &tweak);
|
||||
(*crypt_one)(&ctx->main_key, dst, dst);
|
||||
le128_xor((le128 *)dst, (const le128 *)dst, &tweak);
|
||||
gf128mul_x_ble((be128 *)&tweak, (const be128 *)&tweak);
|
||||
|
||||
dst += sizeof(tweak);
|
||||
src += sizeof(tweak);
|
||||
nbytes -= sizeof(tweak);
|
||||
}
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int speck128_xts_encrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return __speck128_xts_crypt(desc, dst, src, nbytes,
|
||||
crypto_speck128_encrypt,
|
||||
speck128_xts_encrypt_neon);
|
||||
}
|
||||
|
||||
static int speck128_xts_decrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return __speck128_xts_crypt(desc, dst, src, nbytes,
|
||||
crypto_speck128_decrypt,
|
||||
speck128_xts_decrypt_neon);
|
||||
}
|
||||
|
||||
static int speck128_xts_setkey(struct crypto_tfm *tfm, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct speck128_xts_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
int err;
|
||||
|
||||
if (keylen % 2)
|
||||
return -EINVAL;
|
||||
|
||||
keylen /= 2;
|
||||
|
||||
err = crypto_speck128_setkey(&ctx->main_key, key, keylen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return crypto_speck128_setkey(&ctx->tweak_key, key + keylen, keylen);
|
||||
}
|
||||
|
||||
/* Speck64 */
|
||||
|
||||
struct speck64_xts_tfm_ctx {
|
||||
struct speck64_tfm_ctx main_key;
|
||||
struct speck64_tfm_ctx tweak_key;
|
||||
};
|
||||
|
||||
asmlinkage void speck64_xts_encrypt_neon(const u32 *round_keys, int nrounds,
|
||||
void *dst, const void *src,
|
||||
unsigned int nbytes, void *tweak);
|
||||
|
||||
asmlinkage void speck64_xts_decrypt_neon(const u32 *round_keys, int nrounds,
|
||||
void *dst, const void *src,
|
||||
unsigned int nbytes, void *tweak);
|
||||
|
||||
typedef void (*speck64_crypt_one_t)(const struct speck64_tfm_ctx *,
|
||||
u8 *, const u8 *);
|
||||
typedef void (*speck64_xts_crypt_many_t)(const u32 *, int, void *,
|
||||
const void *, unsigned int, void *);
|
||||
|
||||
static __always_inline int
|
||||
__speck64_xts_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes,
|
||||
speck64_crypt_one_t crypt_one,
|
||||
speck64_xts_crypt_many_t crypt_many)
|
||||
{
|
||||
struct crypto_blkcipher *tfm = desc->tfm;
|
||||
const struct speck64_xts_tfm_ctx *ctx = crypto_blkcipher_ctx(tfm);
|
||||
struct blkcipher_walk walk;
|
||||
__le64 tweak;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt_block(desc, &walk, SPECK_NEON_CHUNK_SIZE);
|
||||
|
||||
crypto_speck64_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv);
|
||||
|
||||
while (walk.nbytes > 0) {
|
||||
unsigned int nbytes = walk.nbytes;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
|
||||
if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) {
|
||||
unsigned int count;
|
||||
|
||||
count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE);
|
||||
kernel_neon_begin();
|
||||
(*crypt_many)(ctx->main_key.round_keys,
|
||||
ctx->main_key.nrounds,
|
||||
dst, src, count, &tweak);
|
||||
kernel_neon_end();
|
||||
dst += count;
|
||||
src += count;
|
||||
nbytes -= count;
|
||||
}
|
||||
|
||||
/* Handle any remainder with generic code */
|
||||
while (nbytes >= sizeof(tweak)) {
|
||||
*(__le64 *)dst = *(__le64 *)src ^ tweak;
|
||||
(*crypt_one)(&ctx->main_key, dst, dst);
|
||||
*(__le64 *)dst ^= tweak;
|
||||
tweak = cpu_to_le64((le64_to_cpu(tweak) << 1) ^
|
||||
((tweak & cpu_to_le64(1ULL << 63)) ?
|
||||
0x1B : 0));
|
||||
dst += sizeof(tweak);
|
||||
src += sizeof(tweak);
|
||||
nbytes -= sizeof(tweak);
|
||||
}
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int speck64_xts_encrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return __speck64_xts_crypt(desc, dst, src, nbytes,
|
||||
crypto_speck64_encrypt,
|
||||
speck64_xts_encrypt_neon);
|
||||
}
|
||||
|
||||
static int speck64_xts_decrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
return __speck64_xts_crypt(desc, dst, src, nbytes,
|
||||
crypto_speck64_decrypt,
|
||||
speck64_xts_decrypt_neon);
|
||||
}
|
||||
|
||||
static int speck64_xts_setkey(struct crypto_tfm *tfm, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct speck64_xts_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
int err;
|
||||
|
||||
if (keylen % 2)
|
||||
return -EINVAL;
|
||||
|
||||
keylen /= 2;
|
||||
|
||||
err = crypto_speck64_setkey(&ctx->main_key, key, keylen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return crypto_speck64_setkey(&ctx->tweak_key, key + keylen, keylen);
|
||||
}
|
||||
|
||||
static struct crypto_alg speck_algs[] = {
|
||||
{
|
||||
.cra_name = "xts(speck128)",
|
||||
.cra_driver_name = "xts-speck128-neon",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = SPECK128_BLOCK_SIZE,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_ctxsize = sizeof(struct speck128_xts_tfm_ctx),
|
||||
.cra_alignmask = 7,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = 2 * SPECK128_128_KEY_SIZE,
|
||||
.max_keysize = 2 * SPECK128_256_KEY_SIZE,
|
||||
.ivsize = SPECK128_BLOCK_SIZE,
|
||||
.setkey = speck128_xts_setkey,
|
||||
.encrypt = speck128_xts_encrypt,
|
||||
.decrypt = speck128_xts_decrypt,
|
||||
}
|
||||
}
|
||||
}, {
|
||||
.cra_name = "xts(speck64)",
|
||||
.cra_driver_name = "xts-speck64-neon",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = SPECK64_BLOCK_SIZE,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_ctxsize = sizeof(struct speck64_xts_tfm_ctx),
|
||||
.cra_alignmask = 7,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = 2 * SPECK64_96_KEY_SIZE,
|
||||
.max_keysize = 2 * SPECK64_128_KEY_SIZE,
|
||||
.ivsize = SPECK64_BLOCK_SIZE,
|
||||
.setkey = speck64_xts_setkey,
|
||||
.encrypt = speck64_xts_encrypt,
|
||||
.decrypt = speck64_xts_decrypt,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int __init speck_neon_module_init(void)
|
||||
{
|
||||
if (!(elf_hwcap & HWCAP_ASIMD))
|
||||
return -ENODEV;
|
||||
return crypto_register_algs(speck_algs, ARRAY_SIZE(speck_algs));
|
||||
}
|
||||
|
||||
static void __exit speck_neon_module_exit(void)
|
||||
{
|
||||
crypto_unregister_algs(speck_algs, ARRAY_SIZE(speck_algs));
|
||||
}
|
||||
|
||||
module_init(speck_neon_module_init);
|
||||
module_exit(speck_neon_module_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Speck block cipher (NEON-accelerated)");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
|
||||
MODULE_ALIAS_CRYPTO("xts(speck128)");
|
||||
MODULE_ALIAS_CRYPTO("xts-speck128-neon");
|
||||
MODULE_ALIAS_CRYPTO("xts(speck64)");
|
||||
MODULE_ALIAS_CRYPTO("xts-speck64-neon");
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user