Merge 9fa4abc9ad ("Merge tag 'fbdev-for-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev") into android-mainline
Steps on the way to 6.2-rc1 Change-Id: I0275af4b64368997ab627b5b24a441bbd6d39b8e Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -99,6 +99,12 @@ Description: Controls the issue rate of discard commands that consist of small
|
||||
checkpoint is triggered, and issued during the checkpoint.
|
||||
By default, it is disabled with 0.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/max_ordered_discard
|
||||
Date: October 2022
|
||||
Contact: "Yangtao Li" <frank.li@vivo.com>
|
||||
Description: Controls the maximum ordered discard, the unit size is one block(4KB).
|
||||
Set it to 16 by default.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/max_discard_request
|
||||
Date: December 2021
|
||||
Contact: "Konstantin Vyshetsky" <vkon@google.com>
|
||||
@@ -132,7 +138,8 @@ Contact: "Chao Yu" <yuchao0@huawei.com>
|
||||
Description: Controls discard granularity of inner discard thread. Inner thread
|
||||
will not issue discards with size that is smaller than granularity.
|
||||
The unit size is one block(4KB), now only support configuring
|
||||
in range of [1, 512]. Default value is 4(=16KB).
|
||||
in range of [1, 512]. Default value is 16.
|
||||
For small devices, default value is 1.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/umount_discard_timeout
|
||||
Date: January 2019
|
||||
@@ -235,7 +242,7 @@ Description: Shows total written kbytes issued to disk.
|
||||
What: /sys/fs/f2fs/<disk>/features
|
||||
Date: July 2017
|
||||
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
|
||||
Description: <deprecated: should use /sys/fs/f2fs/<disk>/feature_list/
|
||||
Description: <deprecated: should use /sys/fs/f2fs/<disk>/feature_list/>
|
||||
Shows all enabled features in current device.
|
||||
Supported features:
|
||||
encryption, blkzoned, extra_attr, projquota, inode_checksum,
|
||||
@@ -592,10 +599,10 @@ Description: With "mode=fragment:block" mount options, we can scatter block allo
|
||||
in the length of 1..<max_fragment_hole> by turns. This value can be set
|
||||
between 1..512 and the default value is 4.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/gc_urgent_high_remaining
|
||||
Date: December 2021
|
||||
Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: You can set the trial count limit for GC urgent high mode with this value.
|
||||
What: /sys/fs/f2fs/<disk>/gc_remaining_trials
|
||||
Date: October 2022
|
||||
Contact: "Yangtao Li" <frank.li@vivo.com>
|
||||
Description: You can set the trial count limit for GC urgent and idle mode with this value.
|
||||
If GC thread gets to the limit, the mode will turn back to GC normal mode.
|
||||
By default, the value is zero, which means there is no limit like before.
|
||||
|
||||
@@ -634,3 +641,31 @@ Date: July 2022
|
||||
Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: Show the accumulated total revoked atomic write block count after boot.
|
||||
If you write "0" here, you can initialize to "0".
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/gc_mode
|
||||
Date: October 2022
|
||||
Contact: "Yangtao Li" <frank.li@vivo.com>
|
||||
Description: Show the current gc_mode as a string.
|
||||
This is a read-only entry.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/discard_urgent_util
|
||||
Date: November 2022
|
||||
Contact: "Yangtao Li" <frank.li@vivo.com>
|
||||
Description: When space utilization exceeds this, do background DISCARD aggressively.
|
||||
Does DISCARD forcibly in a period of given min_discard_issue_time when the number
|
||||
of discards is not 0 and set discard granularity to 1.
|
||||
Default: 80
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/hot_data_age_threshold
|
||||
Date: November 2022
|
||||
Contact: "Ping Xiong" <xiongping1@xiaomi.com>
|
||||
Description: When DATA SEPARATION is on, it controls the age threshold to indicate
|
||||
the data blocks as hot. By default it was initialized as 262144 blocks
|
||||
(equals to 1GB).
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/warm_data_age_threshold
|
||||
Date: November 2022
|
||||
Contact: "Ping Xiong" <xiongping1@xiaomi.com>
|
||||
Description: When DATA SEPARATION is on, it controls the age threshold to indicate
|
||||
the data blocks as warm. By default it was initialized as 2621440 blocks
|
||||
(equals to 10GB).
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
What: /sys/kernel/oops_count
|
||||
Date: November 2022
|
||||
KernelVersion: 6.2.0
|
||||
Contact: Linux Kernel Hardening List <linux-hardening@vger.kernel.org>
|
||||
Description:
|
||||
Shows how many times the system has Oopsed since last boot.
|
||||
@@ -0,0 +1,6 @@
|
||||
What: /sys/kernel/oops_count
|
||||
Date: November 2022
|
||||
KernelVersion: 6.2.0
|
||||
Contact: Linux Kernel Hardening List <linux-hardening@vger.kernel.org>
|
||||
Description:
|
||||
Shows how many times the system has Warned since last boot.
|
||||
@@ -595,3 +595,32 @@ X2TLB
|
||||
-----
|
||||
|
||||
Indicates whether the crashed kernel enabled SH extended mode.
|
||||
|
||||
RISCV64
|
||||
=======
|
||||
|
||||
VA_BITS
|
||||
-------
|
||||
|
||||
The maximum number of bits for virtual addresses. Used to compute the
|
||||
virtual memory ranges.
|
||||
|
||||
PAGE_OFFSET
|
||||
-----------
|
||||
|
||||
Indicates the virtual kernel start address of the direct-mapped RAM region.
|
||||
|
||||
phys_ram_base
|
||||
-------------
|
||||
|
||||
Indicates the start physical RAM address.
|
||||
|
||||
MODULES_VADDR|MODULES_END|VMALLOC_START|VMALLOC_END|VMEMMAP_START|VMEMMAP_END|KERNEL_LINK_ADDR
|
||||
----------------------------------------------------------------------------------------------
|
||||
|
||||
Used to get the correct ranges:
|
||||
|
||||
* MODULES_VADDR ~ MODULES_END : Kernel module space.
|
||||
* VMALLOC_START ~ VMALLOC_END : vmalloc() / ioremap() space.
|
||||
* VMEMMAP_START ~ VMEMMAP_END : vmemmap space, used for struct page array.
|
||||
* KERNEL_LINK_ADDR : start address of Kernel link and BPF
|
||||
|
||||
@@ -670,6 +670,15 @@ This is the default behavior.
|
||||
an oops event is detected.
|
||||
|
||||
|
||||
oops_limit
|
||||
==========
|
||||
|
||||
Number of kernel oopses after which the kernel should panic when
|
||||
``panic_on_oops`` is not set. Setting this to 0 disables checking
|
||||
the count. Setting this to 1 has the same effect as setting
|
||||
``panic_on_oops=1``. The default value is 10000.
|
||||
|
||||
|
||||
osrelease, ostype & version
|
||||
===========================
|
||||
|
||||
@@ -1526,6 +1535,16 @@ entry will default to 2 instead of 0.
|
||||
2 Unprivileged calls to ``bpf()`` are disabled
|
||||
= =============================================================
|
||||
|
||||
|
||||
warn_limit
|
||||
==========
|
||||
|
||||
Number of kernel warnings after which the kernel should panic when
|
||||
``panic_on_warn`` is not set. Setting this to 0 disables checking
|
||||
the warning count. Setting this to 1 has the same effect as setting
|
||||
``panic_on_warn=1``. The default value is 0.
|
||||
|
||||
|
||||
watchdog
|
||||
========
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ String Conversions
|
||||
String Manipulation
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: include/linux/fortify-string.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: lib/string.c
|
||||
:export:
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ Here are schematics of how these functions are called when operated from
|
||||
other part of the kernel. Note that the .setkey() call might happen
|
||||
before or after any of these schematics happen, but must not happen
|
||||
during any of these are in-flight. Please note that calling .init()
|
||||
followed immediately by .finish() is also a perfectly valid
|
||||
followed immediately by .final() is also a perfectly valid
|
||||
transformation.
|
||||
|
||||
::
|
||||
|
||||
@@ -131,9 +131,9 @@ from the kernel crypto API. If the buffer is too small for the message
|
||||
digest, the flag MSG_TRUNC is set by the kernel.
|
||||
|
||||
In order to set a message digest key, the calling application must use
|
||||
the setsockopt() option of ALG_SET_KEY. If the key is not set the HMAC
|
||||
operation is performed without the initial HMAC state change caused by
|
||||
the key.
|
||||
the setsockopt() option of ALG_SET_KEY or ALG_SET_KEY_BY_KEY_SERIAL. If the
|
||||
key is not set the HMAC operation is performed without the initial HMAC state
|
||||
change caused by the key.
|
||||
|
||||
Symmetric Cipher API
|
||||
--------------------
|
||||
@@ -382,6 +382,15 @@ mentioned optname:
|
||||
|
||||
- the RNG cipher type to provide the seed
|
||||
|
||||
- ALG_SET_KEY_BY_KEY_SERIAL -- Setting the key via keyring key_serial_t.
|
||||
This operation behaves the same as ALG_SET_KEY. The decrypted
|
||||
data is copied from a keyring key, and uses that data as the
|
||||
key for symmetric encryption.
|
||||
|
||||
The passed in key_serial_t must have the KEY_(POS|USR|GRP|OTH)_SEARCH
|
||||
permission set, otherwise -EPERM is returned. Supports key types: user,
|
||||
logon, encrypted, and trusted.
|
||||
|
||||
- ALG_SET_AEAD_AUTHSIZE -- Setting the authentication tag size for
|
||||
AEAD ciphers. For a encryption operation, the authentication tag of
|
||||
the given size will be generated. For a decryption operation, the
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/crypto/rockchip,rk3288-crypto.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip Electronics Security Accelerator
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- rockchip,rk3288-crypto
|
||||
- rockchip,rk3328-crypto
|
||||
- rockchip,rk3399-crypto
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3288-crypto
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: aclk
|
||||
- const: hclk
|
||||
- const: sclk
|
||||
- const: apb_pclk
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
items:
|
||||
- const: crypto-rst
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3328-crypto
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: hclk_master
|
||||
- const: hclk_slave
|
||||
- const: sclk
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
items:
|
||||
- const: crypto-rst
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3399-crypto
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: hclk_master
|
||||
- const: hclk_slave
|
||||
- const: sclk
|
||||
resets:
|
||||
minItems: 3
|
||||
reset-names:
|
||||
items:
|
||||
- const: master
|
||||
- const: slave
|
||||
- const: crypto-rst
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/rk3288-cru.h>
|
||||
crypto@ff8a0000 {
|
||||
compatible = "rockchip,rk3288-crypto";
|
||||
reg = <0xff8a0000 0x4000>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru ACLK_CRYPTO>, <&cru HCLK_CRYPTO>,
|
||||
<&cru SCLK_CRYPTO>, <&cru ACLK_DMAC1>;
|
||||
clock-names = "aclk", "hclk", "sclk", "apb_pclk";
|
||||
resets = <&cru SRST_CRYPTO>;
|
||||
reset-names = "crypto-rst";
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
Rockchip Electronics And Security Accelerator
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "rockchip,rk3288-crypto"
|
||||
- reg: Base physical address of the engine and length of memory mapped
|
||||
region
|
||||
- interrupts: Interrupt number
|
||||
- clocks: Reference to the clocks about crypto
|
||||
- clock-names: "aclk" used to clock data
|
||||
"hclk" used to clock data
|
||||
"sclk" used to clock crypto accelerator
|
||||
"apb_pclk" used to clock dma
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reset.txt for details.
|
||||
- reset-names: Must include the name "crypto-rst".
|
||||
|
||||
Examples:
|
||||
|
||||
crypto: cypto-controller@ff8a0000 {
|
||||
compatible = "rockchip,rk3288-crypto";
|
||||
reg = <0xff8a0000 0x4000>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru ACLK_CRYPTO>, <&cru HCLK_CRYPTO>,
|
||||
<&cru SCLK_CRYPTO>, <&cru ACLK_DMAC1>;
|
||||
clock-names = "aclk", "hclk", "sclk", "apb_pclk";
|
||||
resets = <&cru SRST_CRYPTO>;
|
||||
reset-names = "crypto-rst";
|
||||
};
|
||||
@@ -6,12 +6,18 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: STMicroelectronics STM32 CRYP bindings
|
||||
|
||||
description: The STM32 CRYP block is built on the CRYP block found in
|
||||
the STn8820 SoC introduced in 2007, and subsequently used in the U8500
|
||||
SoC in 2010.
|
||||
|
||||
maintainers:
|
||||
- Lionel Debieve <lionel.debieve@foss.st.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- st,stn8820-cryp
|
||||
- stericsson,ux500-cryp
|
||||
- st,stm32f756-cryp
|
||||
- st,stm32mp1-cryp
|
||||
|
||||
@@ -27,6 +33,19 @@ properties:
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: mem2cryp DMA channel
|
||||
- description: cryp2mem DMA channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: mem2cryp
|
||||
- const: cryp2mem
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -16,7 +16,9 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nuvoton,npcm750-rng
|
||||
enum:
|
||||
- nuvoton,npcm750-rng
|
||||
- nuvoton,npcm845-rng
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
| openrisc: | TODO |
|
||||
| parisc: | TODO |
|
||||
| powerpc: | ok |
|
||||
| riscv: | TODO |
|
||||
| riscv: | ok |
|
||||
| s390: | TODO |
|
||||
| sh: | TODO |
|
||||
| sparc: | TODO |
|
||||
|
||||
@@ -25,10 +25,14 @@ a consistency checking tool (fsck.f2fs), and a debugging tool (dump.f2fs).
|
||||
|
||||
- git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git
|
||||
|
||||
For reporting bugs and sending patches, please use the following mailing list:
|
||||
For sending patches, please use the following mailing list:
|
||||
|
||||
- linux-f2fs-devel@lists.sourceforge.net
|
||||
|
||||
For reporting bugs, please use the following f2fs bug tracker link:
|
||||
|
||||
- https://bugzilla.kernel.org/enter_bug.cgi?product=File%20System&component=f2fs
|
||||
|
||||
Background and Design issues
|
||||
============================
|
||||
|
||||
@@ -154,6 +158,8 @@ nobarrier This option can be used if underlying storage guarantees
|
||||
If this option is set, no cache_flush commands are issued
|
||||
but f2fs still guarantees the write ordering of all the
|
||||
data writes.
|
||||
barrier If this option is set, cache_flush commands are allowed to be
|
||||
issued.
|
||||
fastboot This option is used when a system wants to reduce mount
|
||||
time as much as possible, even though normal performance
|
||||
can be sacrificed.
|
||||
@@ -199,6 +205,7 @@ fault_type=%d Support configuring fault injection type, should be
|
||||
FAULT_SLAB_ALLOC 0x000008000
|
||||
FAULT_DQUOT_INIT 0x000010000
|
||||
FAULT_LOCK_OP 0x000020000
|
||||
FAULT_BLKADDR 0x000040000
|
||||
=================== ===========
|
||||
mode=%s Control block allocation mode which supports "adaptive"
|
||||
and "lfs". In "lfs" mode, there should be no random
|
||||
@@ -340,6 +347,10 @@ memory=%s Control memory mode. This supports "normal" and "low" modes.
|
||||
Because of the nature of low memory devices, in this mode, f2fs
|
||||
will try to save memory sometimes by sacrificing performance.
|
||||
"normal" mode is the default mode and same as before.
|
||||
age_extent_cache Enable an age extent cache based on rb-tree. It records
|
||||
data block update frequency of the extent per inode, in
|
||||
order to provide better temperature hints for data block
|
||||
allocation.
|
||||
======================== ============================================================
|
||||
|
||||
Debugfs Entries
|
||||
|
||||
@@ -20,16 +20,22 @@ Submit Checklist Addendum
|
||||
-------------------------
|
||||
We'll only accept patches for new modules or extensions if the
|
||||
specifications for those modules or extensions are listed as being
|
||||
"Frozen" or "Ratified" by the RISC-V Foundation. (Developers may, of
|
||||
course, maintain their own Linux kernel trees that contain code for
|
||||
any draft extensions that they wish.)
|
||||
unlikely to be incompatibly changed in the future. For
|
||||
specifications from the RISC-V foundation this means "Frozen" or
|
||||
"Ratified", for the UEFI forum specifications this means a published
|
||||
ECR. (Developers may, of course, maintain their own Linux kernel trees
|
||||
that contain code for any draft extensions that they wish.)
|
||||
|
||||
Additionally, the RISC-V specification allows implementors to create
|
||||
Additionally, the RISC-V specification allows implementers to create
|
||||
their own custom extensions. These custom extensions aren't required
|
||||
to go through any review or ratification process by the RISC-V
|
||||
Foundation. To avoid the maintenance complexity and potential
|
||||
performance impact of adding kernel code for implementor-specific
|
||||
RISC-V extensions, we'll only to accept patches for extensions that
|
||||
have been officially frozen or ratified by the RISC-V Foundation.
|
||||
(Implementors, may, of course, maintain their own Linux kernel trees
|
||||
containing code for any custom extensions that they wish.)
|
||||
RISC-V extensions, we'll only consider patches for extensions that either:
|
||||
|
||||
- Have been officially frozen or ratified by the RISC-V Foundation, or
|
||||
- Have been implemented in hardware that is widely available, per standard
|
||||
Linux practice.
|
||||
|
||||
(Implementers, may, of course, maintain their own Linux kernel trees containing
|
||||
code for any custom extensions that they wish.)
|
||||
|
||||
+13
-1
@@ -7889,6 +7889,7 @@ M: Chao Yu <chao@kernel.org>
|
||||
L: linux-f2fs-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
W: https://f2fs.wiki.kernel.org/
|
||||
B: https://bugzilla.kernel.org/enter_bug.cgi?product=File%20System&component=f2fs
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
|
||||
F: Documentation/ABI/testing/sysfs-fs-f2fs
|
||||
F: Documentation/filesystems/f2fs.rst
|
||||
@@ -8105,6 +8106,8 @@ S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
|
||||
F: include/linux/fortify-string.h
|
||||
F: lib/fortify_kunit.c
|
||||
F: lib/memcpy_kunit.c
|
||||
F: lib/strscpy_kunit.c
|
||||
F: lib/test_fortify/*
|
||||
F: scripts/test_fortify.sh
|
||||
K: \b__NO_FORTIFY\b
|
||||
@@ -11215,6 +11218,8 @@ M: Kees Cook <keescook@chromium.org>
|
||||
L: linux-hardening@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
|
||||
F: Documentation/ABI/testing/sysfs-kernel-oops_count
|
||||
F: Documentation/ABI/testing/sysfs-kernel-warn_count
|
||||
F: include/linux/overflow.h
|
||||
F: include/linux/randomize_kstack.h
|
||||
F: mm/usercopy.c
|
||||
@@ -17944,6 +17949,13 @@ F: Documentation/ABI/*/sysfs-driver-hid-roccat*
|
||||
F: drivers/hid/hid-roccat*
|
||||
F: include/linux/hid-roccat*
|
||||
|
||||
ROCKCHIP CRYPTO DRIVERS
|
||||
M: Corentin Labbe <clabbe@baylibre.com>
|
||||
L: linux-crypto@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/crypto/rockchip,rk3288-crypto.yaml
|
||||
F: drivers/crypto/rockchip/
|
||||
|
||||
ROCKCHIP I2S TDM DRIVER
|
||||
M: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
|
||||
L: linux-rockchip@lists.infradead.org
|
||||
@@ -19057,7 +19069,7 @@ M: Jason A. Donenfeld <Jason@zx2c4.com>
|
||||
S: Maintained
|
||||
F: include/linux/siphash.h
|
||||
F: lib/siphash.c
|
||||
F: lib/test_siphash.c
|
||||
F: lib/siphash_kunit.c
|
||||
|
||||
SIS 190 ETHERNET DRIVER
|
||||
M: Francois Romieu <romieu@fr.zoreil.com>
|
||||
|
||||
@@ -1032,8 +1032,8 @@ KBUILD_CFLAGS += $(CC_FLAGS_CFI)
|
||||
export CC_FLAGS_CFI
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B
|
||||
KBUILD_CFLAGS += -falign-functions=64
|
||||
ifneq ($(CONFIG_FUNCTION_ALIGNMENT),0)
|
||||
KBUILD_CFLAGS += -falign-functions=$(CONFIG_FUNCTION_ALIGNMENT)
|
||||
endif
|
||||
|
||||
# arch Makefile may override CC so keep this after arch Makefile is included
|
||||
@@ -1146,7 +1146,7 @@ endif
|
||||
# We never want expected sections to be placed heuristically by the
|
||||
# linker. All sections should be explicitly named in the linker script.
|
||||
ifdef CONFIG_LD_ORPHAN_WARN
|
||||
LDFLAGS_vmlinux += --orphan-handling=warn
|
||||
LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
|
||||
endif
|
||||
|
||||
# Align the bit size of userspace programs with the kernel
|
||||
|
||||
@@ -1438,4 +1438,28 @@ source "kernel/gcov/Kconfig"
|
||||
|
||||
source "scripts/gcc-plugins/Kconfig"
|
||||
|
||||
config FUNCTION_ALIGNMENT_4B
|
||||
bool
|
||||
|
||||
config FUNCTION_ALIGNMENT_8B
|
||||
bool
|
||||
|
||||
config FUNCTION_ALIGNMENT_16B
|
||||
bool
|
||||
|
||||
config FUNCTION_ALIGNMENT_32B
|
||||
bool
|
||||
|
||||
config FUNCTION_ALIGNMENT_64B
|
||||
bool
|
||||
|
||||
config FUNCTION_ALIGNMENT
|
||||
int
|
||||
default 64 if FUNCTION_ALIGNMENT_64B
|
||||
default 32 if FUNCTION_ALIGNMENT_32B
|
||||
default 16 if FUNCTION_ALIGNMENT_16B
|
||||
default 8 if FUNCTION_ALIGNMENT_8B
|
||||
default 4 if FUNCTION_ALIGNMENT_4B
|
||||
default 0
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -124,7 +124,7 @@ LDFLAGS_vmlinux += --no-undefined
|
||||
LDFLAGS_vmlinux += -X
|
||||
# Report orphan sections
|
||||
ifdef CONFIG_LD_ORPHAN_WARN
|
||||
LDFLAGS_vmlinux += --orphan-handling=warn
|
||||
LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
|
||||
endif
|
||||
# Next argument is a linker script
|
||||
LDFLAGS_vmlinux += -T
|
||||
|
||||
@@ -18,7 +18,7 @@ config CRYPTO_GHASH_ARM_CE
|
||||
depends on KERNEL_MODE_NEON
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_CRYPTD
|
||||
select CRYPTO_GF128MUL
|
||||
select CRYPTO_LIB_GF128MUL
|
||||
help
|
||||
GCM GHASH function (NIST SP800-38D)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <crypto/aes.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
asmlinkage void __aes_arm_encrypt(u32 *rk, int rounds, const u8 *in, u8 *out);
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
/*
|
||||
* void nh_neon(const u32 *key, const u8 *message, size_t message_len,
|
||||
* u8 hash[NH_HASH_BYTES])
|
||||
* __le64 hash[NH_NUM_PASSES])
|
||||
*
|
||||
* It's guaranteed that message_len % 16 == 0.
|
||||
*/
|
||||
|
||||
@@ -14,14 +14,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len,
|
||||
u8 hash[NH_HASH_BYTES]);
|
||||
|
||||
/* wrapper to avoid indirect call to assembly, which doesn't work with CFI */
|
||||
static void _nh_neon(const u32 *key, const u8 *message, size_t message_len,
|
||||
__le64 hash[NH_NUM_PASSES])
|
||||
{
|
||||
nh_neon(key, message, message_len, (u8 *)hash);
|
||||
}
|
||||
__le64 hash[NH_NUM_PASSES]);
|
||||
|
||||
static int nhpoly1305_neon_update(struct shash_desc *desc,
|
||||
const u8 *src, unsigned int srclen)
|
||||
@@ -33,7 +26,7 @@ static int nhpoly1305_neon_update(struct shash_desc *desc,
|
||||
unsigned int n = min_t(unsigned int, srclen, SZ_4K);
|
||||
|
||||
kernel_neon_begin();
|
||||
crypto_nhpoly1305_update_helper(desc, src, n, _nh_neon);
|
||||
crypto_nhpoly1305_update_helper(desc, src, n, nh_neon);
|
||||
kernel_neon_end();
|
||||
src += n;
|
||||
srclen -= n;
|
||||
|
||||
@@ -6,8 +6,8 @@ config CRYPTO_GHASH_ARM64_CE
|
||||
tristate "Hash functions: GHASH (ARMv8 Crypto Extensions)"
|
||||
depends on KERNEL_MODE_NEON
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_GF128MUL
|
||||
select CRYPTO_LIB_AES
|
||||
select CRYPTO_LIB_GF128MUL
|
||||
select CRYPTO_AEAD
|
||||
help
|
||||
GCM GHASH function (NIST SP800-38D)
|
||||
@@ -96,6 +96,17 @@ config CRYPTO_SHA3_ARM64
|
||||
Architecture: arm64 using:
|
||||
- ARMv8.2 Crypto Extensions
|
||||
|
||||
config CRYPTO_SM3_NEON
|
||||
tristate "Hash functions: SM3 (NEON)"
|
||||
depends on KERNEL_MODE_NEON
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_SM3
|
||||
help
|
||||
SM3 (ShangMi 3) secure hash function (OSCCA GM/T 0004-2012)
|
||||
|
||||
Architecture: arm64 using:
|
||||
- NEON (Advanced SIMD) extensions
|
||||
|
||||
config CRYPTO_SM3_ARM64_CE
|
||||
tristate "Hash functions: SM3 (ARMv8.2 Crypto Extensions)"
|
||||
depends on KERNEL_MODE_NEON
|
||||
@@ -220,7 +231,7 @@ config CRYPTO_SM4_ARM64_CE
|
||||
- NEON (Advanced SIMD) extensions
|
||||
|
||||
config CRYPTO_SM4_ARM64_CE_BLK
|
||||
tristate "Ciphers: SM4, modes: ECB/CBC/CFB/CTR (ARMv8 Crypto Extensions)"
|
||||
tristate "Ciphers: SM4, modes: ECB/CBC/CFB/CTR/XTS (ARMv8 Crypto Extensions)"
|
||||
depends on KERNEL_MODE_NEON
|
||||
select CRYPTO_SKCIPHER
|
||||
select CRYPTO_SM4
|
||||
@@ -231,6 +242,8 @@ config CRYPTO_SM4_ARM64_CE_BLK
|
||||
- CBC (Cipher Block Chaining) mode (NIST SP800-38A)
|
||||
- CFB (Cipher Feedback) mode (NIST SP800-38A)
|
||||
- CTR (Counter) mode (NIST SP800-38A)
|
||||
- XTS (XOR Encrypt XOR with ciphertext stealing) mode (NIST SP800-38E
|
||||
and IEEE 1619)
|
||||
|
||||
Architecture: arm64 using:
|
||||
- ARMv8 Crypto Extensions
|
||||
@@ -268,6 +281,38 @@ config CRYPTO_AES_ARM64_CE_CCM
|
||||
- ARMv8 Crypto Extensions
|
||||
- NEON (Advanced SIMD) extensions
|
||||
|
||||
config CRYPTO_SM4_ARM64_CE_CCM
|
||||
tristate "AEAD cipher: SM4 in CCM mode (ARMv8 Crypto Extensions)"
|
||||
depends on KERNEL_MODE_NEON
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_SM4
|
||||
select CRYPTO_SM4_ARM64_CE_BLK
|
||||
help
|
||||
AEAD cipher: SM4 cipher algorithms (OSCCA GB/T 32907-2016) with
|
||||
CCM (Counter with Cipher Block Chaining-Message Authentication Code)
|
||||
authenticated encryption mode (NIST SP800-38C)
|
||||
|
||||
Architecture: arm64 using:
|
||||
- ARMv8 Crypto Extensions
|
||||
- NEON (Advanced SIMD) extensions
|
||||
|
||||
config CRYPTO_SM4_ARM64_CE_GCM
|
||||
tristate "AEAD cipher: SM4 in GCM mode (ARMv8 Crypto Extensions)"
|
||||
depends on KERNEL_MODE_NEON
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_AEAD
|
||||
select CRYPTO_SM4
|
||||
select CRYPTO_SM4_ARM64_CE_BLK
|
||||
help
|
||||
AEAD cipher: SM4 cipher algorithms (OSCCA GB/T 32907-2016) with
|
||||
GCM (Galois/Counter Mode) authenticated encryption mode (NIST SP800-38D)
|
||||
|
||||
Architecture: arm64 using:
|
||||
- ARMv8 Crypto Extensions
|
||||
- PMULL (Polynomial Multiply Long) instructions
|
||||
- NEON (Advanced SIMD) extensions
|
||||
|
||||
config CRYPTO_CRCT10DIF_ARM64_CE
|
||||
tristate "CRCT10DIF (PMULL)"
|
||||
depends on KERNEL_MODE_NEON && CRC_T10DIF
|
||||
|
||||
@@ -17,6 +17,9 @@ sha512-ce-y := sha512-ce-glue.o sha512-ce-core.o
|
||||
obj-$(CONFIG_CRYPTO_SHA3_ARM64) += sha3-ce.o
|
||||
sha3-ce-y := sha3-ce-glue.o sha3-ce-core.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SM3_NEON) += sm3-neon.o
|
||||
sm3-neon-y := sm3-neon-glue.o sm3-neon-core.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SM3_ARM64_CE) += sm3-ce.o
|
||||
sm3-ce-y := sm3-ce-glue.o sm3-ce-core.o
|
||||
|
||||
@@ -26,6 +29,12 @@ sm4-ce-cipher-y := sm4-ce-cipher-glue.o sm4-ce-cipher-core.o
|
||||
obj-$(CONFIG_CRYPTO_SM4_ARM64_CE_BLK) += sm4-ce.o
|
||||
sm4-ce-y := sm4-ce-glue.o sm4-ce-core.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SM4_ARM64_CE_CCM) += sm4-ce-ccm.o
|
||||
sm4-ce-ccm-y := sm4-ce-ccm-glue.o sm4-ce-ccm-core.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SM4_ARM64_CE_GCM) += sm4-ce-gcm.o
|
||||
sm4-ce-gcm-y := sm4-ce-gcm-glue.o sm4-ce-gcm-core.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SM4_ARM64_NEON_BLK) += sm4-neon.o
|
||||
sm4-neon-y := sm4-neon-glue.o sm4-neon-core.o
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <crypto/aes.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "aes-ce-setkey.h"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <crypto/aes.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds);
|
||||
|
||||
@@ -52,8 +52,7 @@ SYM_FUNC_END(aes_decrypt_block5x)
|
||||
*/
|
||||
|
||||
AES_FUNC_START(aes_ecb_encrypt)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
frame_push 0
|
||||
|
||||
enc_prepare w3, x2, x5
|
||||
|
||||
@@ -77,14 +76,13 @@ ST5( st1 {v4.16b}, [x0], #16 )
|
||||
subs w4, w4, #1
|
||||
bne .Lecbencloop
|
||||
.Lecbencout:
|
||||
ldp x29, x30, [sp], #16
|
||||
frame_pop
|
||||
ret
|
||||
AES_FUNC_END(aes_ecb_encrypt)
|
||||
|
||||
|
||||
AES_FUNC_START(aes_ecb_decrypt)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
frame_push 0
|
||||
|
||||
dec_prepare w3, x2, x5
|
||||
|
||||
@@ -108,7 +106,7 @@ ST5( st1 {v4.16b}, [x0], #16 )
|
||||
subs w4, w4, #1
|
||||
bne .Lecbdecloop
|
||||
.Lecbdecout:
|
||||
ldp x29, x30, [sp], #16
|
||||
frame_pop
|
||||
ret
|
||||
AES_FUNC_END(aes_ecb_decrypt)
|
||||
|
||||
@@ -171,9 +169,6 @@ AES_FUNC_END(aes_cbc_encrypt)
|
||||
AES_FUNC_END(aes_essiv_cbc_encrypt)
|
||||
|
||||
AES_FUNC_START(aes_essiv_cbc_decrypt)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
|
||||
ld1 {cbciv.16b}, [x5] /* get iv */
|
||||
|
||||
mov w8, #14 /* AES-256: 14 rounds */
|
||||
@@ -182,11 +177,9 @@ AES_FUNC_START(aes_essiv_cbc_decrypt)
|
||||
b .Lessivcbcdecstart
|
||||
|
||||
AES_FUNC_START(aes_cbc_decrypt)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
|
||||
ld1 {cbciv.16b}, [x5] /* get iv */
|
||||
.Lessivcbcdecstart:
|
||||
frame_push 0
|
||||
dec_prepare w3, x2, x6
|
||||
|
||||
.LcbcdecloopNx:
|
||||
@@ -236,7 +229,7 @@ ST5( st1 {v4.16b}, [x0], #16 )
|
||||
bne .Lcbcdecloop
|
||||
.Lcbcdecout:
|
||||
st1 {cbciv.16b}, [x5] /* return iv */
|
||||
ldp x29, x30, [sp], #16
|
||||
frame_pop
|
||||
ret
|
||||
AES_FUNC_END(aes_cbc_decrypt)
|
||||
AES_FUNC_END(aes_essiv_cbc_decrypt)
|
||||
@@ -337,8 +330,7 @@ AES_FUNC_END(aes_cbc_cts_decrypt)
|
||||
BLOCKS .req x13
|
||||
BLOCKS_W .req w13
|
||||
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
frame_push 0
|
||||
|
||||
enc_prepare ROUNDS_W, KEY, IV_PART
|
||||
ld1 {vctr.16b}, [IV]
|
||||
@@ -481,7 +473,7 @@ ST5( st1 {v4.16b}, [OUT], #16 )
|
||||
.if !\xctr
|
||||
st1 {vctr.16b}, [IV] /* return next CTR value */
|
||||
.endif
|
||||
ldp x29, x30, [sp], #16
|
||||
frame_pop
|
||||
ret
|
||||
|
||||
.Lctrtail\xctr:
|
||||
@@ -645,8 +637,7 @@ AES_FUNC_END(aes_xctr_encrypt)
|
||||
.endm
|
||||
|
||||
AES_FUNC_START(aes_xts_encrypt)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
frame_push 0
|
||||
|
||||
ld1 {v4.16b}, [x6]
|
||||
xts_load_mask v8
|
||||
@@ -704,7 +695,7 @@ AES_FUNC_START(aes_xts_encrypt)
|
||||
st1 {v0.16b}, [x0]
|
||||
.Lxtsencret:
|
||||
st1 {v4.16b}, [x6]
|
||||
ldp x29, x30, [sp], #16
|
||||
frame_pop
|
||||
ret
|
||||
|
||||
.LxtsencctsNx:
|
||||
@@ -732,8 +723,7 @@ AES_FUNC_START(aes_xts_encrypt)
|
||||
AES_FUNC_END(aes_xts_encrypt)
|
||||
|
||||
AES_FUNC_START(aes_xts_decrypt)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
frame_push 0
|
||||
|
||||
/* subtract 16 bytes if we are doing CTS */
|
||||
sub w8, w4, #0x10
|
||||
@@ -794,7 +784,7 @@ AES_FUNC_START(aes_xts_decrypt)
|
||||
b .Lxtsdecloop
|
||||
.Lxtsdecout:
|
||||
st1 {v4.16b}, [x6]
|
||||
ldp x29, x30, [sp], #16
|
||||
frame_pop
|
||||
ret
|
||||
|
||||
.Lxtsdeccts:
|
||||
|
||||
@@ -760,7 +760,7 @@ SYM_FUNC_START_LOCAL(__xts_crypt8)
|
||||
eor v6.16b, v6.16b, v31.16b
|
||||
eor v7.16b, v7.16b, v16.16b
|
||||
|
||||
stp q16, q17, [sp, #16]
|
||||
stp q16, q17, [x6]
|
||||
|
||||
mov bskey, x2
|
||||
mov rounds, x3
|
||||
@@ -768,8 +768,8 @@ SYM_FUNC_START_LOCAL(__xts_crypt8)
|
||||
SYM_FUNC_END(__xts_crypt8)
|
||||
|
||||
.macro __xts_crypt, do8, o0, o1, o2, o3, o4, o5, o6, o7
|
||||
stp x29, x30, [sp, #-48]!
|
||||
mov x29, sp
|
||||
frame_push 0, 32
|
||||
add x6, sp, #.Lframe_local_offset
|
||||
|
||||
ld1 {v25.16b}, [x5]
|
||||
|
||||
@@ -781,7 +781,7 @@ SYM_FUNC_END(__xts_crypt8)
|
||||
eor v18.16b, \o2\().16b, v27.16b
|
||||
eor v19.16b, \o3\().16b, v28.16b
|
||||
|
||||
ldp q24, q25, [sp, #16]
|
||||
ldp q24, q25, [x6]
|
||||
|
||||
eor v20.16b, \o4\().16b, v29.16b
|
||||
eor v21.16b, \o5\().16b, v30.16b
|
||||
@@ -795,7 +795,7 @@ SYM_FUNC_END(__xts_crypt8)
|
||||
b.gt 0b
|
||||
|
||||
st1 {v25.16b}, [x5]
|
||||
ldp x29, x30, [sp], #48
|
||||
frame_pop
|
||||
ret
|
||||
.endm
|
||||
|
||||
@@ -820,9 +820,7 @@ SYM_FUNC_END(aesbs_xts_decrypt)
|
||||
* int rounds, int blocks, u8 iv[])
|
||||
*/
|
||||
SYM_FUNC_START(aesbs_ctr_encrypt)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
|
||||
frame_push 0
|
||||
ldp x7, x8, [x5]
|
||||
ld1 {v0.16b}, [x5]
|
||||
CPU_LE( rev x7, x7 )
|
||||
@@ -862,6 +860,6 @@ CPU_LE( rev x8, x8 )
|
||||
b.gt 0b
|
||||
|
||||
st1 {v0.16b}, [x5]
|
||||
ldp x29, x30, [sp], #16
|
||||
frame_pop
|
||||
ret
|
||||
SYM_FUNC_END(aesbs_ctr_encrypt)
|
||||
|
||||
@@ -429,7 +429,7 @@ CPU_LE( ext v0.16b, v0.16b, v0.16b, #8 )
|
||||
|
||||
umov w0, v0.h[0]
|
||||
.ifc \p, p8
|
||||
ldp x29, x30, [sp], #16
|
||||
frame_pop
|
||||
.endif
|
||||
ret
|
||||
|
||||
@@ -466,8 +466,7 @@ CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 )
|
||||
// Assumes len >= 16.
|
||||
//
|
||||
SYM_FUNC_START(crc_t10dif_pmull_p8)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
frame_push 1
|
||||
crc_t10dif_pmull p8
|
||||
SYM_FUNC_END(crc_t10dif_pmull_p8)
|
||||
|
||||
|
||||
@@ -436,9 +436,7 @@ SYM_FUNC_END(pmull_ghash_update_p8)
|
||||
|
||||
.align 6
|
||||
.macro pmull_gcm_do_crypt, enc
|
||||
stp x29, x30, [sp, #-32]!
|
||||
mov x29, sp
|
||||
str x19, [sp, #24]
|
||||
frame_push 1
|
||||
|
||||
load_round_keys x7, x6, x8
|
||||
|
||||
@@ -529,7 +527,7 @@ CPU_LE( rev w8, w8 )
|
||||
.endif
|
||||
bne 0b
|
||||
|
||||
3: ldp x19, x10, [sp, #24]
|
||||
3: ldr x10, [sp, #.Lframe_local_offset]
|
||||
cbz x10, 5f // output tag?
|
||||
|
||||
ld1 {INP3.16b}, [x10] // load lengths[]
|
||||
@@ -562,7 +560,7 @@ CPU_LE( rev w8, w8 )
|
||||
smov w0, v0.b[0] // return b0
|
||||
.endif
|
||||
|
||||
4: ldp x29, x30, [sp], #32
|
||||
4: frame_pop
|
||||
ret
|
||||
|
||||
5:
|
||||
|
||||
@@ -508,7 +508,7 @@ static void __exit ghash_ce_mod_exit(void)
|
||||
crypto_unregister_shash(&ghash_alg);
|
||||
}
|
||||
|
||||
static const struct cpu_feature ghash_cpu_feature[] = {
|
||||
static const struct cpu_feature __maybe_unused ghash_cpu_feature[] = {
|
||||
{ cpu_feature(PMULL) }, { }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(cpu, ghash_cpu_feature);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/cfi_types.h>
|
||||
|
||||
KEY .req x0
|
||||
MESSAGE .req x1
|
||||
@@ -58,11 +59,11 @@
|
||||
|
||||
/*
|
||||
* void nh_neon(const u32 *key, const u8 *message, size_t message_len,
|
||||
* u8 hash[NH_HASH_BYTES])
|
||||
* __le64 hash[NH_NUM_PASSES])
|
||||
*
|
||||
* It's guaranteed that message_len % 16 == 0.
|
||||
*/
|
||||
SYM_FUNC_START(nh_neon)
|
||||
SYM_TYPED_FUNC_START(nh_neon)
|
||||
|
||||
ld1 {K0.4s,K1.4s}, [KEY], #32
|
||||
movi PASS0_SUMS.2d, #0
|
||||
|
||||
@@ -14,14 +14,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len,
|
||||
u8 hash[NH_HASH_BYTES]);
|
||||
|
||||
/* wrapper to avoid indirect call to assembly, which doesn't work with CFI */
|
||||
static void _nh_neon(const u32 *key, const u8 *message, size_t message_len,
|
||||
__le64 hash[NH_NUM_PASSES])
|
||||
{
|
||||
nh_neon(key, message, message_len, (u8 *)hash);
|
||||
}
|
||||
__le64 hash[NH_NUM_PASSES]);
|
||||
|
||||
static int nhpoly1305_neon_update(struct shash_desc *desc,
|
||||
const u8 *src, unsigned int srclen)
|
||||
@@ -33,7 +26,7 @@ static int nhpoly1305_neon_update(struct shash_desc *desc,
|
||||
unsigned int n = min_t(unsigned int, srclen, SZ_4K);
|
||||
|
||||
kernel_neon_begin();
|
||||
crypto_nhpoly1305_update_helper(desc, src, n, _nh_neon);
|
||||
crypto_nhpoly1305_update_helper(desc, src, n, nh_neon);
|
||||
kernel_neon_end();
|
||||
src += n;
|
||||
srclen -= n;
|
||||
|
||||
@@ -84,7 +84,7 @@ static struct shash_alg sm3_alg = {
|
||||
.base.cra_driver_name = "sm3-ce",
|
||||
.base.cra_blocksize = SM3_BLOCK_SIZE,
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.base.cra_priority = 200,
|
||||
.base.cra_priority = 400,
|
||||
};
|
||||
|
||||
static int __init sm3_ce_mod_init(void)
|
||||
|
||||
@@ -0,0 +1,601 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* sm3-neon-core.S - SM3 secure hash using NEON instructions
|
||||
*
|
||||
* Linux/arm64 port of the libgcrypt SM3 implementation for AArch64
|
||||
*
|
||||
* Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
|
||||
* Copyright (c) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/cfi_types.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
/* Context structure */
|
||||
|
||||
#define state_h0 0
|
||||
#define state_h1 4
|
||||
#define state_h2 8
|
||||
#define state_h3 12
|
||||
#define state_h4 16
|
||||
#define state_h5 20
|
||||
#define state_h6 24
|
||||
#define state_h7 28
|
||||
|
||||
/* Stack structure */
|
||||
|
||||
#define STACK_W_SIZE (32 * 2 * 3)
|
||||
|
||||
#define STACK_W (0)
|
||||
#define STACK_SIZE (STACK_W + STACK_W_SIZE)
|
||||
|
||||
/* Register macros */
|
||||
|
||||
#define RSTATE x0
|
||||
#define RDATA x1
|
||||
#define RNBLKS x2
|
||||
#define RKPTR x28
|
||||
#define RFRAME x29
|
||||
|
||||
#define ra w3
|
||||
#define rb w4
|
||||
#define rc w5
|
||||
#define rd w6
|
||||
#define re w7
|
||||
#define rf w8
|
||||
#define rg w9
|
||||
#define rh w10
|
||||
|
||||
#define t0 w11
|
||||
#define t1 w12
|
||||
#define t2 w13
|
||||
#define t3 w14
|
||||
#define t4 w15
|
||||
#define t5 w16
|
||||
#define t6 w17
|
||||
|
||||
#define k_even w19
|
||||
#define k_odd w20
|
||||
|
||||
#define addr0 x21
|
||||
#define addr1 x22
|
||||
|
||||
#define s0 w23
|
||||
#define s1 w24
|
||||
#define s2 w25
|
||||
#define s3 w26
|
||||
|
||||
#define W0 v0
|
||||
#define W1 v1
|
||||
#define W2 v2
|
||||
#define W3 v3
|
||||
#define W4 v4
|
||||
#define W5 v5
|
||||
|
||||
#define XTMP0 v6
|
||||
#define XTMP1 v7
|
||||
#define XTMP2 v16
|
||||
#define XTMP3 v17
|
||||
#define XTMP4 v18
|
||||
#define XTMP5 v19
|
||||
#define XTMP6 v20
|
||||
|
||||
/* Helper macros. */
|
||||
|
||||
#define _(...) /*_*/
|
||||
|
||||
#define clear_vec(x) \
|
||||
movi x.8h, #0;
|
||||
|
||||
#define rolw(o, a, n) \
|
||||
ror o, a, #(32 - n);
|
||||
|
||||
/* Round function macros. */
|
||||
|
||||
#define GG1_1(x, y, z, o, t) \
|
||||
eor o, x, y;
|
||||
#define GG1_2(x, y, z, o, t) \
|
||||
eor o, o, z;
|
||||
#define GG1_3(x, y, z, o, t)
|
||||
|
||||
#define FF1_1(x, y, z, o, t) GG1_1(x, y, z, o, t)
|
||||
#define FF1_2(x, y, z, o, t)
|
||||
#define FF1_3(x, y, z, o, t) GG1_2(x, y, z, o, t)
|
||||
|
||||
#define GG2_1(x, y, z, o, t) \
|
||||
bic o, z, x;
|
||||
#define GG2_2(x, y, z, o, t) \
|
||||
and t, y, x;
|
||||
#define GG2_3(x, y, z, o, t) \
|
||||
eor o, o, t;
|
||||
|
||||
#define FF2_1(x, y, z, o, t) \
|
||||
eor o, x, y;
|
||||
#define FF2_2(x, y, z, o, t) \
|
||||
and t, x, y; \
|
||||
and o, o, z;
|
||||
#define FF2_3(x, y, z, o, t) \
|
||||
eor o, o, t;
|
||||
|
||||
#define R(i, a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \
|
||||
K_LOAD(round); \
|
||||
ldr t5, [sp, #(wtype##_W1_ADDR(round, widx))]; \
|
||||
rolw(t0, a, 12); /* rol(a, 12) => t0 */ \
|
||||
IOP(1, iop_param); \
|
||||
FF##i##_1(a, b, c, t1, t2); \
|
||||
ldr t6, [sp, #(wtype##_W1W2_ADDR(round, widx))]; \
|
||||
add k, k, e; \
|
||||
IOP(2, iop_param); \
|
||||
GG##i##_1(e, f, g, t3, t4); \
|
||||
FF##i##_2(a, b, c, t1, t2); \
|
||||
IOP(3, iop_param); \
|
||||
add k, k, t0; \
|
||||
add h, h, t5; \
|
||||
add d, d, t6; /* w1w2 + d => d */ \
|
||||
IOP(4, iop_param); \
|
||||
rolw(k, k, 7); /* rol (t0 + e + t), 7) => k */ \
|
||||
GG##i##_2(e, f, g, t3, t4); \
|
||||
add h, h, k; /* h + w1 + k => h */ \
|
||||
IOP(5, iop_param); \
|
||||
FF##i##_3(a, b, c, t1, t2); \
|
||||
eor t0, t0, k; /* k ^ t0 => t0 */ \
|
||||
GG##i##_3(e, f, g, t3, t4); \
|
||||
add d, d, t1; /* FF(a,b,c) + d => d */ \
|
||||
IOP(6, iop_param); \
|
||||
add t3, t3, h; /* GG(e,f,g) + h => t3 */ \
|
||||
rolw(b, b, 9); /* rol(b, 9) => b */ \
|
||||
eor h, t3, t3, ror #(32-9); \
|
||||
IOP(7, iop_param); \
|
||||
add d, d, t0; /* t0 + d => d */ \
|
||||
rolw(f, f, 19); /* rol(f, 19) => f */ \
|
||||
IOP(8, iop_param); \
|
||||
eor h, h, t3, ror #(32-17); /* P0(t3) => h */
|
||||
|
||||
#define R1(a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \
|
||||
R(1, ##a, ##b, ##c, ##d, ##e, ##f, ##g, ##h, ##k, K_LOAD, round, widx, wtype, IOP, iop_param)
|
||||
|
||||
#define R2(a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \
|
||||
R(2, ##a, ##b, ##c, ##d, ##e, ##f, ##g, ##h, ##k, K_LOAD, round, widx, wtype, IOP, iop_param)
|
||||
|
||||
#define KL(round) \
|
||||
ldp k_even, k_odd, [RKPTR, #(4*(round))];
|
||||
|
||||
/* Input expansion macros. */
|
||||
|
||||
/* Byte-swapped input address. */
|
||||
#define IW_W_ADDR(round, widx, offs) \
|
||||
(STACK_W + ((round) / 4) * 64 + (offs) + ((widx) * 4))
|
||||
|
||||
/* Expanded input address. */
|
||||
#define XW_W_ADDR(round, widx, offs) \
|
||||
(STACK_W + ((((round) / 3) - 4) % 2) * 64 + (offs) + ((widx) * 4))
|
||||
|
||||
/* Rounds 1-12, byte-swapped input block addresses. */
|
||||
#define IW_W1_ADDR(round, widx) IW_W_ADDR(round, widx, 32)
|
||||
#define IW_W1W2_ADDR(round, widx) IW_W_ADDR(round, widx, 48)
|
||||
|
||||
/* Rounds 1-12, expanded input block addresses. */
|
||||
#define XW_W1_ADDR(round, widx) XW_W_ADDR(round, widx, 0)
|
||||
#define XW_W1W2_ADDR(round, widx) XW_W_ADDR(round, widx, 16)
|
||||
|
||||
/* Input block loading.
|
||||
* Interleaving within round function needed for in-order CPUs. */
|
||||
#define LOAD_W_VEC_1_1() \
|
||||
add addr0, sp, #IW_W1_ADDR(0, 0);
|
||||
#define LOAD_W_VEC_1_2() \
|
||||
add addr1, sp, #IW_W1_ADDR(4, 0);
|
||||
#define LOAD_W_VEC_1_3() \
|
||||
ld1 {W0.16b}, [RDATA], #16;
|
||||
#define LOAD_W_VEC_1_4() \
|
||||
ld1 {W1.16b}, [RDATA], #16;
|
||||
#define LOAD_W_VEC_1_5() \
|
||||
ld1 {W2.16b}, [RDATA], #16;
|
||||
#define LOAD_W_VEC_1_6() \
|
||||
ld1 {W3.16b}, [RDATA], #16;
|
||||
#define LOAD_W_VEC_1_7() \
|
||||
rev32 XTMP0.16b, W0.16b;
|
||||
#define LOAD_W_VEC_1_8() \
|
||||
rev32 XTMP1.16b, W1.16b;
|
||||
#define LOAD_W_VEC_2_1() \
|
||||
rev32 XTMP2.16b, W2.16b;
|
||||
#define LOAD_W_VEC_2_2() \
|
||||
rev32 XTMP3.16b, W3.16b;
|
||||
#define LOAD_W_VEC_2_3() \
|
||||
eor XTMP4.16b, XTMP1.16b, XTMP0.16b;
|
||||
#define LOAD_W_VEC_2_4() \
|
||||
eor XTMP5.16b, XTMP2.16b, XTMP1.16b;
|
||||
#define LOAD_W_VEC_2_5() \
|
||||
st1 {XTMP0.16b}, [addr0], #16;
|
||||
#define LOAD_W_VEC_2_6() \
|
||||
st1 {XTMP4.16b}, [addr0]; \
|
||||
add addr0, sp, #IW_W1_ADDR(8, 0);
|
||||
#define LOAD_W_VEC_2_7() \
|
||||
eor XTMP6.16b, XTMP3.16b, XTMP2.16b;
|
||||
#define LOAD_W_VEC_2_8() \
|
||||
ext W0.16b, XTMP0.16b, XTMP0.16b, #8; /* W0: xx, w0, xx, xx */
|
||||
#define LOAD_W_VEC_3_1() \
|
||||
mov W2.16b, XTMP1.16b; /* W2: xx, w6, w5, w4 */
|
||||
#define LOAD_W_VEC_3_2() \
|
||||
st1 {XTMP1.16b}, [addr1], #16;
|
||||
#define LOAD_W_VEC_3_3() \
|
||||
st1 {XTMP5.16b}, [addr1]; \
|
||||
ext W1.16b, XTMP0.16b, XTMP0.16b, #4; /* W1: xx, w3, w2, w1 */
|
||||
#define LOAD_W_VEC_3_4() \
|
||||
ext W3.16b, XTMP1.16b, XTMP2.16b, #12; /* W3: xx, w9, w8, w7 */
|
||||
#define LOAD_W_VEC_3_5() \
|
||||
ext W4.16b, XTMP2.16b, XTMP3.16b, #8; /* W4: xx, w12, w11, w10 */
|
||||
#define LOAD_W_VEC_3_6() \
|
||||
st1 {XTMP2.16b}, [addr0], #16;
|
||||
#define LOAD_W_VEC_3_7() \
|
||||
st1 {XTMP6.16b}, [addr0];
|
||||
#define LOAD_W_VEC_3_8() \
|
||||
ext W5.16b, XTMP3.16b, XTMP3.16b, #4; /* W5: xx, w15, w14, w13 */
|
||||
|
||||
#define LOAD_W_VEC_1(iop_num, ...) \
|
||||
LOAD_W_VEC_1_##iop_num()
|
||||
#define LOAD_W_VEC_2(iop_num, ...) \
|
||||
LOAD_W_VEC_2_##iop_num()
|
||||
#define LOAD_W_VEC_3(iop_num, ...) \
|
||||
LOAD_W_VEC_3_##iop_num()
|
||||
|
||||
/* Message scheduling. Note: 3 words per vector register.
|
||||
* Interleaving within round function needed for in-order CPUs. */
|
||||
#define SCHED_W_1_1(round, w0, w1, w2, w3, w4, w5) \
|
||||
/* Load (w[i - 16]) => XTMP0 */ \
|
||||
/* Load (w[i - 13]) => XTMP5 */ \
|
||||
ext XTMP0.16b, w0.16b, w0.16b, #12; /* XTMP0: w0, xx, xx, xx */
|
||||
#define SCHED_W_1_2(round, w0, w1, w2, w3, w4, w5) \
|
||||
ext XTMP5.16b, w1.16b, w1.16b, #12;
|
||||
#define SCHED_W_1_3(round, w0, w1, w2, w3, w4, w5) \
|
||||
ext XTMP0.16b, XTMP0.16b, w1.16b, #12; /* XTMP0: xx, w2, w1, w0 */
|
||||
#define SCHED_W_1_4(round, w0, w1, w2, w3, w4, w5) \
|
||||
ext XTMP5.16b, XTMP5.16b, w2.16b, #12;
|
||||
#define SCHED_W_1_5(round, w0, w1, w2, w3, w4, w5) \
|
||||
/* w[i - 9] == w3 */ \
|
||||
/* W3 ^ XTMP0 => XTMP0 */ \
|
||||
eor XTMP0.16b, XTMP0.16b, w3.16b;
|
||||
#define SCHED_W_1_6(round, w0, w1, w2, w3, w4, w5) \
|
||||
/* w[i - 3] == w5 */ \
|
||||
/* rol(XMM5, 15) ^ XTMP0 => XTMP0 */ \
|
||||
/* rol(XTMP5, 7) => XTMP1 */ \
|
||||
add addr0, sp, #XW_W1_ADDR((round), 0); \
|
||||
shl XTMP2.4s, w5.4s, #15;
|
||||
#define SCHED_W_1_7(round, w0, w1, w2, w3, w4, w5) \
|
||||
shl XTMP1.4s, XTMP5.4s, #7;
|
||||
#define SCHED_W_1_8(round, w0, w1, w2, w3, w4, w5) \
|
||||
sri XTMP2.4s, w5.4s, #(32-15);
|
||||
#define SCHED_W_2_1(round, w0, w1, w2, w3, w4, w5) \
|
||||
sri XTMP1.4s, XTMP5.4s, #(32-7);
|
||||
#define SCHED_W_2_2(round, w0, w1, w2, w3, w4, w5) \
|
||||
eor XTMP0.16b, XTMP0.16b, XTMP2.16b;
|
||||
#define SCHED_W_2_3(round, w0, w1, w2, w3, w4, w5) \
|
||||
/* w[i - 6] == W4 */ \
|
||||
/* W4 ^ XTMP1 => XTMP1 */ \
|
||||
eor XTMP1.16b, XTMP1.16b, w4.16b;
|
||||
#define SCHED_W_2_4(round, w0, w1, w2, w3, w4, w5) \
|
||||
/* P1(XTMP0) ^ XTMP1 => W0 */ \
|
||||
shl XTMP3.4s, XTMP0.4s, #15;
|
||||
#define SCHED_W_2_5(round, w0, w1, w2, w3, w4, w5) \
|
||||
shl XTMP4.4s, XTMP0.4s, #23;
|
||||
#define SCHED_W_2_6(round, w0, w1, w2, w3, w4, w5) \
|
||||
eor w0.16b, XTMP1.16b, XTMP0.16b;
|
||||
#define SCHED_W_2_7(round, w0, w1, w2, w3, w4, w5) \
|
||||
sri XTMP3.4s, XTMP0.4s, #(32-15);
|
||||
#define SCHED_W_2_8(round, w0, w1, w2, w3, w4, w5) \
|
||||
sri XTMP4.4s, XTMP0.4s, #(32-23);
|
||||
#define SCHED_W_3_1(round, w0, w1, w2, w3, w4, w5) \
|
||||
eor w0.16b, w0.16b, XTMP3.16b;
|
||||
#define SCHED_W_3_2(round, w0, w1, w2, w3, w4, w5) \
|
||||
/* Load (w[i - 3]) => XTMP2 */ \
|
||||
ext XTMP2.16b, w4.16b, w4.16b, #12;
|
||||
#define SCHED_W_3_3(round, w0, w1, w2, w3, w4, w5) \
|
||||
eor w0.16b, w0.16b, XTMP4.16b;
|
||||
#define SCHED_W_3_4(round, w0, w1, w2, w3, w4, w5) \
|
||||
ext XTMP2.16b, XTMP2.16b, w5.16b, #12;
|
||||
#define SCHED_W_3_5(round, w0, w1, w2, w3, w4, w5) \
|
||||
/* W1 ^ W2 => XTMP3 */ \
|
||||
eor XTMP3.16b, XTMP2.16b, w0.16b;
|
||||
#define SCHED_W_3_6(round, w0, w1, w2, w3, w4, w5)
|
||||
#define SCHED_W_3_7(round, w0, w1, w2, w3, w4, w5) \
|
||||
st1 {XTMP2.16b-XTMP3.16b}, [addr0];
|
||||
#define SCHED_W_3_8(round, w0, w1, w2, w3, w4, w5)
|
||||
|
||||
#define SCHED_W_W0W1W2W3W4W5_1(iop_num, round) \
|
||||
SCHED_W_1_##iop_num(round, W0, W1, W2, W3, W4, W5)
|
||||
#define SCHED_W_W0W1W2W3W4W5_2(iop_num, round) \
|
||||
SCHED_W_2_##iop_num(round, W0, W1, W2, W3, W4, W5)
|
||||
#define SCHED_W_W0W1W2W3W4W5_3(iop_num, round) \
|
||||
SCHED_W_3_##iop_num(round, W0, W1, W2, W3, W4, W5)
|
||||
|
||||
#define SCHED_W_W1W2W3W4W5W0_1(iop_num, round) \
|
||||
SCHED_W_1_##iop_num(round, W1, W2, W3, W4, W5, W0)
|
||||
#define SCHED_W_W1W2W3W4W5W0_2(iop_num, round) \
|
||||
SCHED_W_2_##iop_num(round, W1, W2, W3, W4, W5, W0)
|
||||
#define SCHED_W_W1W2W3W4W5W0_3(iop_num, round) \
|
||||
SCHED_W_3_##iop_num(round, W1, W2, W3, W4, W5, W0)
|
||||
|
||||
#define SCHED_W_W2W3W4W5W0W1_1(iop_num, round) \
|
||||
SCHED_W_1_##iop_num(round, W2, W3, W4, W5, W0, W1)
|
||||
#define SCHED_W_W2W3W4W5W0W1_2(iop_num, round) \
|
||||
SCHED_W_2_##iop_num(round, W2, W3, W4, W5, W0, W1)
|
||||
#define SCHED_W_W2W3W4W5W0W1_3(iop_num, round) \
|
||||
SCHED_W_3_##iop_num(round, W2, W3, W4, W5, W0, W1)
|
||||
|
||||
#define SCHED_W_W3W4W5W0W1W2_1(iop_num, round) \
|
||||
SCHED_W_1_##iop_num(round, W3, W4, W5, W0, W1, W2)
|
||||
#define SCHED_W_W3W4W5W0W1W2_2(iop_num, round) \
|
||||
SCHED_W_2_##iop_num(round, W3, W4, W5, W0, W1, W2)
|
||||
#define SCHED_W_W3W4W5W0W1W2_3(iop_num, round) \
|
||||
SCHED_W_3_##iop_num(round, W3, W4, W5, W0, W1, W2)
|
||||
|
||||
#define SCHED_W_W4W5W0W1W2W3_1(iop_num, round) \
|
||||
SCHED_W_1_##iop_num(round, W4, W5, W0, W1, W2, W3)
|
||||
#define SCHED_W_W4W5W0W1W2W3_2(iop_num, round) \
|
||||
SCHED_W_2_##iop_num(round, W4, W5, W0, W1, W2, W3)
|
||||
#define SCHED_W_W4W5W0W1W2W3_3(iop_num, round) \
|
||||
SCHED_W_3_##iop_num(round, W4, W5, W0, W1, W2, W3)
|
||||
|
||||
#define SCHED_W_W5W0W1W2W3W4_1(iop_num, round) \
|
||||
SCHED_W_1_##iop_num(round, W5, W0, W1, W2, W3, W4)
|
||||
#define SCHED_W_W5W0W1W2W3W4_2(iop_num, round) \
|
||||
SCHED_W_2_##iop_num(round, W5, W0, W1, W2, W3, W4)
|
||||
#define SCHED_W_W5W0W1W2W3W4_3(iop_num, round) \
|
||||
SCHED_W_3_##iop_num(round, W5, W0, W1, W2, W3, W4)
|
||||
|
||||
|
||||
/*
|
||||
* Transform blocks*64 bytes (blocks*16 32-bit words) at 'src'.
|
||||
*
|
||||
* void sm3_neon_transform(struct sm3_state *sst, u8 const *src,
|
||||
* int blocks)
|
||||
*/
|
||||
.text
|
||||
.align 3
|
||||
SYM_TYPED_FUNC_START(sm3_neon_transform)
|
||||
ldp ra, rb, [RSTATE, #0]
|
||||
ldp rc, rd, [RSTATE, #8]
|
||||
ldp re, rf, [RSTATE, #16]
|
||||
ldp rg, rh, [RSTATE, #24]
|
||||
|
||||
stp x28, x29, [sp, #-16]!
|
||||
stp x19, x20, [sp, #-16]!
|
||||
stp x21, x22, [sp, #-16]!
|
||||
stp x23, x24, [sp, #-16]!
|
||||
stp x25, x26, [sp, #-16]!
|
||||
mov RFRAME, sp
|
||||
|
||||
sub addr0, sp, #STACK_SIZE
|
||||
adr_l RKPTR, .LKtable
|
||||
and sp, addr0, #(~63)
|
||||
|
||||
/* Preload first block. */
|
||||
LOAD_W_VEC_1(1, 0)
|
||||
LOAD_W_VEC_1(2, 0)
|
||||
LOAD_W_VEC_1(3, 0)
|
||||
LOAD_W_VEC_1(4, 0)
|
||||
LOAD_W_VEC_1(5, 0)
|
||||
LOAD_W_VEC_1(6, 0)
|
||||
LOAD_W_VEC_1(7, 0)
|
||||
LOAD_W_VEC_1(8, 0)
|
||||
LOAD_W_VEC_2(1, 0)
|
||||
LOAD_W_VEC_2(2, 0)
|
||||
LOAD_W_VEC_2(3, 0)
|
||||
LOAD_W_VEC_2(4, 0)
|
||||
LOAD_W_VEC_2(5, 0)
|
||||
LOAD_W_VEC_2(6, 0)
|
||||
LOAD_W_VEC_2(7, 0)
|
||||
LOAD_W_VEC_2(8, 0)
|
||||
LOAD_W_VEC_3(1, 0)
|
||||
LOAD_W_VEC_3(2, 0)
|
||||
LOAD_W_VEC_3(3, 0)
|
||||
LOAD_W_VEC_3(4, 0)
|
||||
LOAD_W_VEC_3(5, 0)
|
||||
LOAD_W_VEC_3(6, 0)
|
||||
LOAD_W_VEC_3(7, 0)
|
||||
LOAD_W_VEC_3(8, 0)
|
||||
|
||||
.balign 16
|
||||
.Loop:
|
||||
/* Transform 0-3 */
|
||||
R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 0, 0, IW, _, 0)
|
||||
R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 1, 1, IW, _, 0)
|
||||
R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 2, 2, IW, _, 0)
|
||||
R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 3, 3, IW, _, 0)
|
||||
|
||||
/* Transform 4-7 + Precalc 12-14 */
|
||||
R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 4, 0, IW, _, 0)
|
||||
R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 5, 1, IW, _, 0)
|
||||
R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 6, 2, IW, SCHED_W_W0W1W2W3W4W5_1, 12)
|
||||
R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 7, 3, IW, SCHED_W_W0W1W2W3W4W5_2, 12)
|
||||
|
||||
/* Transform 8-11 + Precalc 12-17 */
|
||||
R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 8, 0, IW, SCHED_W_W0W1W2W3W4W5_3, 12)
|
||||
R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 9, 1, IW, SCHED_W_W1W2W3W4W5W0_1, 15)
|
||||
R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 10, 2, IW, SCHED_W_W1W2W3W4W5W0_2, 15)
|
||||
R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 11, 3, IW, SCHED_W_W1W2W3W4W5W0_3, 15)
|
||||
|
||||
/* Transform 12-14 + Precalc 18-20 */
|
||||
R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 12, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 18)
|
||||
R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 13, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 18)
|
||||
R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 14, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 18)
|
||||
|
||||
/* Transform 15-17 + Precalc 21-23 */
|
||||
R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 15, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 21)
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 16, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 21)
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 17, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 21)
|
||||
|
||||
/* Transform 18-20 + Precalc 24-26 */
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 18, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 24)
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 19, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 24)
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 20, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 24)
|
||||
|
||||
/* Transform 21-23 + Precalc 27-29 */
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 21, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 27)
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 22, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 27)
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 23, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 27)
|
||||
|
||||
/* Transform 24-26 + Precalc 30-32 */
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 24, 0, XW, SCHED_W_W0W1W2W3W4W5_1, 30)
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 25, 1, XW, SCHED_W_W0W1W2W3W4W5_2, 30)
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 26, 2, XW, SCHED_W_W0W1W2W3W4W5_3, 30)
|
||||
|
||||
/* Transform 27-29 + Precalc 33-35 */
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 27, 0, XW, SCHED_W_W1W2W3W4W5W0_1, 33)
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 28, 1, XW, SCHED_W_W1W2W3W4W5W0_2, 33)
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 29, 2, XW, SCHED_W_W1W2W3W4W5W0_3, 33)
|
||||
|
||||
/* Transform 30-32 + Precalc 36-38 */
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 30, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 36)
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 31, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 36)
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 32, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 36)
|
||||
|
||||
/* Transform 33-35 + Precalc 39-41 */
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 33, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 39)
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 34, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 39)
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 35, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 39)
|
||||
|
||||
/* Transform 36-38 + Precalc 42-44 */
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 36, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 42)
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 37, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 42)
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 38, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 42)
|
||||
|
||||
/* Transform 39-41 + Precalc 45-47 */
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 39, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 45)
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 40, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 45)
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 41, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 45)
|
||||
|
||||
/* Transform 42-44 + Precalc 48-50 */
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 42, 0, XW, SCHED_W_W0W1W2W3W4W5_1, 48)
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 43, 1, XW, SCHED_W_W0W1W2W3W4W5_2, 48)
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 44, 2, XW, SCHED_W_W0W1W2W3W4W5_3, 48)
|
||||
|
||||
/* Transform 45-47 + Precalc 51-53 */
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 45, 0, XW, SCHED_W_W1W2W3W4W5W0_1, 51)
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 46, 1, XW, SCHED_W_W1W2W3W4W5W0_2, 51)
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 47, 2, XW, SCHED_W_W1W2W3W4W5W0_3, 51)
|
||||
|
||||
/* Transform 48-50 + Precalc 54-56 */
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 48, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 54)
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 49, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 54)
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 50, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 54)
|
||||
|
||||
/* Transform 51-53 + Precalc 57-59 */
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 51, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 57)
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 52, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 57)
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 53, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 57)
|
||||
|
||||
/* Transform 54-56 + Precalc 60-62 */
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 54, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 60)
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 55, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 60)
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 56, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 60)
|
||||
|
||||
/* Transform 57-59 + Precalc 63 */
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 57, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 63)
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 58, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 63)
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 59, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 63)
|
||||
|
||||
/* Transform 60 */
|
||||
R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 60, 0, XW, _, _)
|
||||
subs RNBLKS, RNBLKS, #1
|
||||
b.eq .Lend
|
||||
|
||||
/* Transform 61-63 + Preload next block */
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 61, 1, XW, LOAD_W_VEC_1, _)
|
||||
ldp s0, s1, [RSTATE, #0]
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 62, 2, XW, LOAD_W_VEC_2, _)
|
||||
ldp s2, s3, [RSTATE, #8]
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 63, 0, XW, LOAD_W_VEC_3, _)
|
||||
|
||||
/* Update the chaining variables. */
|
||||
eor ra, ra, s0
|
||||
eor rb, rb, s1
|
||||
ldp s0, s1, [RSTATE, #16]
|
||||
eor rc, rc, s2
|
||||
ldp k_even, k_odd, [RSTATE, #24]
|
||||
eor rd, rd, s3
|
||||
eor re, re, s0
|
||||
stp ra, rb, [RSTATE, #0]
|
||||
eor rf, rf, s1
|
||||
stp rc, rd, [RSTATE, #8]
|
||||
eor rg, rg, k_even
|
||||
stp re, rf, [RSTATE, #16]
|
||||
eor rh, rh, k_odd
|
||||
stp rg, rh, [RSTATE, #24]
|
||||
b .Loop
|
||||
|
||||
.Lend:
|
||||
/* Transform 61-63 */
|
||||
R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd, _, 61, 1, XW, _, _)
|
||||
ldp s0, s1, [RSTATE, #0]
|
||||
R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 62, 2, XW, _, _)
|
||||
ldp s2, s3, [RSTATE, #8]
|
||||
R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd, _, 63, 0, XW, _, _)
|
||||
|
||||
/* Update the chaining variables. */
|
||||
eor ra, ra, s0
|
||||
clear_vec(W0)
|
||||
eor rb, rb, s1
|
||||
clear_vec(W1)
|
||||
ldp s0, s1, [RSTATE, #16]
|
||||
clear_vec(W2)
|
||||
eor rc, rc, s2
|
||||
clear_vec(W3)
|
||||
ldp k_even, k_odd, [RSTATE, #24]
|
||||
clear_vec(W4)
|
||||
eor rd, rd, s3
|
||||
clear_vec(W5)
|
||||
eor re, re, s0
|
||||
clear_vec(XTMP0)
|
||||
stp ra, rb, [RSTATE, #0]
|
||||
clear_vec(XTMP1)
|
||||
eor rf, rf, s1
|
||||
clear_vec(XTMP2)
|
||||
stp rc, rd, [RSTATE, #8]
|
||||
clear_vec(XTMP3)
|
||||
eor rg, rg, k_even
|
||||
clear_vec(XTMP4)
|
||||
stp re, rf, [RSTATE, #16]
|
||||
clear_vec(XTMP5)
|
||||
eor rh, rh, k_odd
|
||||
clear_vec(XTMP6)
|
||||
stp rg, rh, [RSTATE, #24]
|
||||
|
||||
/* Clear message expansion area */
|
||||
add addr0, sp, #STACK_W
|
||||
st1 {W0.16b-W3.16b}, [addr0], #64
|
||||
st1 {W0.16b-W3.16b}, [addr0], #64
|
||||
st1 {W0.16b-W3.16b}, [addr0]
|
||||
|
||||
mov sp, RFRAME
|
||||
|
||||
ldp x25, x26, [sp], #16
|
||||
ldp x23, x24, [sp], #16
|
||||
ldp x21, x22, [sp], #16
|
||||
ldp x19, x20, [sp], #16
|
||||
ldp x28, x29, [sp], #16
|
||||
|
||||
ret
|
||||
SYM_FUNC_END(sm3_neon_transform)
|
||||
|
||||
|
||||
.section ".rodata", "a"
|
||||
|
||||
.align 4
|
||||
.LKtable:
|
||||
.long 0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb
|
||||
.long 0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc
|
||||
.long 0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce
|
||||
.long 0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6
|
||||
.long 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c
|
||||
.long 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce
|
||||
.long 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec
|
||||
.long 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5
|
||||
.long 0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53
|
||||
.long 0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d
|
||||
.long 0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4
|
||||
.long 0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43
|
||||
.long 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c
|
||||
.long 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce
|
||||
.long 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec
|
||||
.long 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5
|
||||
@@ -0,0 +1,103 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* sm3-neon-glue.c - SM3 secure hash using NEON instructions
|
||||
*
|
||||
* Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
|
||||
*/
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <crypto/sm3.h>
|
||||
#include <crypto/sm3_base.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
|
||||
asmlinkage void sm3_neon_transform(struct sm3_state *sst, u8 const *src,
|
||||
int blocks);
|
||||
|
||||
static int sm3_neon_update(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int len)
|
||||
{
|
||||
if (!crypto_simd_usable()) {
|
||||
sm3_update(shash_desc_ctx(desc), data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kernel_neon_begin();
|
||||
sm3_base_do_update(desc, data, len, sm3_neon_transform);
|
||||
kernel_neon_end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm3_neon_final(struct shash_desc *desc, u8 *out)
|
||||
{
|
||||
if (!crypto_simd_usable()) {
|
||||
sm3_final(shash_desc_ctx(desc), out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kernel_neon_begin();
|
||||
sm3_base_do_finalize(desc, sm3_neon_transform);
|
||||
kernel_neon_end();
|
||||
|
||||
return sm3_base_finish(desc, out);
|
||||
}
|
||||
|
||||
static int sm3_neon_finup(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int len, u8 *out)
|
||||
{
|
||||
if (!crypto_simd_usable()) {
|
||||
struct sm3_state *sctx = shash_desc_ctx(desc);
|
||||
|
||||
if (len)
|
||||
sm3_update(sctx, data, len);
|
||||
sm3_final(sctx, out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kernel_neon_begin();
|
||||
if (len)
|
||||
sm3_base_do_update(desc, data, len, sm3_neon_transform);
|
||||
sm3_base_do_finalize(desc, sm3_neon_transform);
|
||||
kernel_neon_end();
|
||||
|
||||
return sm3_base_finish(desc, out);
|
||||
}
|
||||
|
||||
static struct shash_alg sm3_alg = {
|
||||
.digestsize = SM3_DIGEST_SIZE,
|
||||
.init = sm3_base_init,
|
||||
.update = sm3_neon_update,
|
||||
.final = sm3_neon_final,
|
||||
.finup = sm3_neon_finup,
|
||||
.descsize = sizeof(struct sm3_state),
|
||||
.base.cra_name = "sm3",
|
||||
.base.cra_driver_name = "sm3-neon",
|
||||
.base.cra_blocksize = SM3_BLOCK_SIZE,
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.base.cra_priority = 200,
|
||||
};
|
||||
|
||||
static int __init sm3_neon_init(void)
|
||||
{
|
||||
return crypto_register_shash(&sm3_alg);
|
||||
}
|
||||
|
||||
static void __exit sm3_neon_fini(void)
|
||||
{
|
||||
crypto_unregister_shash(&sm3_alg);
|
||||
}
|
||||
|
||||
module_init(sm3_neon_init);
|
||||
module_exit(sm3_neon_fini);
|
||||
|
||||
MODULE_DESCRIPTION("SM3 secure hash using NEON instructions");
|
||||
MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>");
|
||||
MODULE_AUTHOR("Tianjia Zhang <tianjia.zhang@linux.alibaba.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -0,0 +1,209 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* SM4 helper macros for Crypto Extensions
|
||||
* Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
|
||||
*/
|
||||
|
||||
#define SM4_PREPARE(ptr) \
|
||||
ld1 {v24.16b-v27.16b}, [ptr], #64; \
|
||||
ld1 {v28.16b-v31.16b}, [ptr];
|
||||
|
||||
#define SM4_CRYPT_BLK_BE(b0) \
|
||||
sm4e b0.4s, v24.4s; \
|
||||
sm4e b0.4s, v25.4s; \
|
||||
sm4e b0.4s, v26.4s; \
|
||||
sm4e b0.4s, v27.4s; \
|
||||
sm4e b0.4s, v28.4s; \
|
||||
sm4e b0.4s, v29.4s; \
|
||||
sm4e b0.4s, v30.4s; \
|
||||
sm4e b0.4s, v31.4s; \
|
||||
rev64 b0.4s, b0.4s; \
|
||||
ext b0.16b, b0.16b, b0.16b, #8; \
|
||||
rev32 b0.16b, b0.16b;
|
||||
|
||||
#define SM4_CRYPT_BLK(b0) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
SM4_CRYPT_BLK_BE(b0);
|
||||
|
||||
#define SM4_CRYPT_BLK2_BE(b0, b1) \
|
||||
sm4e b0.4s, v24.4s; \
|
||||
sm4e b1.4s, v24.4s; \
|
||||
sm4e b0.4s, v25.4s; \
|
||||
sm4e b1.4s, v25.4s; \
|
||||
sm4e b0.4s, v26.4s; \
|
||||
sm4e b1.4s, v26.4s; \
|
||||
sm4e b0.4s, v27.4s; \
|
||||
sm4e b1.4s, v27.4s; \
|
||||
sm4e b0.4s, v28.4s; \
|
||||
sm4e b1.4s, v28.4s; \
|
||||
sm4e b0.4s, v29.4s; \
|
||||
sm4e b1.4s, v29.4s; \
|
||||
sm4e b0.4s, v30.4s; \
|
||||
sm4e b1.4s, v30.4s; \
|
||||
sm4e b0.4s, v31.4s; \
|
||||
sm4e b1.4s, v31.4s; \
|
||||
rev64 b0.4s, b0.4s; \
|
||||
rev64 b1.4s, b1.4s; \
|
||||
ext b0.16b, b0.16b, b0.16b, #8; \
|
||||
ext b1.16b, b1.16b, b1.16b, #8; \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
|
||||
#define SM4_CRYPT_BLK2(b0, b1) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
SM4_CRYPT_BLK2_BE(b0, b1);
|
||||
|
||||
#define SM4_CRYPT_BLK4_BE(b0, b1, b2, b3) \
|
||||
sm4e b0.4s, v24.4s; \
|
||||
sm4e b1.4s, v24.4s; \
|
||||
sm4e b2.4s, v24.4s; \
|
||||
sm4e b3.4s, v24.4s; \
|
||||
sm4e b0.4s, v25.4s; \
|
||||
sm4e b1.4s, v25.4s; \
|
||||
sm4e b2.4s, v25.4s; \
|
||||
sm4e b3.4s, v25.4s; \
|
||||
sm4e b0.4s, v26.4s; \
|
||||
sm4e b1.4s, v26.4s; \
|
||||
sm4e b2.4s, v26.4s; \
|
||||
sm4e b3.4s, v26.4s; \
|
||||
sm4e b0.4s, v27.4s; \
|
||||
sm4e b1.4s, v27.4s; \
|
||||
sm4e b2.4s, v27.4s; \
|
||||
sm4e b3.4s, v27.4s; \
|
||||
sm4e b0.4s, v28.4s; \
|
||||
sm4e b1.4s, v28.4s; \
|
||||
sm4e b2.4s, v28.4s; \
|
||||
sm4e b3.4s, v28.4s; \
|
||||
sm4e b0.4s, v29.4s; \
|
||||
sm4e b1.4s, v29.4s; \
|
||||
sm4e b2.4s, v29.4s; \
|
||||
sm4e b3.4s, v29.4s; \
|
||||
sm4e b0.4s, v30.4s; \
|
||||
sm4e b1.4s, v30.4s; \
|
||||
sm4e b2.4s, v30.4s; \
|
||||
sm4e b3.4s, v30.4s; \
|
||||
sm4e b0.4s, v31.4s; \
|
||||
sm4e b1.4s, v31.4s; \
|
||||
sm4e b2.4s, v31.4s; \
|
||||
sm4e b3.4s, v31.4s; \
|
||||
rev64 b0.4s, b0.4s; \
|
||||
rev64 b1.4s, b1.4s; \
|
||||
rev64 b2.4s, b2.4s; \
|
||||
rev64 b3.4s, b3.4s; \
|
||||
ext b0.16b, b0.16b, b0.16b, #8; \
|
||||
ext b1.16b, b1.16b, b1.16b, #8; \
|
||||
ext b2.16b, b2.16b, b2.16b, #8; \
|
||||
ext b3.16b, b3.16b, b3.16b, #8; \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
rev32 b3.16b, b3.16b;
|
||||
|
||||
#define SM4_CRYPT_BLK4(b0, b1, b2, b3) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
rev32 b3.16b, b3.16b; \
|
||||
SM4_CRYPT_BLK4_BE(b0, b1, b2, b3);
|
||||
|
||||
#define SM4_CRYPT_BLK8_BE(b0, b1, b2, b3, b4, b5, b6, b7) \
|
||||
sm4e b0.4s, v24.4s; \
|
||||
sm4e b1.4s, v24.4s; \
|
||||
sm4e b2.4s, v24.4s; \
|
||||
sm4e b3.4s, v24.4s; \
|
||||
sm4e b4.4s, v24.4s; \
|
||||
sm4e b5.4s, v24.4s; \
|
||||
sm4e b6.4s, v24.4s; \
|
||||
sm4e b7.4s, v24.4s; \
|
||||
sm4e b0.4s, v25.4s; \
|
||||
sm4e b1.4s, v25.4s; \
|
||||
sm4e b2.4s, v25.4s; \
|
||||
sm4e b3.4s, v25.4s; \
|
||||
sm4e b4.4s, v25.4s; \
|
||||
sm4e b5.4s, v25.4s; \
|
||||
sm4e b6.4s, v25.4s; \
|
||||
sm4e b7.4s, v25.4s; \
|
||||
sm4e b0.4s, v26.4s; \
|
||||
sm4e b1.4s, v26.4s; \
|
||||
sm4e b2.4s, v26.4s; \
|
||||
sm4e b3.4s, v26.4s; \
|
||||
sm4e b4.4s, v26.4s; \
|
||||
sm4e b5.4s, v26.4s; \
|
||||
sm4e b6.4s, v26.4s; \
|
||||
sm4e b7.4s, v26.4s; \
|
||||
sm4e b0.4s, v27.4s; \
|
||||
sm4e b1.4s, v27.4s; \
|
||||
sm4e b2.4s, v27.4s; \
|
||||
sm4e b3.4s, v27.4s; \
|
||||
sm4e b4.4s, v27.4s; \
|
||||
sm4e b5.4s, v27.4s; \
|
||||
sm4e b6.4s, v27.4s; \
|
||||
sm4e b7.4s, v27.4s; \
|
||||
sm4e b0.4s, v28.4s; \
|
||||
sm4e b1.4s, v28.4s; \
|
||||
sm4e b2.4s, v28.4s; \
|
||||
sm4e b3.4s, v28.4s; \
|
||||
sm4e b4.4s, v28.4s; \
|
||||
sm4e b5.4s, v28.4s; \
|
||||
sm4e b6.4s, v28.4s; \
|
||||
sm4e b7.4s, v28.4s; \
|
||||
sm4e b0.4s, v29.4s; \
|
||||
sm4e b1.4s, v29.4s; \
|
||||
sm4e b2.4s, v29.4s; \
|
||||
sm4e b3.4s, v29.4s; \
|
||||
sm4e b4.4s, v29.4s; \
|
||||
sm4e b5.4s, v29.4s; \
|
||||
sm4e b6.4s, v29.4s; \
|
||||
sm4e b7.4s, v29.4s; \
|
||||
sm4e b0.4s, v30.4s; \
|
||||
sm4e b1.4s, v30.4s; \
|
||||
sm4e b2.4s, v30.4s; \
|
||||
sm4e b3.4s, v30.4s; \
|
||||
sm4e b4.4s, v30.4s; \
|
||||
sm4e b5.4s, v30.4s; \
|
||||
sm4e b6.4s, v30.4s; \
|
||||
sm4e b7.4s, v30.4s; \
|
||||
sm4e b0.4s, v31.4s; \
|
||||
sm4e b1.4s, v31.4s; \
|
||||
sm4e b2.4s, v31.4s; \
|
||||
sm4e b3.4s, v31.4s; \
|
||||
sm4e b4.4s, v31.4s; \
|
||||
sm4e b5.4s, v31.4s; \
|
||||
sm4e b6.4s, v31.4s; \
|
||||
sm4e b7.4s, v31.4s; \
|
||||
rev64 b0.4s, b0.4s; \
|
||||
rev64 b1.4s, b1.4s; \
|
||||
rev64 b2.4s, b2.4s; \
|
||||
rev64 b3.4s, b3.4s; \
|
||||
rev64 b4.4s, b4.4s; \
|
||||
rev64 b5.4s, b5.4s; \
|
||||
rev64 b6.4s, b6.4s; \
|
||||
rev64 b7.4s, b7.4s; \
|
||||
ext b0.16b, b0.16b, b0.16b, #8; \
|
||||
ext b1.16b, b1.16b, b1.16b, #8; \
|
||||
ext b2.16b, b2.16b, b2.16b, #8; \
|
||||
ext b3.16b, b3.16b, b3.16b, #8; \
|
||||
ext b4.16b, b4.16b, b4.16b, #8; \
|
||||
ext b5.16b, b5.16b, b5.16b, #8; \
|
||||
ext b6.16b, b6.16b, b6.16b, #8; \
|
||||
ext b7.16b, b7.16b, b7.16b, #8; \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
rev32 b3.16b, b3.16b; \
|
||||
rev32 b4.16b, b4.16b; \
|
||||
rev32 b5.16b, b5.16b; \
|
||||
rev32 b6.16b, b6.16b; \
|
||||
rev32 b7.16b, b7.16b;
|
||||
|
||||
#define SM4_CRYPT_BLK8(b0, b1, b2, b3, b4, b5, b6, b7) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
rev32 b3.16b, b3.16b; \
|
||||
rev32 b4.16b, b4.16b; \
|
||||
rev32 b5.16b, b5.16b; \
|
||||
rev32 b6.16b, b6.16b; \
|
||||
rev32 b7.16b, b7.16b; \
|
||||
SM4_CRYPT_BLK8_BE(b0, b1, b2, b3, b4, b5, b6, b7);
|
||||
@@ -0,0 +1,328 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* SM4-CCM AEAD Algorithm using ARMv8 Crypto Extensions
|
||||
* as specified in rfc8998
|
||||
* https://datatracker.ietf.org/doc/html/rfc8998
|
||||
*
|
||||
* Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include "sm4-ce-asm.h"
|
||||
|
||||
.arch armv8-a+crypto
|
||||
|
||||
.irp b, 0, 1, 8, 9, 10, 11, 12, 13, 14, 15, 16, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
.set .Lv\b\().4s, \b
|
||||
.endr
|
||||
|
||||
.macro sm4e, vd, vn
|
||||
.inst 0xcec08400 | (.L\vn << 5) | .L\vd
|
||||
.endm
|
||||
|
||||
/* Register macros */
|
||||
|
||||
#define RMAC v16
|
||||
|
||||
/* Helper macros. */
|
||||
|
||||
#define inc_le128(vctr) \
|
||||
mov vctr.d[1], x8; \
|
||||
mov vctr.d[0], x7; \
|
||||
adds x8, x8, #1; \
|
||||
rev64 vctr.16b, vctr.16b; \
|
||||
adc x7, x7, xzr;
|
||||
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_ce_cbcmac_update)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: mac
|
||||
* x2: src
|
||||
* w3: nblocks
|
||||
*/
|
||||
SM4_PREPARE(x0)
|
||||
|
||||
ld1 {RMAC.16b}, [x1]
|
||||
|
||||
.Lcbcmac_loop_4x:
|
||||
cmp w3, #4
|
||||
blt .Lcbcmac_loop_1x
|
||||
|
||||
sub w3, w3, #4
|
||||
|
||||
ld1 {v0.16b-v3.16b}, [x2], #64
|
||||
|
||||
SM4_CRYPT_BLK(RMAC)
|
||||
eor RMAC.16b, RMAC.16b, v0.16b
|
||||
SM4_CRYPT_BLK(RMAC)
|
||||
eor RMAC.16b, RMAC.16b, v1.16b
|
||||
SM4_CRYPT_BLK(RMAC)
|
||||
eor RMAC.16b, RMAC.16b, v2.16b
|
||||
SM4_CRYPT_BLK(RMAC)
|
||||
eor RMAC.16b, RMAC.16b, v3.16b
|
||||
|
||||
cbz w3, .Lcbcmac_end
|
||||
b .Lcbcmac_loop_4x
|
||||
|
||||
.Lcbcmac_loop_1x:
|
||||
sub w3, w3, #1
|
||||
|
||||
ld1 {v0.16b}, [x2], #16
|
||||
|
||||
SM4_CRYPT_BLK(RMAC)
|
||||
eor RMAC.16b, RMAC.16b, v0.16b
|
||||
|
||||
cbnz w3, .Lcbcmac_loop_1x
|
||||
|
||||
.Lcbcmac_end:
|
||||
st1 {RMAC.16b}, [x1]
|
||||
ret
|
||||
SYM_FUNC_END(sm4_ce_cbcmac_update)
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_ce_ccm_final)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: ctr0 (big endian, 128 bit)
|
||||
* x2: mac
|
||||
*/
|
||||
SM4_PREPARE(x0)
|
||||
|
||||
ld1 {RMAC.16b}, [x2]
|
||||
ld1 {v0.16b}, [x1]
|
||||
|
||||
SM4_CRYPT_BLK2(RMAC, v0)
|
||||
|
||||
/* en-/decrypt the mac with ctr0 */
|
||||
eor RMAC.16b, RMAC.16b, v0.16b
|
||||
st1 {RMAC.16b}, [x2]
|
||||
|
||||
ret
|
||||
SYM_FUNC_END(sm4_ce_ccm_final)
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_ce_ccm_enc)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* x3: ctr (big endian, 128 bit)
|
||||
* w4: nbytes
|
||||
* x5: mac
|
||||
*/
|
||||
SM4_PREPARE(x0)
|
||||
|
||||
ldp x7, x8, [x3]
|
||||
rev x7, x7
|
||||
rev x8, x8
|
||||
|
||||
ld1 {RMAC.16b}, [x5]
|
||||
|
||||
.Lccm_enc_loop_4x:
|
||||
cmp w4, #(4 * 16)
|
||||
blt .Lccm_enc_loop_1x
|
||||
|
||||
sub w4, w4, #(4 * 16)
|
||||
|
||||
/* construct CTRs */
|
||||
inc_le128(v8) /* +0 */
|
||||
inc_le128(v9) /* +1 */
|
||||
inc_le128(v10) /* +2 */
|
||||
inc_le128(v11) /* +3 */
|
||||
|
||||
ld1 {v0.16b-v3.16b}, [x2], #64
|
||||
|
||||
SM4_CRYPT_BLK2(v8, RMAC)
|
||||
eor v8.16b, v8.16b, v0.16b
|
||||
eor RMAC.16b, RMAC.16b, v0.16b
|
||||
SM4_CRYPT_BLK2(v9, RMAC)
|
||||
eor v9.16b, v9.16b, v1.16b
|
||||
eor RMAC.16b, RMAC.16b, v1.16b
|
||||
SM4_CRYPT_BLK2(v10, RMAC)
|
||||
eor v10.16b, v10.16b, v2.16b
|
||||
eor RMAC.16b, RMAC.16b, v2.16b
|
||||
SM4_CRYPT_BLK2(v11, RMAC)
|
||||
eor v11.16b, v11.16b, v3.16b
|
||||
eor RMAC.16b, RMAC.16b, v3.16b
|
||||
|
||||
st1 {v8.16b-v11.16b}, [x1], #64
|
||||
|
||||
cbz w4, .Lccm_enc_end
|
||||
b .Lccm_enc_loop_4x
|
||||
|
||||
.Lccm_enc_loop_1x:
|
||||
cmp w4, #16
|
||||
blt .Lccm_enc_tail
|
||||
|
||||
sub w4, w4, #16
|
||||
|
||||
/* construct CTRs */
|
||||
inc_le128(v8)
|
||||
|
||||
ld1 {v0.16b}, [x2], #16
|
||||
|
||||
SM4_CRYPT_BLK2(v8, RMAC)
|
||||
eor v8.16b, v8.16b, v0.16b
|
||||
eor RMAC.16b, RMAC.16b, v0.16b
|
||||
|
||||
st1 {v8.16b}, [x1], #16
|
||||
|
||||
cbz w4, .Lccm_enc_end
|
||||
b .Lccm_enc_loop_1x
|
||||
|
||||
.Lccm_enc_tail:
|
||||
/* construct CTRs */
|
||||
inc_le128(v8)
|
||||
|
||||
SM4_CRYPT_BLK2(RMAC, v8)
|
||||
|
||||
/* store new MAC */
|
||||
st1 {RMAC.16b}, [x5]
|
||||
|
||||
.Lccm_enc_tail_loop:
|
||||
ldrb w0, [x2], #1 /* get 1 byte from input */
|
||||
umov w9, v8.b[0] /* get top crypted CTR byte */
|
||||
umov w6, RMAC.b[0] /* get top MAC byte */
|
||||
|
||||
eor w9, w9, w0 /* w9 = CTR ^ input */
|
||||
eor w6, w6, w0 /* w6 = MAC ^ input */
|
||||
|
||||
strb w9, [x1], #1 /* store out byte */
|
||||
strb w6, [x5], #1 /* store MAC byte */
|
||||
|
||||
subs w4, w4, #1
|
||||
beq .Lccm_enc_ret
|
||||
|
||||
/* shift out one byte */
|
||||
ext RMAC.16b, RMAC.16b, RMAC.16b, #1
|
||||
ext v8.16b, v8.16b, v8.16b, #1
|
||||
|
||||
b .Lccm_enc_tail_loop
|
||||
|
||||
.Lccm_enc_end:
|
||||
/* store new MAC */
|
||||
st1 {RMAC.16b}, [x5]
|
||||
|
||||
/* store new CTR */
|
||||
rev x7, x7
|
||||
rev x8, x8
|
||||
stp x7, x8, [x3]
|
||||
|
||||
.Lccm_enc_ret:
|
||||
ret
|
||||
SYM_FUNC_END(sm4_ce_ccm_enc)
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_ce_ccm_dec)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* x3: ctr (big endian, 128 bit)
|
||||
* w4: nbytes
|
||||
* x5: mac
|
||||
*/
|
||||
SM4_PREPARE(x0)
|
||||
|
||||
ldp x7, x8, [x3]
|
||||
rev x7, x7
|
||||
rev x8, x8
|
||||
|
||||
ld1 {RMAC.16b}, [x5]
|
||||
|
||||
.Lccm_dec_loop_4x:
|
||||
cmp w4, #(4 * 16)
|
||||
blt .Lccm_dec_loop_1x
|
||||
|
||||
sub w4, w4, #(4 * 16)
|
||||
|
||||
/* construct CTRs */
|
||||
inc_le128(v8) /* +0 */
|
||||
inc_le128(v9) /* +1 */
|
||||
inc_le128(v10) /* +2 */
|
||||
inc_le128(v11) /* +3 */
|
||||
|
||||
ld1 {v0.16b-v3.16b}, [x2], #64
|
||||
|
||||
SM4_CRYPT_BLK2(v8, RMAC)
|
||||
eor v8.16b, v8.16b, v0.16b
|
||||
eor RMAC.16b, RMAC.16b, v8.16b
|
||||
SM4_CRYPT_BLK2(v9, RMAC)
|
||||
eor v9.16b, v9.16b, v1.16b
|
||||
eor RMAC.16b, RMAC.16b, v9.16b
|
||||
SM4_CRYPT_BLK2(v10, RMAC)
|
||||
eor v10.16b, v10.16b, v2.16b
|
||||
eor RMAC.16b, RMAC.16b, v10.16b
|
||||
SM4_CRYPT_BLK2(v11, RMAC)
|
||||
eor v11.16b, v11.16b, v3.16b
|
||||
eor RMAC.16b, RMAC.16b, v11.16b
|
||||
|
||||
st1 {v8.16b-v11.16b}, [x1], #64
|
||||
|
||||
cbz w4, .Lccm_dec_end
|
||||
b .Lccm_dec_loop_4x
|
||||
|
||||
.Lccm_dec_loop_1x:
|
||||
cmp w4, #16
|
||||
blt .Lccm_dec_tail
|
||||
|
||||
sub w4, w4, #16
|
||||
|
||||
/* construct CTRs */
|
||||
inc_le128(v8)
|
||||
|
||||
ld1 {v0.16b}, [x2], #16
|
||||
|
||||
SM4_CRYPT_BLK2(v8, RMAC)
|
||||
eor v8.16b, v8.16b, v0.16b
|
||||
eor RMAC.16b, RMAC.16b, v8.16b
|
||||
|
||||
st1 {v8.16b}, [x1], #16
|
||||
|
||||
cbz w4, .Lccm_dec_end
|
||||
b .Lccm_dec_loop_1x
|
||||
|
||||
.Lccm_dec_tail:
|
||||
/* construct CTRs */
|
||||
inc_le128(v8)
|
||||
|
||||
SM4_CRYPT_BLK2(RMAC, v8)
|
||||
|
||||
/* store new MAC */
|
||||
st1 {RMAC.16b}, [x5]
|
||||
|
||||
.Lccm_dec_tail_loop:
|
||||
ldrb w0, [x2], #1 /* get 1 byte from input */
|
||||
umov w9, v8.b[0] /* get top crypted CTR byte */
|
||||
umov w6, RMAC.b[0] /* get top MAC byte */
|
||||
|
||||
eor w9, w9, w0 /* w9 = CTR ^ input */
|
||||
eor w6, w6, w9 /* w6 = MAC ^ output */
|
||||
|
||||
strb w9, [x1], #1 /* store out byte */
|
||||
strb w6, [x5], #1 /* store MAC byte */
|
||||
|
||||
subs w4, w4, #1
|
||||
beq .Lccm_dec_ret
|
||||
|
||||
/* shift out one byte */
|
||||
ext RMAC.16b, RMAC.16b, RMAC.16b, #1
|
||||
ext v8.16b, v8.16b, v8.16b, #1
|
||||
|
||||
b .Lccm_dec_tail_loop
|
||||
|
||||
.Lccm_dec_end:
|
||||
/* store new MAC */
|
||||
st1 {RMAC.16b}, [x5]
|
||||
|
||||
/* store new CTR */
|
||||
rev x7, x7
|
||||
rev x8, x8
|
||||
stp x7, x8, [x3]
|
||||
|
||||
.Lccm_dec_ret:
|
||||
ret
|
||||
SYM_FUNC_END(sm4_ce_ccm_dec)
|
||||
@@ -0,0 +1,303 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* SM4-CCM AEAD Algorithm using ARMv8 Crypto Extensions
|
||||
* as specified in rfc8998
|
||||
* https://datatracker.ietf.org/doc/html/rfc8998
|
||||
*
|
||||
* Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <asm/neon.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/internal/aead.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/sm4.h>
|
||||
#include "sm4-ce.h"
|
||||
|
||||
asmlinkage void sm4_ce_cbcmac_update(const u32 *rkey_enc, u8 *mac,
|
||||
const u8 *src, unsigned int nblocks);
|
||||
asmlinkage void sm4_ce_ccm_enc(const u32 *rkey_enc, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nbytes, u8 *mac);
|
||||
asmlinkage void sm4_ce_ccm_dec(const u32 *rkey_enc, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nbytes, u8 *mac);
|
||||
asmlinkage void sm4_ce_ccm_final(const u32 *rkey_enc, u8 *iv, u8 *mac);
|
||||
|
||||
|
||||
static int ccm_setkey(struct crypto_aead *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct sm4_ctx *ctx = crypto_aead_ctx(tfm);
|
||||
|
||||
if (key_len != SM4_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
kernel_neon_begin();
|
||||
sm4_ce_expand_key(key, ctx->rkey_enc, ctx->rkey_dec,
|
||||
crypto_sm4_fk, crypto_sm4_ck);
|
||||
kernel_neon_end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
|
||||
{
|
||||
if ((authsize & 1) || authsize < 4)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccm_format_input(u8 info[], struct aead_request *req,
|
||||
unsigned int msglen)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
unsigned int l = req->iv[0] + 1;
|
||||
unsigned int m;
|
||||
__be32 len;
|
||||
|
||||
/* verify that CCM dimension 'L': 2 <= L <= 8 */
|
||||
if (l < 2 || l > 8)
|
||||
return -EINVAL;
|
||||
if (l < 4 && msglen >> (8 * l))
|
||||
return -EOVERFLOW;
|
||||
|
||||
memset(&req->iv[SM4_BLOCK_SIZE - l], 0, l);
|
||||
|
||||
memcpy(info, req->iv, SM4_BLOCK_SIZE);
|
||||
|
||||
m = crypto_aead_authsize(aead);
|
||||
|
||||
/* format flags field per RFC 3610/NIST 800-38C */
|
||||
*info |= ((m - 2) / 2) << 3;
|
||||
if (req->assoclen)
|
||||
*info |= (1 << 6);
|
||||
|
||||
/*
|
||||
* format message length field,
|
||||
* Linux uses a u32 type to represent msglen
|
||||
*/
|
||||
if (l >= 4)
|
||||
l = 4;
|
||||
|
||||
len = cpu_to_be32(msglen);
|
||||
memcpy(&info[SM4_BLOCK_SIZE - l], (u8 *)&len + 4 - l, l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
struct sm4_ctx *ctx = crypto_aead_ctx(aead);
|
||||
struct __packed { __be16 l; __be32 h; } aadlen;
|
||||
u32 assoclen = req->assoclen;
|
||||
struct scatter_walk walk;
|
||||
unsigned int len;
|
||||
|
||||
if (assoclen < 0xff00) {
|
||||
aadlen.l = cpu_to_be16(assoclen);
|
||||
len = 2;
|
||||
} else {
|
||||
aadlen.l = cpu_to_be16(0xfffe);
|
||||
put_unaligned_be32(assoclen, &aadlen.h);
|
||||
len = 6;
|
||||
}
|
||||
|
||||
sm4_ce_crypt_block(ctx->rkey_enc, mac, mac);
|
||||
crypto_xor(mac, (const u8 *)&aadlen, len);
|
||||
|
||||
scatterwalk_start(&walk, req->src);
|
||||
|
||||
do {
|
||||
u32 n = scatterwalk_clamp(&walk, assoclen);
|
||||
u8 *p, *ptr;
|
||||
|
||||
if (!n) {
|
||||
scatterwalk_start(&walk, sg_next(walk.sg));
|
||||
n = scatterwalk_clamp(&walk, assoclen);
|
||||
}
|
||||
|
||||
p = ptr = scatterwalk_map(&walk);
|
||||
assoclen -= n;
|
||||
scatterwalk_advance(&walk, n);
|
||||
|
||||
while (n > 0) {
|
||||
unsigned int l, nblocks;
|
||||
|
||||
if (len == SM4_BLOCK_SIZE) {
|
||||
if (n < SM4_BLOCK_SIZE) {
|
||||
sm4_ce_crypt_block(ctx->rkey_enc,
|
||||
mac, mac);
|
||||
|
||||
len = 0;
|
||||
} else {
|
||||
nblocks = n / SM4_BLOCK_SIZE;
|
||||
sm4_ce_cbcmac_update(ctx->rkey_enc,
|
||||
mac, ptr, nblocks);
|
||||
|
||||
ptr += nblocks * SM4_BLOCK_SIZE;
|
||||
n %= SM4_BLOCK_SIZE;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
l = min(n, SM4_BLOCK_SIZE - len);
|
||||
if (l) {
|
||||
crypto_xor(mac + len, ptr, l);
|
||||
len += l;
|
||||
ptr += l;
|
||||
n -= l;
|
||||
}
|
||||
}
|
||||
|
||||
scatterwalk_unmap(p);
|
||||
scatterwalk_done(&walk, 0, assoclen);
|
||||
} while (assoclen);
|
||||
}
|
||||
|
||||
static int ccm_crypt(struct aead_request *req, struct skcipher_walk *walk,
|
||||
u32 *rkey_enc, u8 mac[],
|
||||
void (*sm4_ce_ccm_crypt)(const u32 *rkey_enc, u8 *dst,
|
||||
const u8 *src, u8 *iv,
|
||||
unsigned int nbytes, u8 *mac))
|
||||
{
|
||||
u8 __aligned(8) ctr0[SM4_BLOCK_SIZE];
|
||||
int err;
|
||||
|
||||
/* preserve the initial ctr0 for the TAG */
|
||||
memcpy(ctr0, walk->iv, SM4_BLOCK_SIZE);
|
||||
crypto_inc(walk->iv, SM4_BLOCK_SIZE);
|
||||
|
||||
kernel_neon_begin();
|
||||
|
||||
if (req->assoclen)
|
||||
ccm_calculate_auth_mac(req, mac);
|
||||
|
||||
do {
|
||||
unsigned int tail = walk->nbytes % SM4_BLOCK_SIZE;
|
||||
const u8 *src = walk->src.virt.addr;
|
||||
u8 *dst = walk->dst.virt.addr;
|
||||
|
||||
if (walk->nbytes == walk->total)
|
||||
tail = 0;
|
||||
|
||||
if (walk->nbytes - tail)
|
||||
sm4_ce_ccm_crypt(rkey_enc, dst, src, walk->iv,
|
||||
walk->nbytes - tail, mac);
|
||||
|
||||
if (walk->nbytes == walk->total)
|
||||
sm4_ce_ccm_final(rkey_enc, ctr0, mac);
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
if (walk->nbytes) {
|
||||
err = skcipher_walk_done(walk, tail);
|
||||
if (err)
|
||||
return err;
|
||||
if (walk->nbytes)
|
||||
kernel_neon_begin();
|
||||
}
|
||||
} while (walk->nbytes > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccm_encrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
struct sm4_ctx *ctx = crypto_aead_ctx(aead);
|
||||
u8 __aligned(8) mac[SM4_BLOCK_SIZE];
|
||||
struct skcipher_walk walk;
|
||||
int err;
|
||||
|
||||
err = ccm_format_input(mac, req, req->cryptlen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = skcipher_walk_aead_encrypt(&walk, req, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ccm_crypt(req, &walk, ctx->rkey_enc, mac, sm4_ce_ccm_enc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* copy authtag to end of dst */
|
||||
scatterwalk_map_and_copy(mac, req->dst, req->assoclen + req->cryptlen,
|
||||
crypto_aead_authsize(aead), 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccm_decrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
unsigned int authsize = crypto_aead_authsize(aead);
|
||||
struct sm4_ctx *ctx = crypto_aead_ctx(aead);
|
||||
u8 __aligned(8) mac[SM4_BLOCK_SIZE];
|
||||
u8 authtag[SM4_BLOCK_SIZE];
|
||||
struct skcipher_walk walk;
|
||||
int err;
|
||||
|
||||
err = ccm_format_input(mac, req, req->cryptlen - authsize);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = skcipher_walk_aead_decrypt(&walk, req, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = ccm_crypt(req, &walk, ctx->rkey_enc, mac, sm4_ce_ccm_dec);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* compare calculated auth tag with the stored one */
|
||||
scatterwalk_map_and_copy(authtag, req->src,
|
||||
req->assoclen + req->cryptlen - authsize,
|
||||
authsize, 0);
|
||||
|
||||
if (crypto_memneq(authtag, mac, authsize))
|
||||
return -EBADMSG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct aead_alg sm4_ccm_alg = {
|
||||
.base = {
|
||||
.cra_name = "ccm(sm4)",
|
||||
.cra_driver_name = "ccm-sm4-ce",
|
||||
.cra_priority = 400,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct sm4_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
},
|
||||
.ivsize = SM4_BLOCK_SIZE,
|
||||
.chunksize = SM4_BLOCK_SIZE,
|
||||
.maxauthsize = SM4_BLOCK_SIZE,
|
||||
.setkey = ccm_setkey,
|
||||
.setauthsize = ccm_setauthsize,
|
||||
.encrypt = ccm_encrypt,
|
||||
.decrypt = ccm_decrypt,
|
||||
};
|
||||
|
||||
static int __init sm4_ce_ccm_init(void)
|
||||
{
|
||||
return crypto_register_aead(&sm4_ccm_alg);
|
||||
}
|
||||
|
||||
static void __exit sm4_ce_ccm_exit(void)
|
||||
{
|
||||
crypto_unregister_aead(&sm4_ccm_alg);
|
||||
}
|
||||
|
||||
module_cpu_feature_match(SM4, sm4_ce_ccm_init);
|
||||
module_exit(sm4_ce_ccm_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Synchronous SM4 in CCM mode using ARMv8 Crypto Extensions");
|
||||
MODULE_ALIAS_CRYPTO("ccm(sm4)");
|
||||
MODULE_AUTHOR("Tianjia Zhang <tianjia.zhang@linux.alibaba.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/sm4.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
MODULE_ALIAS_CRYPTO("sm4");
|
||||
|
||||
+815
-382
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,741 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* SM4-GCM AEAD Algorithm using ARMv8 Crypto Extensions
|
||||
* as specified in rfc8998
|
||||
* https://datatracker.ietf.org/doc/html/rfc8998
|
||||
*
|
||||
* Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
|
||||
* Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include "sm4-ce-asm.h"
|
||||
|
||||
.arch armv8-a+crypto
|
||||
|
||||
.irp b, 0, 1, 2, 3, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
.set .Lv\b\().4s, \b
|
||||
.endr
|
||||
|
||||
.macro sm4e, vd, vn
|
||||
.inst 0xcec08400 | (.L\vn << 5) | .L\vd
|
||||
.endm
|
||||
|
||||
/* Register macros */
|
||||
|
||||
/* Used for both encryption and decryption */
|
||||
#define RHASH v21
|
||||
#define RRCONST v22
|
||||
#define RZERO v23
|
||||
|
||||
/* Helper macros. */
|
||||
|
||||
/*
|
||||
* input: m0, m1
|
||||
* output: r0:r1 (low 128-bits in r0, high in r1)
|
||||
*/
|
||||
#define PMUL_128x128(r0, r1, m0, m1, T0, T1) \
|
||||
ext T0.16b, m1.16b, m1.16b, #8; \
|
||||
pmull r0.1q, m0.1d, m1.1d; \
|
||||
pmull T1.1q, m0.1d, T0.1d; \
|
||||
pmull2 T0.1q, m0.2d, T0.2d; \
|
||||
pmull2 r1.1q, m0.2d, m1.2d; \
|
||||
eor T0.16b, T0.16b, T1.16b; \
|
||||
ext T1.16b, RZERO.16b, T0.16b, #8; \
|
||||
ext T0.16b, T0.16b, RZERO.16b, #8; \
|
||||
eor r0.16b, r0.16b, T1.16b; \
|
||||
eor r1.16b, r1.16b, T0.16b;
|
||||
|
||||
#define PMUL_128x128_4x(r0, r1, m0, m1, T0, T1, \
|
||||
r2, r3, m2, m3, T2, T3, \
|
||||
r4, r5, m4, m5, T4, T5, \
|
||||
r6, r7, m6, m7, T6, T7) \
|
||||
ext T0.16b, m1.16b, m1.16b, #8; \
|
||||
ext T2.16b, m3.16b, m3.16b, #8; \
|
||||
ext T4.16b, m5.16b, m5.16b, #8; \
|
||||
ext T6.16b, m7.16b, m7.16b, #8; \
|
||||
pmull r0.1q, m0.1d, m1.1d; \
|
||||
pmull r2.1q, m2.1d, m3.1d; \
|
||||
pmull r4.1q, m4.1d, m5.1d; \
|
||||
pmull r6.1q, m6.1d, m7.1d; \
|
||||
pmull T1.1q, m0.1d, T0.1d; \
|
||||
pmull T3.1q, m2.1d, T2.1d; \
|
||||
pmull T5.1q, m4.1d, T4.1d; \
|
||||
pmull T7.1q, m6.1d, T6.1d; \
|
||||
pmull2 T0.1q, m0.2d, T0.2d; \
|
||||
pmull2 T2.1q, m2.2d, T2.2d; \
|
||||
pmull2 T4.1q, m4.2d, T4.2d; \
|
||||
pmull2 T6.1q, m6.2d, T6.2d; \
|
||||
pmull2 r1.1q, m0.2d, m1.2d; \
|
||||
pmull2 r3.1q, m2.2d, m3.2d; \
|
||||
pmull2 r5.1q, m4.2d, m5.2d; \
|
||||
pmull2 r7.1q, m6.2d, m7.2d; \
|
||||
eor T0.16b, T0.16b, T1.16b; \
|
||||
eor T2.16b, T2.16b, T3.16b; \
|
||||
eor T4.16b, T4.16b, T5.16b; \
|
||||
eor T6.16b, T6.16b, T7.16b; \
|
||||
ext T1.16b, RZERO.16b, T0.16b, #8; \
|
||||
ext T3.16b, RZERO.16b, T2.16b, #8; \
|
||||
ext T5.16b, RZERO.16b, T4.16b, #8; \
|
||||
ext T7.16b, RZERO.16b, T6.16b, #8; \
|
||||
ext T0.16b, T0.16b, RZERO.16b, #8; \
|
||||
ext T2.16b, T2.16b, RZERO.16b, #8; \
|
||||
ext T4.16b, T4.16b, RZERO.16b, #8; \
|
||||
ext T6.16b, T6.16b, RZERO.16b, #8; \
|
||||
eor r0.16b, r0.16b, T1.16b; \
|
||||
eor r2.16b, r2.16b, T3.16b; \
|
||||
eor r4.16b, r4.16b, T5.16b; \
|
||||
eor r6.16b, r6.16b, T7.16b; \
|
||||
eor r1.16b, r1.16b, T0.16b; \
|
||||
eor r3.16b, r3.16b, T2.16b; \
|
||||
eor r5.16b, r5.16b, T4.16b; \
|
||||
eor r7.16b, r7.16b, T6.16b;
|
||||
|
||||
/*
|
||||
* input: r0:r1 (low 128-bits in r0, high in r1)
|
||||
* output: a
|
||||
*/
|
||||
#define REDUCTION(a, r0, r1, rconst, T0, T1) \
|
||||
pmull2 T0.1q, r1.2d, rconst.2d; \
|
||||
ext T1.16b, T0.16b, RZERO.16b, #8; \
|
||||
ext T0.16b, RZERO.16b, T0.16b, #8; \
|
||||
eor r1.16b, r1.16b, T1.16b; \
|
||||
eor r0.16b, r0.16b, T0.16b; \
|
||||
pmull T0.1q, r1.1d, rconst.1d; \
|
||||
eor a.16b, r0.16b, T0.16b;
|
||||
|
||||
#define SM4_CRYPT_PMUL_128x128_BLK(b0, r0, r1, m0, m1, T0, T1) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
ext T0.16b, m1.16b, m1.16b, #8; \
|
||||
sm4e b0.4s, v24.4s; \
|
||||
pmull r0.1q, m0.1d, m1.1d; \
|
||||
sm4e b0.4s, v25.4s; \
|
||||
pmull T1.1q, m0.1d, T0.1d; \
|
||||
sm4e b0.4s, v26.4s; \
|
||||
pmull2 T0.1q, m0.2d, T0.2d; \
|
||||
sm4e b0.4s, v27.4s; \
|
||||
pmull2 r1.1q, m0.2d, m1.2d; \
|
||||
sm4e b0.4s, v28.4s; \
|
||||
eor T0.16b, T0.16b, T1.16b; \
|
||||
sm4e b0.4s, v29.4s; \
|
||||
ext T1.16b, RZERO.16b, T0.16b, #8; \
|
||||
sm4e b0.4s, v30.4s; \
|
||||
ext T0.16b, T0.16b, RZERO.16b, #8; \
|
||||
sm4e b0.4s, v31.4s; \
|
||||
eor r0.16b, r0.16b, T1.16b; \
|
||||
rev64 b0.4s, b0.4s; \
|
||||
eor r1.16b, r1.16b, T0.16b; \
|
||||
ext b0.16b, b0.16b, b0.16b, #8; \
|
||||
rev32 b0.16b, b0.16b;
|
||||
|
||||
#define SM4_CRYPT_PMUL_128x128_BLK3(b0, b1, b2, \
|
||||
r0, r1, m0, m1, T0, T1, \
|
||||
r2, r3, m2, m3, T2, T3, \
|
||||
r4, r5, m4, m5, T4, T5) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
ext T0.16b, m1.16b, m1.16b, #8; \
|
||||
ext T2.16b, m3.16b, m3.16b, #8; \
|
||||
ext T4.16b, m5.16b, m5.16b, #8; \
|
||||
sm4e b0.4s, v24.4s; \
|
||||
sm4e b1.4s, v24.4s; \
|
||||
sm4e b2.4s, v24.4s; \
|
||||
pmull r0.1q, m0.1d, m1.1d; \
|
||||
pmull r2.1q, m2.1d, m3.1d; \
|
||||
pmull r4.1q, m4.1d, m5.1d; \
|
||||
sm4e b0.4s, v25.4s; \
|
||||
sm4e b1.4s, v25.4s; \
|
||||
sm4e b2.4s, v25.4s; \
|
||||
pmull T1.1q, m0.1d, T0.1d; \
|
||||
pmull T3.1q, m2.1d, T2.1d; \
|
||||
pmull T5.1q, m4.1d, T4.1d; \
|
||||
sm4e b0.4s, v26.4s; \
|
||||
sm4e b1.4s, v26.4s; \
|
||||
sm4e b2.4s, v26.4s; \
|
||||
pmull2 T0.1q, m0.2d, T0.2d; \
|
||||
pmull2 T2.1q, m2.2d, T2.2d; \
|
||||
pmull2 T4.1q, m4.2d, T4.2d; \
|
||||
sm4e b0.4s, v27.4s; \
|
||||
sm4e b1.4s, v27.4s; \
|
||||
sm4e b2.4s, v27.4s; \
|
||||
pmull2 r1.1q, m0.2d, m1.2d; \
|
||||
pmull2 r3.1q, m2.2d, m3.2d; \
|
||||
pmull2 r5.1q, m4.2d, m5.2d; \
|
||||
sm4e b0.4s, v28.4s; \
|
||||
sm4e b1.4s, v28.4s; \
|
||||
sm4e b2.4s, v28.4s; \
|
||||
eor T0.16b, T0.16b, T1.16b; \
|
||||
eor T2.16b, T2.16b, T3.16b; \
|
||||
eor T4.16b, T4.16b, T5.16b; \
|
||||
sm4e b0.4s, v29.4s; \
|
||||
sm4e b1.4s, v29.4s; \
|
||||
sm4e b2.4s, v29.4s; \
|
||||
ext T1.16b, RZERO.16b, T0.16b, #8; \
|
||||
ext T3.16b, RZERO.16b, T2.16b, #8; \
|
||||
ext T5.16b, RZERO.16b, T4.16b, #8; \
|
||||
sm4e b0.4s, v30.4s; \
|
||||
sm4e b1.4s, v30.4s; \
|
||||
sm4e b2.4s, v30.4s; \
|
||||
ext T0.16b, T0.16b, RZERO.16b, #8; \
|
||||
ext T2.16b, T2.16b, RZERO.16b, #8; \
|
||||
ext T4.16b, T4.16b, RZERO.16b, #8; \
|
||||
sm4e b0.4s, v31.4s; \
|
||||
sm4e b1.4s, v31.4s; \
|
||||
sm4e b2.4s, v31.4s; \
|
||||
eor r0.16b, r0.16b, T1.16b; \
|
||||
eor r2.16b, r2.16b, T3.16b; \
|
||||
eor r4.16b, r4.16b, T5.16b; \
|
||||
rev64 b0.4s, b0.4s; \
|
||||
rev64 b1.4s, b1.4s; \
|
||||
rev64 b2.4s, b2.4s; \
|
||||
eor r1.16b, r1.16b, T0.16b; \
|
||||
eor r3.16b, r3.16b, T2.16b; \
|
||||
eor r5.16b, r5.16b, T4.16b; \
|
||||
ext b0.16b, b0.16b, b0.16b, #8; \
|
||||
ext b1.16b, b1.16b, b1.16b, #8; \
|
||||
ext b2.16b, b2.16b, b2.16b, #8; \
|
||||
eor r0.16b, r0.16b, r2.16b; \
|
||||
eor r1.16b, r1.16b, r3.16b; \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
eor r0.16b, r0.16b, r4.16b; \
|
||||
eor r1.16b, r1.16b, r5.16b;
|
||||
|
||||
#define inc32_le128(vctr) \
|
||||
mov vctr.d[1], x9; \
|
||||
add w6, w9, #1; \
|
||||
mov vctr.d[0], x8; \
|
||||
bfi x9, x6, #0, #32; \
|
||||
rev64 vctr.16b, vctr.16b;
|
||||
|
||||
#define GTAG_HASH_LENGTHS(vctr0, vlen) \
|
||||
ld1 {vlen.16b}, [x7]; \
|
||||
/* construct CTR0 */ \
|
||||
/* the lower 32-bits of initial IV is always be32(1) */ \
|
||||
mov x6, #0x1; \
|
||||
bfi x9, x6, #0, #32; \
|
||||
mov vctr0.d[0], x8; \
|
||||
mov vctr0.d[1], x9; \
|
||||
rbit vlen.16b, vlen.16b; \
|
||||
rev64 vctr0.16b, vctr0.16b; \
|
||||
/* authtag = GCTR(CTR0, GHASH) */ \
|
||||
eor RHASH.16b, RHASH.16b, vlen.16b; \
|
||||
SM4_CRYPT_PMUL_128x128_BLK(vctr0, RR0, RR1, RHASH, RH1, \
|
||||
RTMP0, RTMP1); \
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP2, RTMP3); \
|
||||
rbit RHASH.16b, RHASH.16b; \
|
||||
eor RHASH.16b, RHASH.16b, vctr0.16b;
|
||||
|
||||
|
||||
/* Register macros for encrypt and ghash */
|
||||
|
||||
/* can be the same as input v0-v3 */
|
||||
#define RR1 v0
|
||||
#define RR3 v1
|
||||
#define RR5 v2
|
||||
#define RR7 v3
|
||||
|
||||
#define RR0 v4
|
||||
#define RR2 v5
|
||||
#define RR4 v6
|
||||
#define RR6 v7
|
||||
|
||||
#define RTMP0 v8
|
||||
#define RTMP1 v9
|
||||
#define RTMP2 v10
|
||||
#define RTMP3 v11
|
||||
#define RTMP4 v12
|
||||
#define RTMP5 v13
|
||||
#define RTMP6 v14
|
||||
#define RTMP7 v15
|
||||
|
||||
#define RH1 v16
|
||||
#define RH2 v17
|
||||
#define RH3 v18
|
||||
#define RH4 v19
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_ce_pmull_ghash_setup)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: ghash table
|
||||
*/
|
||||
SM4_PREPARE(x0)
|
||||
|
||||
adr_l x2, .Lghash_rconst
|
||||
ld1r {RRCONST.2d}, [x2]
|
||||
|
||||
eor RZERO.16b, RZERO.16b, RZERO.16b
|
||||
|
||||
/* H = E(K, 0^128) */
|
||||
rev32 v0.16b, RZERO.16b
|
||||
SM4_CRYPT_BLK_BE(v0)
|
||||
|
||||
/* H ^ 1 */
|
||||
rbit RH1.16b, v0.16b
|
||||
|
||||
/* H ^ 2 */
|
||||
PMUL_128x128(RR0, RR1, RH1, RH1, RTMP0, RTMP1)
|
||||
REDUCTION(RH2, RR0, RR1, RRCONST, RTMP2, RTMP3)
|
||||
|
||||
/* H ^ 3 */
|
||||
PMUL_128x128(RR0, RR1, RH2, RH1, RTMP0, RTMP1)
|
||||
REDUCTION(RH3, RR0, RR1, RRCONST, RTMP2, RTMP3)
|
||||
|
||||
/* H ^ 4 */
|
||||
PMUL_128x128(RR0, RR1, RH2, RH2, RTMP0, RTMP1)
|
||||
REDUCTION(RH4, RR0, RR1, RRCONST, RTMP2, RTMP3)
|
||||
|
||||
st1 {RH1.16b-RH4.16b}, [x1]
|
||||
|
||||
ret
|
||||
SYM_FUNC_END(sm4_ce_pmull_ghash_setup)
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(pmull_ghash_update)
|
||||
/* input:
|
||||
* x0: ghash table
|
||||
* x1: ghash result
|
||||
* x2: src
|
||||
* w3: nblocks
|
||||
*/
|
||||
ld1 {RH1.16b-RH4.16b}, [x0]
|
||||
|
||||
ld1 {RHASH.16b}, [x1]
|
||||
rbit RHASH.16b, RHASH.16b
|
||||
|
||||
adr_l x4, .Lghash_rconst
|
||||
ld1r {RRCONST.2d}, [x4]
|
||||
|
||||
eor RZERO.16b, RZERO.16b, RZERO.16b
|
||||
|
||||
.Lghash_loop_4x:
|
||||
cmp w3, #4
|
||||
blt .Lghash_loop_1x
|
||||
|
||||
sub w3, w3, #4
|
||||
|
||||
ld1 {v0.16b-v3.16b}, [x2], #64
|
||||
|
||||
rbit v0.16b, v0.16b
|
||||
rbit v1.16b, v1.16b
|
||||
rbit v2.16b, v2.16b
|
||||
rbit v3.16b, v3.16b
|
||||
|
||||
/*
|
||||
* (in0 ^ HASH) * H^4 => rr0:rr1
|
||||
* (in1) * H^3 => rr2:rr3
|
||||
* (in2) * H^2 => rr4:rr5
|
||||
* (in3) * H^1 => rr6:rr7
|
||||
*/
|
||||
eor RHASH.16b, RHASH.16b, v0.16b
|
||||
|
||||
PMUL_128x128_4x(RR0, RR1, RHASH, RH4, RTMP0, RTMP1,
|
||||
RR2, RR3, v1, RH3, RTMP2, RTMP3,
|
||||
RR4, RR5, v2, RH2, RTMP4, RTMP5,
|
||||
RR6, RR7, v3, RH1, RTMP6, RTMP7)
|
||||
|
||||
eor RR0.16b, RR0.16b, RR2.16b
|
||||
eor RR1.16b, RR1.16b, RR3.16b
|
||||
eor RR0.16b, RR0.16b, RR4.16b
|
||||
eor RR1.16b, RR1.16b, RR5.16b
|
||||
eor RR0.16b, RR0.16b, RR6.16b
|
||||
eor RR1.16b, RR1.16b, RR7.16b
|
||||
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP0, RTMP1)
|
||||
|
||||
cbz w3, .Lghash_end
|
||||
b .Lghash_loop_4x
|
||||
|
||||
.Lghash_loop_1x:
|
||||
sub w3, w3, #1
|
||||
|
||||
ld1 {v0.16b}, [x2], #16
|
||||
rbit v0.16b, v0.16b
|
||||
eor RHASH.16b, RHASH.16b, v0.16b
|
||||
|
||||
PMUL_128x128(RR0, RR1, RHASH, RH1, RTMP0, RTMP1)
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP2, RTMP3)
|
||||
|
||||
cbnz w3, .Lghash_loop_1x
|
||||
|
||||
.Lghash_end:
|
||||
rbit RHASH.16b, RHASH.16b
|
||||
st1 {RHASH.2d}, [x1]
|
||||
|
||||
ret
|
||||
SYM_FUNC_END(pmull_ghash_update)
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_ce_pmull_gcm_enc)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* x3: ctr (big endian, 128 bit)
|
||||
* w4: nbytes
|
||||
* x5: ghash result
|
||||
* x6: ghash table
|
||||
* x7: lengths (only for last block)
|
||||
*/
|
||||
SM4_PREPARE(x0)
|
||||
|
||||
ldp x8, x9, [x3]
|
||||
rev x8, x8
|
||||
rev x9, x9
|
||||
|
||||
ld1 {RH1.16b-RH4.16b}, [x6]
|
||||
|
||||
ld1 {RHASH.16b}, [x5]
|
||||
rbit RHASH.16b, RHASH.16b
|
||||
|
||||
adr_l x6, .Lghash_rconst
|
||||
ld1r {RRCONST.2d}, [x6]
|
||||
|
||||
eor RZERO.16b, RZERO.16b, RZERO.16b
|
||||
|
||||
cbz w4, .Lgcm_enc_hash_len
|
||||
|
||||
.Lgcm_enc_loop_4x:
|
||||
cmp w4, #(4 * 16)
|
||||
blt .Lgcm_enc_loop_1x
|
||||
|
||||
sub w4, w4, #(4 * 16)
|
||||
|
||||
/* construct CTRs */
|
||||
inc32_le128(v0) /* +0 */
|
||||
inc32_le128(v1) /* +1 */
|
||||
inc32_le128(v2) /* +2 */
|
||||
inc32_le128(v3) /* +3 */
|
||||
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64
|
||||
|
||||
SM4_CRYPT_BLK4(v0, v1, v2, v3)
|
||||
|
||||
eor v0.16b, v0.16b, RTMP0.16b
|
||||
eor v1.16b, v1.16b, RTMP1.16b
|
||||
eor v2.16b, v2.16b, RTMP2.16b
|
||||
eor v3.16b, v3.16b, RTMP3.16b
|
||||
st1 {v0.16b-v3.16b}, [x1], #64
|
||||
|
||||
/* ghash update */
|
||||
|
||||
rbit v0.16b, v0.16b
|
||||
rbit v1.16b, v1.16b
|
||||
rbit v2.16b, v2.16b
|
||||
rbit v3.16b, v3.16b
|
||||
|
||||
/*
|
||||
* (in0 ^ HASH) * H^4 => rr0:rr1
|
||||
* (in1) * H^3 => rr2:rr3
|
||||
* (in2) * H^2 => rr4:rr5
|
||||
* (in3) * H^1 => rr6:rr7
|
||||
*/
|
||||
eor RHASH.16b, RHASH.16b, v0.16b
|
||||
|
||||
PMUL_128x128_4x(RR0, RR1, RHASH, RH4, RTMP0, RTMP1,
|
||||
RR2, RR3, v1, RH3, RTMP2, RTMP3,
|
||||
RR4, RR5, v2, RH2, RTMP4, RTMP5,
|
||||
RR6, RR7, v3, RH1, RTMP6, RTMP7)
|
||||
|
||||
eor RR0.16b, RR0.16b, RR2.16b
|
||||
eor RR1.16b, RR1.16b, RR3.16b
|
||||
eor RR0.16b, RR0.16b, RR4.16b
|
||||
eor RR1.16b, RR1.16b, RR5.16b
|
||||
eor RR0.16b, RR0.16b, RR6.16b
|
||||
eor RR1.16b, RR1.16b, RR7.16b
|
||||
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP0, RTMP1)
|
||||
|
||||
cbz w4, .Lgcm_enc_hash_len
|
||||
b .Lgcm_enc_loop_4x
|
||||
|
||||
.Lgcm_enc_loop_1x:
|
||||
cmp w4, #16
|
||||
blt .Lgcm_enc_tail
|
||||
|
||||
sub w4, w4, #16
|
||||
|
||||
/* construct CTRs */
|
||||
inc32_le128(v0)
|
||||
|
||||
ld1 {RTMP0.16b}, [x2], #16
|
||||
|
||||
SM4_CRYPT_BLK(v0)
|
||||
|
||||
eor v0.16b, v0.16b, RTMP0.16b
|
||||
st1 {v0.16b}, [x1], #16
|
||||
|
||||
/* ghash update */
|
||||
rbit v0.16b, v0.16b
|
||||
eor RHASH.16b, RHASH.16b, v0.16b
|
||||
PMUL_128x128(RR0, RR1, RHASH, RH1, RTMP0, RTMP1)
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP2, RTMP3)
|
||||
|
||||
cbz w4, .Lgcm_enc_hash_len
|
||||
b .Lgcm_enc_loop_1x
|
||||
|
||||
.Lgcm_enc_tail:
|
||||
/* construct CTRs */
|
||||
inc32_le128(v0)
|
||||
SM4_CRYPT_BLK(v0)
|
||||
|
||||
/* load permute table */
|
||||
adr_l x0, .Lcts_permute_table
|
||||
add x0, x0, #32
|
||||
sub x0, x0, w4, uxtw
|
||||
ld1 {v3.16b}, [x0]
|
||||
|
||||
.Lgcm_enc_tail_loop:
|
||||
/* do encrypt */
|
||||
ldrb w0, [x2], #1 /* get 1 byte from input */
|
||||
umov w6, v0.b[0] /* get top crypted byte */
|
||||
eor w6, w6, w0 /* w6 = CTR ^ input */
|
||||
strb w6, [x1], #1 /* store out byte */
|
||||
|
||||
/* shift right out one byte */
|
||||
ext v0.16b, v0.16b, v0.16b, #1
|
||||
/* the last ciphertext is placed in high bytes */
|
||||
ins v0.b[15], w6
|
||||
|
||||
subs w4, w4, #1
|
||||
bne .Lgcm_enc_tail_loop
|
||||
|
||||
/* padding last block with zeros */
|
||||
tbl v0.16b, {v0.16b}, v3.16b
|
||||
|
||||
/* ghash update */
|
||||
rbit v0.16b, v0.16b
|
||||
eor RHASH.16b, RHASH.16b, v0.16b
|
||||
PMUL_128x128(RR0, RR1, RHASH, RH1, RTMP0, RTMP1)
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP2, RTMP3)
|
||||
|
||||
.Lgcm_enc_hash_len:
|
||||
cbz x7, .Lgcm_enc_end
|
||||
|
||||
GTAG_HASH_LENGTHS(v1, v3)
|
||||
|
||||
b .Lgcm_enc_ret
|
||||
|
||||
.Lgcm_enc_end:
|
||||
/* store new CTR */
|
||||
rev x8, x8
|
||||
rev x9, x9
|
||||
stp x8, x9, [x3]
|
||||
|
||||
rbit RHASH.16b, RHASH.16b
|
||||
|
||||
.Lgcm_enc_ret:
|
||||
/* store new MAC */
|
||||
st1 {RHASH.2d}, [x5]
|
||||
|
||||
ret
|
||||
SYM_FUNC_END(sm4_ce_pmull_gcm_enc)
|
||||
|
||||
#undef RR1
|
||||
#undef RR3
|
||||
#undef RR5
|
||||
#undef RR7
|
||||
#undef RR0
|
||||
#undef RR2
|
||||
#undef RR4
|
||||
#undef RR6
|
||||
#undef RTMP0
|
||||
#undef RTMP1
|
||||
#undef RTMP2
|
||||
#undef RTMP3
|
||||
#undef RTMP4
|
||||
#undef RTMP5
|
||||
#undef RTMP6
|
||||
#undef RTMP7
|
||||
#undef RH1
|
||||
#undef RH2
|
||||
#undef RH3
|
||||
#undef RH4
|
||||
|
||||
|
||||
/* Register macros for decrypt */
|
||||
|
||||
/* v0-v2 for building CTRs, v3-v5 for saving inputs */
|
||||
|
||||
#define RR1 v6
|
||||
#define RR3 v7
|
||||
#define RR5 v8
|
||||
|
||||
#define RR0 v9
|
||||
#define RR2 v10
|
||||
#define RR4 v11
|
||||
|
||||
#define RTMP0 v12
|
||||
#define RTMP1 v13
|
||||
#define RTMP2 v14
|
||||
#define RTMP3 v15
|
||||
#define RTMP4 v16
|
||||
#define RTMP5 v17
|
||||
|
||||
#define RH1 v18
|
||||
#define RH2 v19
|
||||
#define RH3 v20
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_ce_pmull_gcm_dec)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* x3: ctr (big endian, 128 bit)
|
||||
* w4: nbytes
|
||||
* x5: ghash result
|
||||
* x6: ghash table
|
||||
* x7: lengths (only for last block)
|
||||
*/
|
||||
SM4_PREPARE(x0)
|
||||
|
||||
ldp x8, x9, [x3]
|
||||
rev x8, x8
|
||||
rev x9, x9
|
||||
|
||||
ld1 {RH1.16b-RH3.16b}, [x6]
|
||||
|
||||
ld1 {RHASH.16b}, [x5]
|
||||
rbit RHASH.16b, RHASH.16b
|
||||
|
||||
adr_l x6, .Lghash_rconst
|
||||
ld1r {RRCONST.2d}, [x6]
|
||||
|
||||
eor RZERO.16b, RZERO.16b, RZERO.16b
|
||||
|
||||
cbz w4, .Lgcm_dec_hash_len
|
||||
|
||||
.Lgcm_dec_loop_3x:
|
||||
cmp w4, #(3 * 16)
|
||||
blt .Lgcm_dec_loop_1x
|
||||
|
||||
sub w4, w4, #(3 * 16)
|
||||
|
||||
ld1 {v3.16b-v5.16b}, [x2], #(3 * 16)
|
||||
|
||||
/* construct CTRs */
|
||||
inc32_le128(v0) /* +0 */
|
||||
rbit v6.16b, v3.16b
|
||||
inc32_le128(v1) /* +1 */
|
||||
rbit v7.16b, v4.16b
|
||||
inc32_le128(v2) /* +2 */
|
||||
rbit v8.16b, v5.16b
|
||||
|
||||
eor RHASH.16b, RHASH.16b, v6.16b
|
||||
|
||||
/* decrypt & ghash update */
|
||||
SM4_CRYPT_PMUL_128x128_BLK3(v0, v1, v2,
|
||||
RR0, RR1, RHASH, RH3, RTMP0, RTMP1,
|
||||
RR2, RR3, v7, RH2, RTMP2, RTMP3,
|
||||
RR4, RR5, v8, RH1, RTMP4, RTMP5)
|
||||
|
||||
eor v0.16b, v0.16b, v3.16b
|
||||
eor v1.16b, v1.16b, v4.16b
|
||||
eor v2.16b, v2.16b, v5.16b
|
||||
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP0, RTMP1)
|
||||
|
||||
st1 {v0.16b-v2.16b}, [x1], #(3 * 16)
|
||||
|
||||
cbz w4, .Lgcm_dec_hash_len
|
||||
b .Lgcm_dec_loop_3x
|
||||
|
||||
.Lgcm_dec_loop_1x:
|
||||
cmp w4, #16
|
||||
blt .Lgcm_dec_tail
|
||||
|
||||
sub w4, w4, #16
|
||||
|
||||
ld1 {v3.16b}, [x2], #16
|
||||
|
||||
/* construct CTRs */
|
||||
inc32_le128(v0)
|
||||
rbit v6.16b, v3.16b
|
||||
|
||||
eor RHASH.16b, RHASH.16b, v6.16b
|
||||
|
||||
SM4_CRYPT_PMUL_128x128_BLK(v0, RR0, RR1, RHASH, RH1, RTMP0, RTMP1)
|
||||
|
||||
eor v0.16b, v0.16b, v3.16b
|
||||
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP2, RTMP3)
|
||||
|
||||
st1 {v0.16b}, [x1], #16
|
||||
|
||||
cbz w4, .Lgcm_dec_hash_len
|
||||
b .Lgcm_dec_loop_1x
|
||||
|
||||
.Lgcm_dec_tail:
|
||||
/* construct CTRs */
|
||||
inc32_le128(v0)
|
||||
SM4_CRYPT_BLK(v0)
|
||||
|
||||
/* load permute table */
|
||||
adr_l x0, .Lcts_permute_table
|
||||
add x0, x0, #32
|
||||
sub x0, x0, w4, uxtw
|
||||
ld1 {v3.16b}, [x0]
|
||||
|
||||
.Lgcm_dec_tail_loop:
|
||||
/* do decrypt */
|
||||
ldrb w0, [x2], #1 /* get 1 byte from input */
|
||||
umov w6, v0.b[0] /* get top crypted byte */
|
||||
eor w6, w6, w0 /* w6 = CTR ^ input */
|
||||
strb w6, [x1], #1 /* store out byte */
|
||||
|
||||
/* shift right out one byte */
|
||||
ext v0.16b, v0.16b, v0.16b, #1
|
||||
/* the last ciphertext is placed in high bytes */
|
||||
ins v0.b[15], w0
|
||||
|
||||
subs w4, w4, #1
|
||||
bne .Lgcm_dec_tail_loop
|
||||
|
||||
/* padding last block with zeros */
|
||||
tbl v0.16b, {v0.16b}, v3.16b
|
||||
|
||||
/* ghash update */
|
||||
rbit v0.16b, v0.16b
|
||||
eor RHASH.16b, RHASH.16b, v0.16b
|
||||
PMUL_128x128(RR0, RR1, RHASH, RH1, RTMP0, RTMP1)
|
||||
REDUCTION(RHASH, RR0, RR1, RRCONST, RTMP2, RTMP3)
|
||||
|
||||
.Lgcm_dec_hash_len:
|
||||
cbz x7, .Lgcm_dec_end
|
||||
|
||||
GTAG_HASH_LENGTHS(v1, v3)
|
||||
|
||||
b .Lgcm_dec_ret
|
||||
|
||||
.Lgcm_dec_end:
|
||||
/* store new CTR */
|
||||
rev x8, x8
|
||||
rev x9, x9
|
||||
stp x8, x9, [x3]
|
||||
|
||||
rbit RHASH.16b, RHASH.16b
|
||||
|
||||
.Lgcm_dec_ret:
|
||||
/* store new MAC */
|
||||
st1 {RHASH.2d}, [x5]
|
||||
|
||||
ret
|
||||
SYM_FUNC_END(sm4_ce_pmull_gcm_dec)
|
||||
|
||||
.section ".rodata", "a"
|
||||
.align 4
|
||||
.Lcts_permute_table:
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
|
||||
.byte 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
|
||||
.Lghash_rconst:
|
||||
.quad 0x87
|
||||
@@ -0,0 +1,286 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* SM4-GCM AEAD Algorithm using ARMv8 Crypto Extensions
|
||||
* as specified in rfc8998
|
||||
* https://datatracker.ietf.org/doc/html/rfc8998
|
||||
*
|
||||
* Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <asm/neon.h>
|
||||
#include <crypto/b128ops.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/internal/aead.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/sm4.h>
|
||||
#include "sm4-ce.h"
|
||||
|
||||
asmlinkage void sm4_ce_pmull_ghash_setup(const u32 *rkey_enc, u8 *ghash_table);
|
||||
asmlinkage void pmull_ghash_update(const u8 *ghash_table, u8 *ghash,
|
||||
const u8 *src, unsigned int nblocks);
|
||||
asmlinkage void sm4_ce_pmull_gcm_enc(const u32 *rkey_enc, u8 *dst,
|
||||
const u8 *src, u8 *iv,
|
||||
unsigned int nbytes, u8 *ghash,
|
||||
const u8 *ghash_table, const u8 *lengths);
|
||||
asmlinkage void sm4_ce_pmull_gcm_dec(const u32 *rkey_enc, u8 *dst,
|
||||
const u8 *src, u8 *iv,
|
||||
unsigned int nbytes, u8 *ghash,
|
||||
const u8 *ghash_table, const u8 *lengths);
|
||||
|
||||
#define GHASH_BLOCK_SIZE 16
|
||||
#define GCM_IV_SIZE 12
|
||||
|
||||
struct sm4_gcm_ctx {
|
||||
struct sm4_ctx key;
|
||||
u8 ghash_table[16 * 4];
|
||||
};
|
||||
|
||||
|
||||
static int gcm_setkey(struct crypto_aead *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct sm4_gcm_ctx *ctx = crypto_aead_ctx(tfm);
|
||||
|
||||
if (key_len != SM4_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
kernel_neon_begin();
|
||||
|
||||
sm4_ce_expand_key(key, ctx->key.rkey_enc, ctx->key.rkey_dec,
|
||||
crypto_sm4_fk, crypto_sm4_ck);
|
||||
sm4_ce_pmull_ghash_setup(ctx->key.rkey_enc, ctx->ghash_table);
|
||||
|
||||
kernel_neon_end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
|
||||
{
|
||||
switch (authsize) {
|
||||
case 4:
|
||||
case 8:
|
||||
case 12 ... 16:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void gcm_calculate_auth_mac(struct aead_request *req, u8 ghash[])
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
struct sm4_gcm_ctx *ctx = crypto_aead_ctx(aead);
|
||||
u8 __aligned(8) buffer[GHASH_BLOCK_SIZE];
|
||||
u32 assoclen = req->assoclen;
|
||||
struct scatter_walk walk;
|
||||
unsigned int buflen = 0;
|
||||
|
||||
scatterwalk_start(&walk, req->src);
|
||||
|
||||
do {
|
||||
u32 n = scatterwalk_clamp(&walk, assoclen);
|
||||
u8 *p, *ptr;
|
||||
|
||||
if (!n) {
|
||||
scatterwalk_start(&walk, sg_next(walk.sg));
|
||||
n = scatterwalk_clamp(&walk, assoclen);
|
||||
}
|
||||
|
||||
p = ptr = scatterwalk_map(&walk);
|
||||
assoclen -= n;
|
||||
scatterwalk_advance(&walk, n);
|
||||
|
||||
if (n + buflen < GHASH_BLOCK_SIZE) {
|
||||
memcpy(&buffer[buflen], ptr, n);
|
||||
buflen += n;
|
||||
} else {
|
||||
unsigned int nblocks;
|
||||
|
||||
if (buflen) {
|
||||
unsigned int l = GHASH_BLOCK_SIZE - buflen;
|
||||
|
||||
memcpy(&buffer[buflen], ptr, l);
|
||||
ptr += l;
|
||||
n -= l;
|
||||
|
||||
pmull_ghash_update(ctx->ghash_table, ghash,
|
||||
buffer, 1);
|
||||
}
|
||||
|
||||
nblocks = n / GHASH_BLOCK_SIZE;
|
||||
if (nblocks) {
|
||||
pmull_ghash_update(ctx->ghash_table, ghash,
|
||||
ptr, nblocks);
|
||||
ptr += nblocks * GHASH_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
buflen = n % GHASH_BLOCK_SIZE;
|
||||
if (buflen)
|
||||
memcpy(&buffer[0], ptr, buflen);
|
||||
}
|
||||
|
||||
scatterwalk_unmap(p);
|
||||
scatterwalk_done(&walk, 0, assoclen);
|
||||
} while (assoclen);
|
||||
|
||||
/* padding with '0' */
|
||||
if (buflen) {
|
||||
memset(&buffer[buflen], 0, GHASH_BLOCK_SIZE - buflen);
|
||||
pmull_ghash_update(ctx->ghash_table, ghash, buffer, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int gcm_crypt(struct aead_request *req, struct skcipher_walk *walk,
|
||||
struct sm4_gcm_ctx *ctx, u8 ghash[],
|
||||
void (*sm4_ce_pmull_gcm_crypt)(const u32 *rkey_enc,
|
||||
u8 *dst, const u8 *src, u8 *iv,
|
||||
unsigned int nbytes, u8 *ghash,
|
||||
const u8 *ghash_table, const u8 *lengths))
|
||||
{
|
||||
u8 __aligned(8) iv[SM4_BLOCK_SIZE];
|
||||
be128 __aligned(8) lengths;
|
||||
int err;
|
||||
|
||||
memset(ghash, 0, SM4_BLOCK_SIZE);
|
||||
|
||||
lengths.a = cpu_to_be64(req->assoclen * 8);
|
||||
lengths.b = cpu_to_be64(walk->total * 8);
|
||||
|
||||
memcpy(iv, walk->iv, GCM_IV_SIZE);
|
||||
put_unaligned_be32(2, iv + GCM_IV_SIZE);
|
||||
|
||||
kernel_neon_begin();
|
||||
|
||||
if (req->assoclen)
|
||||
gcm_calculate_auth_mac(req, ghash);
|
||||
|
||||
do {
|
||||
unsigned int tail = walk->nbytes % SM4_BLOCK_SIZE;
|
||||
const u8 *src = walk->src.virt.addr;
|
||||
u8 *dst = walk->dst.virt.addr;
|
||||
|
||||
if (walk->nbytes == walk->total) {
|
||||
tail = 0;
|
||||
|
||||
sm4_ce_pmull_gcm_crypt(ctx->key.rkey_enc, dst, src, iv,
|
||||
walk->nbytes, ghash,
|
||||
ctx->ghash_table,
|
||||
(const u8 *)&lengths);
|
||||
} else if (walk->nbytes - tail) {
|
||||
sm4_ce_pmull_gcm_crypt(ctx->key.rkey_enc, dst, src, iv,
|
||||
walk->nbytes - tail, ghash,
|
||||
ctx->ghash_table, NULL);
|
||||
}
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
err = skcipher_walk_done(walk, tail);
|
||||
if (err)
|
||||
return err;
|
||||
if (walk->nbytes)
|
||||
kernel_neon_begin();
|
||||
} while (walk->nbytes > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gcm_encrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
struct sm4_gcm_ctx *ctx = crypto_aead_ctx(aead);
|
||||
u8 __aligned(8) ghash[SM4_BLOCK_SIZE];
|
||||
struct skcipher_walk walk;
|
||||
int err;
|
||||
|
||||
err = skcipher_walk_aead_encrypt(&walk, req, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = gcm_crypt(req, &walk, ctx, ghash, sm4_ce_pmull_gcm_enc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* copy authtag to end of dst */
|
||||
scatterwalk_map_and_copy(ghash, req->dst, req->assoclen + req->cryptlen,
|
||||
crypto_aead_authsize(aead), 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gcm_decrypt(struct aead_request *req)
|
||||
{
|
||||
struct crypto_aead *aead = crypto_aead_reqtfm(req);
|
||||
unsigned int authsize = crypto_aead_authsize(aead);
|
||||
struct sm4_gcm_ctx *ctx = crypto_aead_ctx(aead);
|
||||
u8 __aligned(8) ghash[SM4_BLOCK_SIZE];
|
||||
u8 authtag[SM4_BLOCK_SIZE];
|
||||
struct skcipher_walk walk;
|
||||
int err;
|
||||
|
||||
err = skcipher_walk_aead_decrypt(&walk, req, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = gcm_crypt(req, &walk, ctx, ghash, sm4_ce_pmull_gcm_dec);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* compare calculated auth tag with the stored one */
|
||||
scatterwalk_map_and_copy(authtag, req->src,
|
||||
req->assoclen + req->cryptlen - authsize,
|
||||
authsize, 0);
|
||||
|
||||
if (crypto_memneq(authtag, ghash, authsize))
|
||||
return -EBADMSG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct aead_alg sm4_gcm_alg = {
|
||||
.base = {
|
||||
.cra_name = "gcm(sm4)",
|
||||
.cra_driver_name = "gcm-sm4-ce",
|
||||
.cra_priority = 400,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct sm4_gcm_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
},
|
||||
.ivsize = GCM_IV_SIZE,
|
||||
.chunksize = SM4_BLOCK_SIZE,
|
||||
.maxauthsize = SM4_BLOCK_SIZE,
|
||||
.setkey = gcm_setkey,
|
||||
.setauthsize = gcm_setauthsize,
|
||||
.encrypt = gcm_encrypt,
|
||||
.decrypt = gcm_decrypt,
|
||||
};
|
||||
|
||||
static int __init sm4_ce_gcm_init(void)
|
||||
{
|
||||
if (!cpu_have_named_feature(PMULL))
|
||||
return -ENODEV;
|
||||
|
||||
return crypto_register_aead(&sm4_gcm_alg);
|
||||
}
|
||||
|
||||
static void __exit sm4_ce_gcm_exit(void)
|
||||
{
|
||||
crypto_unregister_aead(&sm4_gcm_alg);
|
||||
}
|
||||
|
||||
static const struct cpu_feature __maybe_unused sm4_ce_gcm_cpu_feature[] = {
|
||||
{ cpu_feature(PMULL) },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(cpu, sm4_ce_gcm_cpu_feature);
|
||||
|
||||
module_cpu_feature_match(SM4, sm4_ce_gcm_init);
|
||||
module_exit(sm4_ce_gcm_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Synchronous SM4 in GCM mode using ARMv8 Crypto Extensions");
|
||||
MODULE_ALIAS_CRYPTO("gcm(sm4)");
|
||||
MODULE_AUTHOR("Tianjia Zhang <tianjia.zhang@linux.alibaba.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
+544
-31
@@ -14,8 +14,12 @@
|
||||
#include <linux/cpufeature.h>
|
||||
#include <asm/neon.h>
|
||||
#include <asm/simd.h>
|
||||
#include <crypto/b128ops.h>
|
||||
#include <crypto/internal/simd.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/xts.h>
|
||||
#include <crypto/sm4.h>
|
||||
|
||||
#define BYTES2BLKS(nbytes) ((nbytes) >> 4)
|
||||
@@ -26,15 +30,48 @@ asmlinkage void sm4_ce_crypt_block(const u32 *rkey, u8 *dst, const u8 *src);
|
||||
asmlinkage void sm4_ce_crypt(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
unsigned int nblks);
|
||||
asmlinkage void sm4_ce_cbc_enc(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblks);
|
||||
u8 *iv, unsigned int nblocks);
|
||||
asmlinkage void sm4_ce_cbc_dec(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblks);
|
||||
u8 *iv, unsigned int nblocks);
|
||||
asmlinkage void sm4_ce_cbc_cts_enc(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nbytes);
|
||||
asmlinkage void sm4_ce_cbc_cts_dec(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nbytes);
|
||||
asmlinkage void sm4_ce_cfb_enc(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblks);
|
||||
asmlinkage void sm4_ce_cfb_dec(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblks);
|
||||
asmlinkage void sm4_ce_ctr_enc(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblks);
|
||||
asmlinkage void sm4_ce_xts_enc(const u32 *rkey1, u8 *dst, const u8 *src,
|
||||
u8 *tweak, unsigned int nbytes,
|
||||
const u32 *rkey2_enc);
|
||||
asmlinkage void sm4_ce_xts_dec(const u32 *rkey1, u8 *dst, const u8 *src,
|
||||
u8 *tweak, unsigned int nbytes,
|
||||
const u32 *rkey2_enc);
|
||||
asmlinkage void sm4_ce_mac_update(const u32 *rkey_enc, u8 *digest,
|
||||
const u8 *src, unsigned int nblocks,
|
||||
bool enc_before, bool enc_after);
|
||||
|
||||
EXPORT_SYMBOL(sm4_ce_expand_key);
|
||||
EXPORT_SYMBOL(sm4_ce_crypt_block);
|
||||
EXPORT_SYMBOL(sm4_ce_cbc_enc);
|
||||
EXPORT_SYMBOL(sm4_ce_cfb_enc);
|
||||
|
||||
struct sm4_xts_ctx {
|
||||
struct sm4_ctx key1;
|
||||
struct sm4_ctx key2;
|
||||
};
|
||||
|
||||
struct sm4_mac_tfm_ctx {
|
||||
struct sm4_ctx key;
|
||||
u8 __aligned(8) consts[];
|
||||
};
|
||||
|
||||
struct sm4_mac_desc_ctx {
|
||||
unsigned int len;
|
||||
u8 digest[SM4_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
static int sm4_setkey(struct crypto_skcipher *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
@@ -44,8 +81,33 @@ static int sm4_setkey(struct crypto_skcipher *tfm, const u8 *key,
|
||||
if (key_len != SM4_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
kernel_neon_begin();
|
||||
sm4_ce_expand_key(key, ctx->rkey_enc, ctx->rkey_dec,
|
||||
crypto_sm4_fk, crypto_sm4_ck);
|
||||
kernel_neon_end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm4_xts_setkey(struct crypto_skcipher *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct sm4_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
int ret;
|
||||
|
||||
if (key_len != SM4_KEY_SIZE * 2)
|
||||
return -EINVAL;
|
||||
|
||||
ret = xts_verify_key(tfm, key, key_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
kernel_neon_begin();
|
||||
sm4_ce_expand_key(key, ctx->key1.rkey_enc,
|
||||
ctx->key1.rkey_dec, crypto_sm4_fk, crypto_sm4_ck);
|
||||
sm4_ce_expand_key(&key[SM4_KEY_SIZE], ctx->key2.rkey_enc,
|
||||
ctx->key2.rkey_dec, crypto_sm4_fk, crypto_sm4_ck);
|
||||
kernel_neon_end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -94,66 +156,128 @@ static int sm4_ecb_decrypt(struct skcipher_request *req)
|
||||
return sm4_ecb_do_crypt(req, ctx->rkey_dec);
|
||||
}
|
||||
|
||||
static int sm4_cbc_encrypt(struct skcipher_request *req)
|
||||
static int sm4_cbc_crypt(struct skcipher_request *req,
|
||||
struct sm4_ctx *ctx, bool encrypt)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
struct skcipher_walk walk;
|
||||
unsigned int nbytes;
|
||||
int err;
|
||||
|
||||
err = skcipher_walk_virt(&walk, req, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
while ((nbytes = walk.nbytes) > 0) {
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
unsigned int nblks;
|
||||
unsigned int nblocks;
|
||||
|
||||
kernel_neon_begin();
|
||||
nblocks = nbytes / SM4_BLOCK_SIZE;
|
||||
if (nblocks) {
|
||||
kernel_neon_begin();
|
||||
|
||||
nblks = BYTES2BLKS(nbytes);
|
||||
if (nblks) {
|
||||
sm4_ce_cbc_enc(ctx->rkey_enc, dst, src, walk.iv, nblks);
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
if (encrypt)
|
||||
sm4_ce_cbc_enc(ctx->rkey_enc, dst, src,
|
||||
walk.iv, nblocks);
|
||||
else
|
||||
sm4_ce_cbc_dec(ctx->rkey_dec, dst, src,
|
||||
walk.iv, nblocks);
|
||||
|
||||
kernel_neon_end();
|
||||
}
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
err = skcipher_walk_done(&walk, nbytes);
|
||||
err = skcipher_walk_done(&walk, nbytes % SM4_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sm4_cbc_encrypt(struct skcipher_request *req)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
|
||||
return sm4_cbc_crypt(req, ctx, true);
|
||||
}
|
||||
|
||||
static int sm4_cbc_decrypt(struct skcipher_request *req)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
|
||||
return sm4_cbc_crypt(req, ctx, false);
|
||||
}
|
||||
|
||||
static int sm4_cbc_cts_crypt(struct skcipher_request *req, bool encrypt)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
struct scatterlist *src = req->src;
|
||||
struct scatterlist *dst = req->dst;
|
||||
struct scatterlist sg_src[2], sg_dst[2];
|
||||
struct skcipher_request subreq;
|
||||
struct skcipher_walk walk;
|
||||
unsigned int nbytes;
|
||||
int cbc_blocks;
|
||||
int err;
|
||||
|
||||
err = skcipher_walk_virt(&walk, req, false);
|
||||
if (req->cryptlen < SM4_BLOCK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
while ((nbytes = walk.nbytes) > 0) {
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
unsigned int nblks;
|
||||
if (req->cryptlen == SM4_BLOCK_SIZE)
|
||||
return sm4_cbc_crypt(req, ctx, encrypt);
|
||||
|
||||
kernel_neon_begin();
|
||||
skcipher_request_set_tfm(&subreq, tfm);
|
||||
skcipher_request_set_callback(&subreq, skcipher_request_flags(req),
|
||||
NULL, NULL);
|
||||
|
||||
nblks = BYTES2BLKS(nbytes);
|
||||
if (nblks) {
|
||||
sm4_ce_cbc_dec(ctx->rkey_dec, dst, src, walk.iv, nblks);
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
}
|
||||
/* handle the CBC cryption part */
|
||||
cbc_blocks = DIV_ROUND_UP(req->cryptlen, SM4_BLOCK_SIZE) - 2;
|
||||
if (cbc_blocks) {
|
||||
skcipher_request_set_crypt(&subreq, src, dst,
|
||||
cbc_blocks * SM4_BLOCK_SIZE,
|
||||
req->iv);
|
||||
|
||||
kernel_neon_end();
|
||||
err = sm4_cbc_crypt(&subreq, ctx, encrypt);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = skcipher_walk_done(&walk, nbytes);
|
||||
dst = src = scatterwalk_ffwd(sg_src, src, subreq.cryptlen);
|
||||
if (req->dst != req->src)
|
||||
dst = scatterwalk_ffwd(sg_dst, req->dst,
|
||||
subreq.cryptlen);
|
||||
}
|
||||
|
||||
return err;
|
||||
/* handle ciphertext stealing */
|
||||
skcipher_request_set_crypt(&subreq, src, dst,
|
||||
req->cryptlen - cbc_blocks * SM4_BLOCK_SIZE,
|
||||
req->iv);
|
||||
|
||||
err = skcipher_walk_virt(&walk, &subreq, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
kernel_neon_begin();
|
||||
|
||||
if (encrypt)
|
||||
sm4_ce_cbc_cts_enc(ctx->rkey_enc, walk.dst.virt.addr,
|
||||
walk.src.virt.addr, walk.iv, walk.nbytes);
|
||||
else
|
||||
sm4_ce_cbc_cts_dec(ctx->rkey_dec, walk.dst.virt.addr,
|
||||
walk.src.virt.addr, walk.iv, walk.nbytes);
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
return skcipher_walk_done(&walk, 0);
|
||||
}
|
||||
|
||||
static int sm4_cbc_cts_encrypt(struct skcipher_request *req)
|
||||
{
|
||||
return sm4_cbc_cts_crypt(req, true);
|
||||
}
|
||||
|
||||
static int sm4_cbc_cts_decrypt(struct skcipher_request *req)
|
||||
{
|
||||
return sm4_cbc_cts_crypt(req, false);
|
||||
}
|
||||
|
||||
static int sm4_cfb_encrypt(struct skcipher_request *req)
|
||||
@@ -283,6 +407,111 @@ static int sm4_ctr_crypt(struct skcipher_request *req)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sm4_xts_crypt(struct skcipher_request *req, bool encrypt)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct sm4_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
int tail = req->cryptlen % SM4_BLOCK_SIZE;
|
||||
const u32 *rkey2_enc = ctx->key2.rkey_enc;
|
||||
struct scatterlist sg_src[2], sg_dst[2];
|
||||
struct skcipher_request subreq;
|
||||
struct scatterlist *src, *dst;
|
||||
struct skcipher_walk walk;
|
||||
unsigned int nbytes;
|
||||
int err;
|
||||
|
||||
if (req->cryptlen < SM4_BLOCK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
err = skcipher_walk_virt(&walk, req, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (unlikely(tail > 0 && walk.nbytes < walk.total)) {
|
||||
int nblocks = DIV_ROUND_UP(req->cryptlen, SM4_BLOCK_SIZE) - 2;
|
||||
|
||||
skcipher_walk_abort(&walk);
|
||||
|
||||
skcipher_request_set_tfm(&subreq, tfm);
|
||||
skcipher_request_set_callback(&subreq,
|
||||
skcipher_request_flags(req),
|
||||
NULL, NULL);
|
||||
skcipher_request_set_crypt(&subreq, req->src, req->dst,
|
||||
nblocks * SM4_BLOCK_SIZE, req->iv);
|
||||
|
||||
err = skcipher_walk_virt(&walk, &subreq, false);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
tail = 0;
|
||||
}
|
||||
|
||||
while ((nbytes = walk.nbytes) >= SM4_BLOCK_SIZE) {
|
||||
if (nbytes < walk.total)
|
||||
nbytes &= ~(SM4_BLOCK_SIZE - 1);
|
||||
|
||||
kernel_neon_begin();
|
||||
|
||||
if (encrypt)
|
||||
sm4_ce_xts_enc(ctx->key1.rkey_enc, walk.dst.virt.addr,
|
||||
walk.src.virt.addr, walk.iv, nbytes,
|
||||
rkey2_enc);
|
||||
else
|
||||
sm4_ce_xts_dec(ctx->key1.rkey_dec, walk.dst.virt.addr,
|
||||
walk.src.virt.addr, walk.iv, nbytes,
|
||||
rkey2_enc);
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
rkey2_enc = NULL;
|
||||
|
||||
err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (likely(tail == 0))
|
||||
return 0;
|
||||
|
||||
/* handle ciphertext stealing */
|
||||
|
||||
dst = src = scatterwalk_ffwd(sg_src, req->src, subreq.cryptlen);
|
||||
if (req->dst != req->src)
|
||||
dst = scatterwalk_ffwd(sg_dst, req->dst, subreq.cryptlen);
|
||||
|
||||
skcipher_request_set_crypt(&subreq, src, dst, SM4_BLOCK_SIZE + tail,
|
||||
req->iv);
|
||||
|
||||
err = skcipher_walk_virt(&walk, &subreq, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
kernel_neon_begin();
|
||||
|
||||
if (encrypt)
|
||||
sm4_ce_xts_enc(ctx->key1.rkey_enc, walk.dst.virt.addr,
|
||||
walk.src.virt.addr, walk.iv, walk.nbytes,
|
||||
rkey2_enc);
|
||||
else
|
||||
sm4_ce_xts_dec(ctx->key1.rkey_dec, walk.dst.virt.addr,
|
||||
walk.src.virt.addr, walk.iv, walk.nbytes,
|
||||
rkey2_enc);
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
return skcipher_walk_done(&walk, 0);
|
||||
}
|
||||
|
||||
static int sm4_xts_encrypt(struct skcipher_request *req)
|
||||
{
|
||||
return sm4_xts_crypt(req, true);
|
||||
}
|
||||
|
||||
static int sm4_xts_decrypt(struct skcipher_request *req)
|
||||
{
|
||||
return sm4_xts_crypt(req, false);
|
||||
}
|
||||
|
||||
static struct skcipher_alg sm4_algs[] = {
|
||||
{
|
||||
.base = {
|
||||
@@ -345,28 +574,312 @@ static struct skcipher_alg sm4_algs[] = {
|
||||
.setkey = sm4_setkey,
|
||||
.encrypt = sm4_ctr_crypt,
|
||||
.decrypt = sm4_ctr_crypt,
|
||||
}, {
|
||||
.base = {
|
||||
.cra_name = "cts(cbc(sm4))",
|
||||
.cra_driver_name = "cts-cbc-sm4-ce",
|
||||
.cra_priority = 400,
|
||||
.cra_blocksize = SM4_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct sm4_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
},
|
||||
.min_keysize = SM4_KEY_SIZE,
|
||||
.max_keysize = SM4_KEY_SIZE,
|
||||
.ivsize = SM4_BLOCK_SIZE,
|
||||
.walksize = SM4_BLOCK_SIZE * 2,
|
||||
.setkey = sm4_setkey,
|
||||
.encrypt = sm4_cbc_cts_encrypt,
|
||||
.decrypt = sm4_cbc_cts_decrypt,
|
||||
}, {
|
||||
.base = {
|
||||
.cra_name = "xts(sm4)",
|
||||
.cra_driver_name = "xts-sm4-ce",
|
||||
.cra_priority = 400,
|
||||
.cra_blocksize = SM4_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct sm4_xts_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
},
|
||||
.min_keysize = SM4_KEY_SIZE * 2,
|
||||
.max_keysize = SM4_KEY_SIZE * 2,
|
||||
.ivsize = SM4_BLOCK_SIZE,
|
||||
.walksize = SM4_BLOCK_SIZE * 2,
|
||||
.setkey = sm4_xts_setkey,
|
||||
.encrypt = sm4_xts_encrypt,
|
||||
.decrypt = sm4_xts_decrypt,
|
||||
}
|
||||
};
|
||||
|
||||
static int sm4_cbcmac_setkey(struct crypto_shash *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct sm4_mac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
|
||||
|
||||
if (key_len != SM4_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
kernel_neon_begin();
|
||||
sm4_ce_expand_key(key, ctx->key.rkey_enc, ctx->key.rkey_dec,
|
||||
crypto_sm4_fk, crypto_sm4_ck);
|
||||
kernel_neon_end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm4_cmac_setkey(struct crypto_shash *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct sm4_mac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
|
||||
be128 *consts = (be128 *)ctx->consts;
|
||||
u64 a, b;
|
||||
|
||||
if (key_len != SM4_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
memset(consts, 0, SM4_BLOCK_SIZE);
|
||||
|
||||
kernel_neon_begin();
|
||||
|
||||
sm4_ce_expand_key(key, ctx->key.rkey_enc, ctx->key.rkey_dec,
|
||||
crypto_sm4_fk, crypto_sm4_ck);
|
||||
|
||||
/* encrypt the zero block */
|
||||
sm4_ce_crypt_block(ctx->key.rkey_enc, (u8 *)consts, (const u8 *)consts);
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
/* gf(2^128) multiply zero-ciphertext with u and u^2 */
|
||||
a = be64_to_cpu(consts[0].a);
|
||||
b = be64_to_cpu(consts[0].b);
|
||||
consts[0].a = cpu_to_be64((a << 1) | (b >> 63));
|
||||
consts[0].b = cpu_to_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0));
|
||||
|
||||
a = be64_to_cpu(consts[0].a);
|
||||
b = be64_to_cpu(consts[0].b);
|
||||
consts[1].a = cpu_to_be64((a << 1) | (b >> 63));
|
||||
consts[1].b = cpu_to_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm4_xcbc_setkey(struct crypto_shash *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct sm4_mac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
|
||||
u8 __aligned(8) key2[SM4_BLOCK_SIZE];
|
||||
static u8 const ks[3][SM4_BLOCK_SIZE] = {
|
||||
{ [0 ... SM4_BLOCK_SIZE - 1] = 0x1},
|
||||
{ [0 ... SM4_BLOCK_SIZE - 1] = 0x2},
|
||||
{ [0 ... SM4_BLOCK_SIZE - 1] = 0x3},
|
||||
};
|
||||
|
||||
if (key_len != SM4_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
kernel_neon_begin();
|
||||
|
||||
sm4_ce_expand_key(key, ctx->key.rkey_enc, ctx->key.rkey_dec,
|
||||
crypto_sm4_fk, crypto_sm4_ck);
|
||||
|
||||
sm4_ce_crypt_block(ctx->key.rkey_enc, key2, ks[0]);
|
||||
sm4_ce_crypt(ctx->key.rkey_enc, ctx->consts, ks[1], 2);
|
||||
|
||||
sm4_ce_expand_key(key2, ctx->key.rkey_enc, ctx->key.rkey_dec,
|
||||
crypto_sm4_fk, crypto_sm4_ck);
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm4_mac_init(struct shash_desc *desc)
|
||||
{
|
||||
struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc);
|
||||
|
||||
memset(ctx->digest, 0, SM4_BLOCK_SIZE);
|
||||
ctx->len = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm4_mac_update(struct shash_desc *desc, const u8 *p,
|
||||
unsigned int len)
|
||||
{
|
||||
struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
|
||||
struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc);
|
||||
unsigned int l, nblocks;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
if (ctx->len || ctx->len + len < SM4_BLOCK_SIZE) {
|
||||
l = min(len, SM4_BLOCK_SIZE - ctx->len);
|
||||
|
||||
crypto_xor(ctx->digest + ctx->len, p, l);
|
||||
ctx->len += l;
|
||||
len -= l;
|
||||
p += l;
|
||||
}
|
||||
|
||||
if (len && (ctx->len % SM4_BLOCK_SIZE) == 0) {
|
||||
kernel_neon_begin();
|
||||
|
||||
if (len < SM4_BLOCK_SIZE && ctx->len == SM4_BLOCK_SIZE) {
|
||||
sm4_ce_crypt_block(tctx->key.rkey_enc,
|
||||
ctx->digest, ctx->digest);
|
||||
ctx->len = 0;
|
||||
} else {
|
||||
nblocks = len / SM4_BLOCK_SIZE;
|
||||
len %= SM4_BLOCK_SIZE;
|
||||
|
||||
sm4_ce_mac_update(tctx->key.rkey_enc, ctx->digest, p,
|
||||
nblocks, (ctx->len == SM4_BLOCK_SIZE),
|
||||
(len != 0));
|
||||
|
||||
p += nblocks * SM4_BLOCK_SIZE;
|
||||
|
||||
if (len == 0)
|
||||
ctx->len = SM4_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
if (len) {
|
||||
crypto_xor(ctx->digest, p, len);
|
||||
ctx->len = len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm4_cmac_final(struct shash_desc *desc, u8 *out)
|
||||
{
|
||||
struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
|
||||
struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc);
|
||||
const u8 *consts = tctx->consts;
|
||||
|
||||
if (ctx->len != SM4_BLOCK_SIZE) {
|
||||
ctx->digest[ctx->len] ^= 0x80;
|
||||
consts += SM4_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
kernel_neon_begin();
|
||||
sm4_ce_mac_update(tctx->key.rkey_enc, ctx->digest, consts, 1,
|
||||
false, true);
|
||||
kernel_neon_end();
|
||||
|
||||
memcpy(out, ctx->digest, SM4_BLOCK_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm4_cbcmac_final(struct shash_desc *desc, u8 *out)
|
||||
{
|
||||
struct sm4_mac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
|
||||
struct sm4_mac_desc_ctx *ctx = shash_desc_ctx(desc);
|
||||
|
||||
if (ctx->len) {
|
||||
kernel_neon_begin();
|
||||
sm4_ce_crypt_block(tctx->key.rkey_enc, ctx->digest,
|
||||
ctx->digest);
|
||||
kernel_neon_end();
|
||||
}
|
||||
|
||||
memcpy(out, ctx->digest, SM4_BLOCK_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct shash_alg sm4_mac_algs[] = {
|
||||
{
|
||||
.base = {
|
||||
.cra_name = "cmac(sm4)",
|
||||
.cra_driver_name = "cmac-sm4-ce",
|
||||
.cra_priority = 400,
|
||||
.cra_blocksize = SM4_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx)
|
||||
+ SM4_BLOCK_SIZE * 2,
|
||||
.cra_module = THIS_MODULE,
|
||||
},
|
||||
.digestsize = SM4_BLOCK_SIZE,
|
||||
.init = sm4_mac_init,
|
||||
.update = sm4_mac_update,
|
||||
.final = sm4_cmac_final,
|
||||
.setkey = sm4_cmac_setkey,
|
||||
.descsize = sizeof(struct sm4_mac_desc_ctx),
|
||||
}, {
|
||||
.base = {
|
||||
.cra_name = "xcbc(sm4)",
|
||||
.cra_driver_name = "xcbc-sm4-ce",
|
||||
.cra_priority = 400,
|
||||
.cra_blocksize = SM4_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx)
|
||||
+ SM4_BLOCK_SIZE * 2,
|
||||
.cra_module = THIS_MODULE,
|
||||
},
|
||||
.digestsize = SM4_BLOCK_SIZE,
|
||||
.init = sm4_mac_init,
|
||||
.update = sm4_mac_update,
|
||||
.final = sm4_cmac_final,
|
||||
.setkey = sm4_xcbc_setkey,
|
||||
.descsize = sizeof(struct sm4_mac_desc_ctx),
|
||||
}, {
|
||||
.base = {
|
||||
.cra_name = "cbcmac(sm4)",
|
||||
.cra_driver_name = "cbcmac-sm4-ce",
|
||||
.cra_priority = 400,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct sm4_mac_tfm_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
},
|
||||
.digestsize = SM4_BLOCK_SIZE,
|
||||
.init = sm4_mac_init,
|
||||
.update = sm4_mac_update,
|
||||
.final = sm4_cbcmac_final,
|
||||
.setkey = sm4_cbcmac_setkey,
|
||||
.descsize = sizeof(struct sm4_mac_desc_ctx),
|
||||
}
|
||||
};
|
||||
|
||||
static int __init sm4_init(void)
|
||||
{
|
||||
return crypto_register_skciphers(sm4_algs, ARRAY_SIZE(sm4_algs));
|
||||
int err;
|
||||
|
||||
err = crypto_register_skciphers(sm4_algs, ARRAY_SIZE(sm4_algs));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = crypto_register_shashes(sm4_mac_algs, ARRAY_SIZE(sm4_mac_algs));
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
crypto_unregister_skciphers(sm4_algs, ARRAY_SIZE(sm4_algs));
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit sm4_exit(void)
|
||||
{
|
||||
crypto_unregister_shashes(sm4_mac_algs, ARRAY_SIZE(sm4_mac_algs));
|
||||
crypto_unregister_skciphers(sm4_algs, ARRAY_SIZE(sm4_algs));
|
||||
}
|
||||
|
||||
module_cpu_feature_match(SM4, sm4_init);
|
||||
module_exit(sm4_exit);
|
||||
|
||||
MODULE_DESCRIPTION("SM4 ECB/CBC/CFB/CTR using ARMv8 Crypto Extensions");
|
||||
MODULE_DESCRIPTION("SM4 ECB/CBC/CFB/CTR/XTS using ARMv8 Crypto Extensions");
|
||||
MODULE_ALIAS_CRYPTO("sm4-ce");
|
||||
MODULE_ALIAS_CRYPTO("sm4");
|
||||
MODULE_ALIAS_CRYPTO("ecb(sm4)");
|
||||
MODULE_ALIAS_CRYPTO("cbc(sm4)");
|
||||
MODULE_ALIAS_CRYPTO("cfb(sm4)");
|
||||
MODULE_ALIAS_CRYPTO("ctr(sm4)");
|
||||
MODULE_ALIAS_CRYPTO("cts(cbc(sm4))");
|
||||
MODULE_ALIAS_CRYPTO("xts(sm4)");
|
||||
MODULE_ALIAS_CRYPTO("cmac(sm4)");
|
||||
MODULE_ALIAS_CRYPTO("xcbc(sm4)");
|
||||
MODULE_ALIAS_CRYPTO("cbcmac(sm4)");
|
||||
MODULE_AUTHOR("Tianjia Zhang <tianjia.zhang@linux.alibaba.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* SM4 common functions for Crypto Extensions
|
||||
* Copyright (C) 2022 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
|
||||
*/
|
||||
|
||||
void sm4_ce_expand_key(const u8 *key, u32 *rkey_enc, u32 *rkey_dec,
|
||||
const u32 *fk, const u32 *ck);
|
||||
|
||||
void sm4_ce_crypt_block(const u32 *rkey, u8 *dst, const u8 *src);
|
||||
|
||||
void sm4_ce_cbc_enc(const u32 *rkey_enc, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblocks);
|
||||
|
||||
void sm4_ce_cfb_enc(const u32 *rkey_enc, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblocks);
|
||||
+398
-206
@@ -18,6 +18,11 @@
|
||||
#define RTMP2 v10
|
||||
#define RTMP3 v11
|
||||
|
||||
#define RTMP4 v12
|
||||
#define RTMP5 v13
|
||||
#define RTMP6 v14
|
||||
#define RTMP7 v15
|
||||
|
||||
#define RX0 v12
|
||||
#define RX1 v13
|
||||
#define RKEY v14
|
||||
@@ -25,7 +30,7 @@
|
||||
|
||||
/* Helper macros. */
|
||||
|
||||
#define PREPARE \
|
||||
#define SM4_PREPARE() \
|
||||
adr_l x5, crypto_sm4_sbox; \
|
||||
ld1 {v16.16b-v19.16b}, [x5], #64; \
|
||||
ld1 {v20.16b-v23.16b}, [x5], #64; \
|
||||
@@ -42,7 +47,25 @@
|
||||
zip1 s2.2d, RTMP2.2d, RTMP3.2d; \
|
||||
zip2 s3.2d, RTMP2.2d, RTMP3.2d;
|
||||
|
||||
#define rotate_clockwise_90(s0, s1, s2, s3) \
|
||||
#define transpose_4x4_2x(s0, s1, s2, s3, s4, s5, s6, s7) \
|
||||
zip1 RTMP0.4s, s0.4s, s1.4s; \
|
||||
zip1 RTMP1.4s, s2.4s, s3.4s; \
|
||||
zip2 RTMP2.4s, s0.4s, s1.4s; \
|
||||
zip2 RTMP3.4s, s2.4s, s3.4s; \
|
||||
zip1 RTMP4.4s, s4.4s, s5.4s; \
|
||||
zip1 RTMP5.4s, s6.4s, s7.4s; \
|
||||
zip2 RTMP6.4s, s4.4s, s5.4s; \
|
||||
zip2 RTMP7.4s, s6.4s, s7.4s; \
|
||||
zip1 s0.2d, RTMP0.2d, RTMP1.2d; \
|
||||
zip2 s1.2d, RTMP0.2d, RTMP1.2d; \
|
||||
zip1 s2.2d, RTMP2.2d, RTMP3.2d; \
|
||||
zip2 s3.2d, RTMP2.2d, RTMP3.2d; \
|
||||
zip1 s4.2d, RTMP4.2d, RTMP5.2d; \
|
||||
zip2 s5.2d, RTMP4.2d, RTMP5.2d; \
|
||||
zip1 s6.2d, RTMP6.2d, RTMP7.2d; \
|
||||
zip2 s7.2d, RTMP6.2d, RTMP7.2d;
|
||||
|
||||
#define rotate_clockwise_4x4(s0, s1, s2, s3) \
|
||||
zip1 RTMP0.4s, s1.4s, s0.4s; \
|
||||
zip2 RTMP1.4s, s1.4s, s0.4s; \
|
||||
zip1 RTMP2.4s, s3.4s, s2.4s; \
|
||||
@@ -52,6 +75,24 @@
|
||||
zip1 s2.2d, RTMP3.2d, RTMP1.2d; \
|
||||
zip2 s3.2d, RTMP3.2d, RTMP1.2d;
|
||||
|
||||
#define rotate_clockwise_4x4_2x(s0, s1, s2, s3, s4, s5, s6, s7) \
|
||||
zip1 RTMP0.4s, s1.4s, s0.4s; \
|
||||
zip1 RTMP2.4s, s3.4s, s2.4s; \
|
||||
zip2 RTMP1.4s, s1.4s, s0.4s; \
|
||||
zip2 RTMP3.4s, s3.4s, s2.4s; \
|
||||
zip1 RTMP4.4s, s5.4s, s4.4s; \
|
||||
zip1 RTMP6.4s, s7.4s, s6.4s; \
|
||||
zip2 RTMP5.4s, s5.4s, s4.4s; \
|
||||
zip2 RTMP7.4s, s7.4s, s6.4s; \
|
||||
zip1 s0.2d, RTMP2.2d, RTMP0.2d; \
|
||||
zip2 s1.2d, RTMP2.2d, RTMP0.2d; \
|
||||
zip1 s2.2d, RTMP3.2d, RTMP1.2d; \
|
||||
zip2 s3.2d, RTMP3.2d, RTMP1.2d; \
|
||||
zip1 s4.2d, RTMP6.2d, RTMP4.2d; \
|
||||
zip2 s5.2d, RTMP6.2d, RTMP4.2d; \
|
||||
zip1 s6.2d, RTMP7.2d, RTMP5.2d; \
|
||||
zip2 s7.2d, RTMP7.2d, RTMP5.2d;
|
||||
|
||||
#define ROUND4(round, s0, s1, s2, s3) \
|
||||
dup RX0.4s, RKEY.s[round]; \
|
||||
/* rk ^ s1 ^ s2 ^ s3 */ \
|
||||
@@ -87,14 +128,7 @@
|
||||
/* s0 ^= RTMP3 */ \
|
||||
eor s0.16b, s0.16b, RTMP3.16b;
|
||||
|
||||
#define SM4_CRYPT_BLK4(b0, b1, b2, b3) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
rev32 b3.16b, b3.16b; \
|
||||
\
|
||||
transpose_4x4(b0, b1, b2, b3); \
|
||||
\
|
||||
#define SM4_CRYPT_BLK4_BE(b0, b1, b2, b3) \
|
||||
mov x6, 8; \
|
||||
4: \
|
||||
ld1 {RKEY.4s}, [x0], #16; \
|
||||
@@ -107,15 +141,23 @@
|
||||
\
|
||||
bne 4b; \
|
||||
\
|
||||
rotate_clockwise_90(b0, b1, b2, b3); \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
rev32 b3.16b, b3.16b; \
|
||||
\
|
||||
rotate_clockwise_4x4(b0, b1, b2, b3); \
|
||||
\
|
||||
/* repoint to rkey */ \
|
||||
sub x0, x0, #128;
|
||||
|
||||
#define SM4_CRYPT_BLK4(b0, b1, b2, b3) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
rev32 b3.16b, b3.16b; \
|
||||
SM4_CRYPT_BLK4_BE(b0, b1, b2, b3);
|
||||
|
||||
#define ROUND8(round, s0, s1, s2, s3, t0, t1, t2, t3) \
|
||||
/* rk ^ s1 ^ s2 ^ s3 */ \
|
||||
dup RX0.4s, RKEY.s[round]; \
|
||||
@@ -175,7 +217,7 @@
|
||||
eor s0.16b, s0.16b, RTMP0.16b; \
|
||||
eor t0.16b, t0.16b, RTMP1.16b;
|
||||
|
||||
#define SM4_CRYPT_BLK8(b0, b1, b2, b3, b4, b5, b6, b7) \
|
||||
#define SM4_CRYPT_BLK8_norotate(b0, b1, b2, b3, b4, b5, b6, b7) \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
@@ -185,9 +227,6 @@
|
||||
rev32 b6.16b, b6.16b; \
|
||||
rev32 b7.16b, b7.16b; \
|
||||
\
|
||||
transpose_4x4(b0, b1, b2, b3); \
|
||||
transpose_4x4(b4, b5, b6, b7); \
|
||||
\
|
||||
mov x6, 8; \
|
||||
8: \
|
||||
ld1 {RKEY.4s}, [x0], #16; \
|
||||
@@ -200,8 +239,6 @@
|
||||
\
|
||||
bne 8b; \
|
||||
\
|
||||
rotate_clockwise_90(b0, b1, b2, b3); \
|
||||
rotate_clockwise_90(b4, b5, b6, b7); \
|
||||
rev32 b0.16b, b0.16b; \
|
||||
rev32 b1.16b, b1.16b; \
|
||||
rev32 b2.16b, b2.16b; \
|
||||
@@ -214,274 +251,429 @@
|
||||
/* repoint to rkey */ \
|
||||
sub x0, x0, #128;
|
||||
|
||||
#define SM4_CRYPT_BLK8(b0, b1, b2, b3, b4, b5, b6, b7) \
|
||||
SM4_CRYPT_BLK8_norotate(b0, b1, b2, b3, b4, b5, b6, b7); \
|
||||
rotate_clockwise_4x4_2x(b0, b1, b2, b3, b4, b5, b6, b7); \
|
||||
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START_LOCAL(__sm4_neon_crypt_blk1_4)
|
||||
SYM_FUNC_START(sm4_neon_crypt)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* w3: num blocks (1..4)
|
||||
* w3: nblocks
|
||||
*/
|
||||
PREPARE;
|
||||
SM4_PREPARE()
|
||||
|
||||
ld1 {v0.16b}, [x2], #16;
|
||||
mov v1.16b, v0.16b;
|
||||
mov v2.16b, v0.16b;
|
||||
mov v3.16b, v0.16b;
|
||||
cmp w3, #2;
|
||||
blt .Lblk4_load_input_done;
|
||||
ld1 {v1.16b}, [x2], #16;
|
||||
beq .Lblk4_load_input_done;
|
||||
ld1 {v2.16b}, [x2], #16;
|
||||
cmp w3, #3;
|
||||
beq .Lblk4_load_input_done;
|
||||
ld1 {v3.16b}, [x2];
|
||||
.Lcrypt_loop_8x:
|
||||
sub w3, w3, #8
|
||||
tbnz w3, #31, .Lcrypt_4x
|
||||
|
||||
.Lblk4_load_input_done:
|
||||
SM4_CRYPT_BLK4(v0, v1, v2, v3);
|
||||
ld4 {v0.4s-v3.4s}, [x2], #64
|
||||
ld4 {v4.4s-v7.4s}, [x2], #64
|
||||
|
||||
st1 {v0.16b}, [x1], #16;
|
||||
cmp w3, #2;
|
||||
blt .Lblk4_store_output_done;
|
||||
st1 {v1.16b}, [x1], #16;
|
||||
beq .Lblk4_store_output_done;
|
||||
st1 {v2.16b}, [x1], #16;
|
||||
cmp w3, #3;
|
||||
beq .Lblk4_store_output_done;
|
||||
st1 {v3.16b}, [x1];
|
||||
SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7)
|
||||
|
||||
.Lblk4_store_output_done:
|
||||
ret;
|
||||
SYM_FUNC_END(__sm4_neon_crypt_blk1_4)
|
||||
st1 {v0.16b-v3.16b}, [x1], #64
|
||||
st1 {v4.16b-v7.16b}, [x1], #64
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_neon_crypt_blk1_8)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* w3: num blocks (1..8)
|
||||
*/
|
||||
cmp w3, #5;
|
||||
blt __sm4_neon_crypt_blk1_4;
|
||||
cbz w3, .Lcrypt_end
|
||||
b .Lcrypt_loop_8x
|
||||
|
||||
PREPARE;
|
||||
.Lcrypt_4x:
|
||||
add w3, w3, #8
|
||||
cmp w3, #4
|
||||
blt .Lcrypt_tail
|
||||
|
||||
ld1 {v0.16b-v3.16b}, [x2], #64;
|
||||
ld1 {v4.16b}, [x2], #16;
|
||||
mov v5.16b, v4.16b;
|
||||
mov v6.16b, v4.16b;
|
||||
mov v7.16b, v4.16b;
|
||||
beq .Lblk8_load_input_done;
|
||||
ld1 {v5.16b}, [x2], #16;
|
||||
cmp w3, #7;
|
||||
blt .Lblk8_load_input_done;
|
||||
ld1 {v6.16b}, [x2], #16;
|
||||
beq .Lblk8_load_input_done;
|
||||
ld1 {v7.16b}, [x2];
|
||||
sub w3, w3, #4
|
||||
|
||||
.Lblk8_load_input_done:
|
||||
SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7);
|
||||
ld4 {v0.4s-v3.4s}, [x2], #64
|
||||
|
||||
cmp w3, #6;
|
||||
st1 {v0.16b-v3.16b}, [x1], #64;
|
||||
st1 {v4.16b}, [x1], #16;
|
||||
blt .Lblk8_store_output_done;
|
||||
st1 {v5.16b}, [x1], #16;
|
||||
beq .Lblk8_store_output_done;
|
||||
st1 {v6.16b}, [x1], #16;
|
||||
cmp w3, #7;
|
||||
beq .Lblk8_store_output_done;
|
||||
st1 {v7.16b}, [x1];
|
||||
SM4_CRYPT_BLK4(v0, v1, v2, v3)
|
||||
|
||||
.Lblk8_store_output_done:
|
||||
ret;
|
||||
SYM_FUNC_END(sm4_neon_crypt_blk1_8)
|
||||
st1 {v0.16b-v3.16b}, [x1], #64
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_neon_crypt_blk8)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* w3: nblocks (multiples of 8)
|
||||
*/
|
||||
PREPARE;
|
||||
cbz w3, .Lcrypt_end
|
||||
|
||||
.Lcrypt_loop_blk:
|
||||
subs w3, w3, #8;
|
||||
bmi .Lcrypt_end;
|
||||
.Lcrypt_tail:
|
||||
cmp w3, #2
|
||||
ld1 {v0.16b}, [x2], #16
|
||||
blt .Lcrypt_tail_load_done
|
||||
ld1 {v1.16b}, [x2], #16
|
||||
beq .Lcrypt_tail_load_done
|
||||
ld1 {v2.16b}, [x2], #16
|
||||
|
||||
ld1 {v0.16b-v3.16b}, [x2], #64;
|
||||
ld1 {v4.16b-v7.16b}, [x2], #64;
|
||||
.Lcrypt_tail_load_done:
|
||||
transpose_4x4(v0, v1, v2, v3)
|
||||
|
||||
SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7);
|
||||
SM4_CRYPT_BLK4(v0, v1, v2, v3)
|
||||
|
||||
st1 {v0.16b-v3.16b}, [x1], #64;
|
||||
st1 {v4.16b-v7.16b}, [x1], #64;
|
||||
|
||||
b .Lcrypt_loop_blk;
|
||||
cmp w3, #2
|
||||
st1 {v0.16b}, [x1], #16
|
||||
blt .Lcrypt_end
|
||||
st1 {v1.16b}, [x1], #16
|
||||
beq .Lcrypt_end
|
||||
st1 {v2.16b}, [x1], #16
|
||||
|
||||
.Lcrypt_end:
|
||||
ret;
|
||||
SYM_FUNC_END(sm4_neon_crypt_blk8)
|
||||
ret
|
||||
SYM_FUNC_END(sm4_neon_crypt)
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_neon_cbc_dec_blk8)
|
||||
SYM_FUNC_START(sm4_neon_cbc_dec)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* x3: iv (big endian, 128 bit)
|
||||
* w4: nblocks (multiples of 8)
|
||||
* w4: nblocks
|
||||
*/
|
||||
PREPARE;
|
||||
SM4_PREPARE()
|
||||
|
||||
ld1 {RIV.16b}, [x3];
|
||||
ld1 {RIV.16b}, [x3]
|
||||
|
||||
.Lcbc_loop_blk:
|
||||
subs w4, w4, #8;
|
||||
bmi .Lcbc_end;
|
||||
.Lcbc_dec_loop_8x:
|
||||
sub w4, w4, #8
|
||||
tbnz w4, #31, .Lcbc_dec_4x
|
||||
|
||||
ld1 {v0.16b-v3.16b}, [x2], #64;
|
||||
ld1 {v4.16b-v7.16b}, [x2];
|
||||
ld4 {v0.4s-v3.4s}, [x2], #64
|
||||
ld4 {v4.4s-v7.4s}, [x2]
|
||||
|
||||
SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7);
|
||||
SM4_CRYPT_BLK8_norotate(v0, v1, v2, v3, v4, v5, v6, v7)
|
||||
|
||||
sub x2, x2, #64;
|
||||
eor v0.16b, v0.16b, RIV.16b;
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64;
|
||||
eor v1.16b, v1.16b, RTMP0.16b;
|
||||
eor v2.16b, v2.16b, RTMP1.16b;
|
||||
eor v3.16b, v3.16b, RTMP2.16b;
|
||||
st1 {v0.16b-v3.16b}, [x1], #64;
|
||||
/* Avoid overwriting the RIV register */
|
||||
rotate_clockwise_4x4(v0, v1, v2, v3)
|
||||
rotate_clockwise_4x4(v4, v5, v6, v7)
|
||||
|
||||
eor v4.16b, v4.16b, RTMP3.16b;
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64;
|
||||
eor v5.16b, v5.16b, RTMP0.16b;
|
||||
eor v6.16b, v6.16b, RTMP1.16b;
|
||||
eor v7.16b, v7.16b, RTMP2.16b;
|
||||
sub x2, x2, #64
|
||||
|
||||
mov RIV.16b, RTMP3.16b;
|
||||
st1 {v4.16b-v7.16b}, [x1], #64;
|
||||
eor v0.16b, v0.16b, RIV.16b
|
||||
|
||||
b .Lcbc_loop_blk;
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64
|
||||
ld1 {RTMP4.16b-RTMP7.16b}, [x2], #64
|
||||
|
||||
.Lcbc_end:
|
||||
eor v1.16b, v1.16b, RTMP0.16b
|
||||
eor v2.16b, v2.16b, RTMP1.16b
|
||||
eor v3.16b, v3.16b, RTMP2.16b
|
||||
eor v4.16b, v4.16b, RTMP3.16b
|
||||
eor v5.16b, v5.16b, RTMP4.16b
|
||||
eor v6.16b, v6.16b, RTMP5.16b
|
||||
eor v7.16b, v7.16b, RTMP6.16b
|
||||
|
||||
mov RIV.16b, RTMP7.16b
|
||||
|
||||
st1 {v0.16b-v3.16b}, [x1], #64
|
||||
st1 {v4.16b-v7.16b}, [x1], #64
|
||||
|
||||
cbz w4, .Lcbc_dec_end
|
||||
b .Lcbc_dec_loop_8x
|
||||
|
||||
.Lcbc_dec_4x:
|
||||
add w4, w4, #8
|
||||
cmp w4, #4
|
||||
blt .Lcbc_dec_tail
|
||||
|
||||
sub w4, w4, #4
|
||||
|
||||
ld1 {v0.16b-v3.16b}, [x2], #64
|
||||
|
||||
rev32 v4.16b, v0.16b
|
||||
rev32 v5.16b, v1.16b
|
||||
rev32 v6.16b, v2.16b
|
||||
rev32 v7.16b, v3.16b
|
||||
|
||||
transpose_4x4(v4, v5, v6, v7)
|
||||
|
||||
SM4_CRYPT_BLK4_BE(v4, v5, v6, v7)
|
||||
|
||||
eor v4.16b, v4.16b, RIV.16b
|
||||
eor v5.16b, v5.16b, v0.16b
|
||||
eor v6.16b, v6.16b, v1.16b
|
||||
eor v7.16b, v7.16b, v2.16b
|
||||
|
||||
mov RIV.16b, v3.16b
|
||||
|
||||
st1 {v4.16b-v7.16b}, [x1], #64
|
||||
|
||||
cbz w4, .Lcbc_dec_end
|
||||
|
||||
.Lcbc_dec_tail:
|
||||
cmp w4, #2
|
||||
ld1 {v0.16b}, [x2], #16
|
||||
blt .Lcbc_dec_tail_load_done
|
||||
ld1 {v1.16b}, [x2], #16
|
||||
beq .Lcbc_dec_tail_load_done
|
||||
ld1 {v2.16b}, [x2], #16
|
||||
|
||||
.Lcbc_dec_tail_load_done:
|
||||
rev32 v4.16b, v0.16b
|
||||
rev32 v5.16b, v1.16b
|
||||
rev32 v6.16b, v2.16b
|
||||
|
||||
transpose_4x4(v4, v5, v6, v7)
|
||||
|
||||
SM4_CRYPT_BLK4_BE(v4, v5, v6, v7)
|
||||
|
||||
cmp w4, #2
|
||||
eor v4.16b, v4.16b, RIV.16b
|
||||
mov RIV.16b, v0.16b
|
||||
st1 {v4.16b}, [x1], #16
|
||||
blt .Lcbc_dec_end
|
||||
|
||||
eor v5.16b, v5.16b, v0.16b
|
||||
mov RIV.16b, v1.16b
|
||||
st1 {v5.16b}, [x1], #16
|
||||
beq .Lcbc_dec_end
|
||||
|
||||
eor v6.16b, v6.16b, v1.16b
|
||||
mov RIV.16b, v2.16b
|
||||
st1 {v6.16b}, [x1], #16
|
||||
|
||||
.Lcbc_dec_end:
|
||||
/* store new IV */
|
||||
st1 {RIV.16b}, [x3];
|
||||
st1 {RIV.16b}, [x3]
|
||||
|
||||
ret;
|
||||
SYM_FUNC_END(sm4_neon_cbc_dec_blk8)
|
||||
ret
|
||||
SYM_FUNC_END(sm4_neon_cbc_dec)
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_neon_cfb_dec_blk8)
|
||||
SYM_FUNC_START(sm4_neon_cfb_dec)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* x3: iv (big endian, 128 bit)
|
||||
* w4: nblocks (multiples of 8)
|
||||
* w4: nblocks
|
||||
*/
|
||||
PREPARE;
|
||||
SM4_PREPARE()
|
||||
|
||||
ld1 {v0.16b}, [x3];
|
||||
ld1 {v0.16b}, [x3]
|
||||
|
||||
.Lcfb_loop_blk:
|
||||
subs w4, w4, #8;
|
||||
bmi .Lcfb_end;
|
||||
.Lcfb_dec_loop_8x:
|
||||
sub w4, w4, #8
|
||||
tbnz w4, #31, .Lcfb_dec_4x
|
||||
|
||||
ld1 {v1.16b, v2.16b, v3.16b}, [x2], #48;
|
||||
ld1 {v4.16b-v7.16b}, [x2];
|
||||
ld1 {v1.16b-v3.16b}, [x2], #48
|
||||
ld4 {v4.4s-v7.4s}, [x2]
|
||||
|
||||
SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7);
|
||||
transpose_4x4(v0, v1, v2, v3)
|
||||
|
||||
sub x2, x2, #48;
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64;
|
||||
eor v0.16b, v0.16b, RTMP0.16b;
|
||||
eor v1.16b, v1.16b, RTMP1.16b;
|
||||
eor v2.16b, v2.16b, RTMP2.16b;
|
||||
eor v3.16b, v3.16b, RTMP3.16b;
|
||||
st1 {v0.16b-v3.16b}, [x1], #64;
|
||||
SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7)
|
||||
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64;
|
||||
eor v4.16b, v4.16b, RTMP0.16b;
|
||||
eor v5.16b, v5.16b, RTMP1.16b;
|
||||
eor v6.16b, v6.16b, RTMP2.16b;
|
||||
eor v7.16b, v7.16b, RTMP3.16b;
|
||||
st1 {v4.16b-v7.16b}, [x1], #64;
|
||||
sub x2, x2, #48
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64
|
||||
ld1 {RTMP4.16b-RTMP7.16b}, [x2], #64
|
||||
|
||||
mov v0.16b, RTMP3.16b;
|
||||
eor v0.16b, v0.16b, RTMP0.16b
|
||||
eor v1.16b, v1.16b, RTMP1.16b
|
||||
eor v2.16b, v2.16b, RTMP2.16b
|
||||
eor v3.16b, v3.16b, RTMP3.16b
|
||||
eor v4.16b, v4.16b, RTMP4.16b
|
||||
eor v5.16b, v5.16b, RTMP5.16b
|
||||
eor v6.16b, v6.16b, RTMP6.16b
|
||||
eor v7.16b, v7.16b, RTMP7.16b
|
||||
|
||||
b .Lcfb_loop_blk;
|
||||
st1 {v0.16b-v3.16b}, [x1], #64
|
||||
st1 {v4.16b-v7.16b}, [x1], #64
|
||||
|
||||
.Lcfb_end:
|
||||
mov v0.16b, RTMP7.16b
|
||||
|
||||
cbz w4, .Lcfb_dec_end
|
||||
b .Lcfb_dec_loop_8x
|
||||
|
||||
.Lcfb_dec_4x:
|
||||
add w4, w4, #8
|
||||
cmp w4, #4
|
||||
blt .Lcfb_dec_tail
|
||||
|
||||
sub w4, w4, #4
|
||||
|
||||
ld1 {v4.16b-v7.16b}, [x2], #64
|
||||
|
||||
rev32 v0.16b, v0.16b /* v0 is IV register */
|
||||
rev32 v1.16b, v4.16b
|
||||
rev32 v2.16b, v5.16b
|
||||
rev32 v3.16b, v6.16b
|
||||
|
||||
transpose_4x4(v0, v1, v2, v3)
|
||||
|
||||
SM4_CRYPT_BLK4_BE(v0, v1, v2, v3)
|
||||
|
||||
eor v0.16b, v0.16b, v4.16b
|
||||
eor v1.16b, v1.16b, v5.16b
|
||||
eor v2.16b, v2.16b, v6.16b
|
||||
eor v3.16b, v3.16b, v7.16b
|
||||
|
||||
st1 {v0.16b-v3.16b}, [x1], #64
|
||||
|
||||
mov v0.16b, v7.16b
|
||||
|
||||
cbz w4, .Lcfb_dec_end
|
||||
|
||||
.Lcfb_dec_tail:
|
||||
cmp w4, #2
|
||||
ld1 {v4.16b}, [x2], #16
|
||||
blt .Lcfb_dec_tail_load_done
|
||||
ld1 {v5.16b}, [x2], #16
|
||||
beq .Lcfb_dec_tail_load_done
|
||||
ld1 {v6.16b}, [x2], #16
|
||||
|
||||
.Lcfb_dec_tail_load_done:
|
||||
rev32 v0.16b, v0.16b /* v0 is IV register */
|
||||
rev32 v1.16b, v4.16b
|
||||
rev32 v2.16b, v5.16b
|
||||
|
||||
transpose_4x4(v0, v1, v2, v3)
|
||||
|
||||
SM4_CRYPT_BLK4_BE(v0, v1, v2, v3)
|
||||
|
||||
cmp w4, #2
|
||||
eor v0.16b, v0.16b, v4.16b
|
||||
st1 {v0.16b}, [x1], #16
|
||||
mov v0.16b, v4.16b
|
||||
blt .Lcfb_dec_end
|
||||
|
||||
eor v1.16b, v1.16b, v5.16b
|
||||
st1 {v1.16b}, [x1], #16
|
||||
mov v0.16b, v5.16b
|
||||
beq .Lcfb_dec_end
|
||||
|
||||
eor v2.16b, v2.16b, v6.16b
|
||||
st1 {v2.16b}, [x1], #16
|
||||
mov v0.16b, v6.16b
|
||||
|
||||
.Lcfb_dec_end:
|
||||
/* store new IV */
|
||||
st1 {v0.16b}, [x3];
|
||||
st1 {v0.16b}, [x3]
|
||||
|
||||
ret;
|
||||
SYM_FUNC_END(sm4_neon_cfb_dec_blk8)
|
||||
ret
|
||||
SYM_FUNC_END(sm4_neon_cfb_dec)
|
||||
|
||||
.align 3
|
||||
SYM_FUNC_START(sm4_neon_ctr_enc_blk8)
|
||||
SYM_FUNC_START(sm4_neon_ctr_crypt)
|
||||
/* input:
|
||||
* x0: round key array, CTX
|
||||
* x1: dst
|
||||
* x2: src
|
||||
* x3: ctr (big endian, 128 bit)
|
||||
* w4: nblocks (multiples of 8)
|
||||
* w4: nblocks
|
||||
*/
|
||||
PREPARE;
|
||||
SM4_PREPARE()
|
||||
|
||||
ldp x7, x8, [x3];
|
||||
rev x7, x7;
|
||||
rev x8, x8;
|
||||
ldp x7, x8, [x3]
|
||||
rev x7, x7
|
||||
rev x8, x8
|
||||
|
||||
.Lctr_loop_blk:
|
||||
subs w4, w4, #8;
|
||||
bmi .Lctr_end;
|
||||
.Lctr_crypt_loop_8x:
|
||||
sub w4, w4, #8
|
||||
tbnz w4, #31, .Lctr_crypt_4x
|
||||
|
||||
#define inc_le128(vctr) \
|
||||
mov vctr.d[1], x8; \
|
||||
mov vctr.d[0], x7; \
|
||||
adds x8, x8, #1; \
|
||||
adc x7, x7, xzr; \
|
||||
rev64 vctr.16b, vctr.16b;
|
||||
#define inc_le128(vctr) \
|
||||
mov vctr.d[1], x8; \
|
||||
mov vctr.d[0], x7; \
|
||||
adds x8, x8, #1; \
|
||||
rev64 vctr.16b, vctr.16b; \
|
||||
adc x7, x7, xzr;
|
||||
|
||||
/* construct CTRs */
|
||||
inc_le128(v0); /* +0 */
|
||||
inc_le128(v1); /* +1 */
|
||||
inc_le128(v2); /* +2 */
|
||||
inc_le128(v3); /* +3 */
|
||||
inc_le128(v4); /* +4 */
|
||||
inc_le128(v5); /* +5 */
|
||||
inc_le128(v6); /* +6 */
|
||||
inc_le128(v7); /* +7 */
|
||||
inc_le128(v0) /* +0 */
|
||||
inc_le128(v1) /* +1 */
|
||||
inc_le128(v2) /* +2 */
|
||||
inc_le128(v3) /* +3 */
|
||||
inc_le128(v4) /* +4 */
|
||||
inc_le128(v5) /* +5 */
|
||||
inc_le128(v6) /* +6 */
|
||||
inc_le128(v7) /* +7 */
|
||||
|
||||
SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7);
|
||||
transpose_4x4_2x(v0, v1, v2, v3, v4, v5, v6, v7)
|
||||
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64;
|
||||
eor v0.16b, v0.16b, RTMP0.16b;
|
||||
eor v1.16b, v1.16b, RTMP1.16b;
|
||||
eor v2.16b, v2.16b, RTMP2.16b;
|
||||
eor v3.16b, v3.16b, RTMP3.16b;
|
||||
st1 {v0.16b-v3.16b}, [x1], #64;
|
||||
SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7)
|
||||
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64;
|
||||
eor v4.16b, v4.16b, RTMP0.16b;
|
||||
eor v5.16b, v5.16b, RTMP1.16b;
|
||||
eor v6.16b, v6.16b, RTMP2.16b;
|
||||
eor v7.16b, v7.16b, RTMP3.16b;
|
||||
st1 {v4.16b-v7.16b}, [x1], #64;
|
||||
ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64
|
||||
ld1 {RTMP4.16b-RTMP7.16b}, [x2], #64
|
||||
|
||||
b .Lctr_loop_blk;
|
||||
eor v0.16b, v0.16b, RTMP0.16b
|
||||
eor v1.16b, v1.16b, RTMP1.16b
|
||||
eor v2.16b, v2.16b, RTMP2.16b
|
||||
eor v3.16b, v3.16b, RTMP3.16b
|
||||
eor v4.16b, v4.16b, RTMP4.16b
|
||||
eor v5.16b, v5.16b, RTMP5.16b
|
||||
eor v6.16b, v6.16b, RTMP6.16b
|
||||
eor v7.16b, v7.16b, RTMP7.16b
|
||||
|
||||
.Lctr_end:
|
||||
st1 {v0.16b-v3.16b}, [x1], #64
|
||||
st1 {v4.16b-v7.16b}, [x1], #64
|
||||
|
||||
cbz w4, .Lctr_crypt_end
|
||||
b .Lctr_crypt_loop_8x
|
||||
|
||||
.Lctr_crypt_4x:
|
||||
add w4, w4, #8
|
||||
cmp w4, #4
|
||||
blt .Lctr_crypt_tail
|
||||
|
||||
sub w4, w4, #4
|
||||
|
||||
/* construct CTRs */
|
||||
inc_le128(v0) /* +0 */
|
||||
inc_le128(v1) /* +1 */
|
||||
inc_le128(v2) /* +2 */
|
||||
inc_le128(v3) /* +3 */
|
||||
|
||||
ld1 {v4.16b-v7.16b}, [x2], #64
|
||||
|
||||
transpose_4x4(v0, v1, v2, v3)
|
||||
|
||||
SM4_CRYPT_BLK4(v0, v1, v2, v3)
|
||||
|
||||
eor v0.16b, v0.16b, v4.16b
|
||||
eor v1.16b, v1.16b, v5.16b
|
||||
eor v2.16b, v2.16b, v6.16b
|
||||
eor v3.16b, v3.16b, v7.16b
|
||||
|
||||
st1 {v0.16b-v3.16b}, [x1], #64
|
||||
|
||||
cbz w4, .Lctr_crypt_end
|
||||
|
||||
.Lctr_crypt_tail:
|
||||
/* inc_le128 will change the sign bit */
|
||||
ld1 {v4.16b}, [x2], #16
|
||||
inc_le128(v0)
|
||||
cmp w4, #2
|
||||
blt .Lctr_crypt_tail_load_done
|
||||
|
||||
ld1 {v5.16b}, [x2], #16
|
||||
inc_le128(v1)
|
||||
cmp w4, #2
|
||||
beq .Lctr_crypt_tail_load_done
|
||||
|
||||
ld1 {v6.16b}, [x2], #16
|
||||
inc_le128(v2)
|
||||
|
||||
.Lctr_crypt_tail_load_done:
|
||||
transpose_4x4(v0, v1, v2, v3)
|
||||
|
||||
SM4_CRYPT_BLK4(v0, v1, v2, v3)
|
||||
|
||||
cmp w4, #2
|
||||
|
||||
eor v0.16b, v0.16b, v4.16b
|
||||
st1 {v0.16b}, [x1], #16
|
||||
blt .Lctr_crypt_end
|
||||
|
||||
eor v1.16b, v1.16b, v5.16b
|
||||
st1 {v1.16b}, [x1], #16
|
||||
beq .Lctr_crypt_end
|
||||
|
||||
eor v2.16b, v2.16b, v6.16b
|
||||
st1 {v2.16b}, [x1], #16
|
||||
|
||||
.Lctr_crypt_end:
|
||||
/* store new CTR */
|
||||
rev x7, x7;
|
||||
rev x8, x8;
|
||||
stp x7, x8, [x3];
|
||||
rev x7, x7
|
||||
rev x8, x8
|
||||
stp x7, x8, [x3]
|
||||
|
||||
ret;
|
||||
SYM_FUNC_END(sm4_neon_ctr_enc_blk8)
|
||||
ret
|
||||
SYM_FUNC_END(sm4_neon_ctr_crypt)
|
||||
|
||||
@@ -18,19 +18,14 @@
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <crypto/sm4.h>
|
||||
|
||||
#define BYTES2BLKS(nbytes) ((nbytes) >> 4)
|
||||
#define BYTES2BLK8(nbytes) (((nbytes) >> 4) & ~(8 - 1))
|
||||
|
||||
asmlinkage void sm4_neon_crypt_blk1_8(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
unsigned int nblks);
|
||||
asmlinkage void sm4_neon_crypt_blk8(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
unsigned int nblks);
|
||||
asmlinkage void sm4_neon_cbc_dec_blk8(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblks);
|
||||
asmlinkage void sm4_neon_cfb_dec_blk8(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblks);
|
||||
asmlinkage void sm4_neon_ctr_enc_blk8(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblks);
|
||||
asmlinkage void sm4_neon_crypt(const u32 *rkey, u8 *dst, const u8 *src,
|
||||
unsigned int nblocks);
|
||||
asmlinkage void sm4_neon_cbc_dec(const u32 *rkey_dec, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblocks);
|
||||
asmlinkage void sm4_neon_cfb_dec(const u32 *rkey_enc, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblocks);
|
||||
asmlinkage void sm4_neon_ctr_crypt(const u32 *rkey_enc, u8 *dst, const u8 *src,
|
||||
u8 *iv, unsigned int nblocks);
|
||||
|
||||
static int sm4_setkey(struct crypto_skcipher *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
@@ -51,27 +46,18 @@ static int sm4_ecb_do_crypt(struct skcipher_request *req, const u32 *rkey)
|
||||
while ((nbytes = walk.nbytes) > 0) {
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
unsigned int nblks;
|
||||
unsigned int nblocks;
|
||||
|
||||
kernel_neon_begin();
|
||||
nblocks = nbytes / SM4_BLOCK_SIZE;
|
||||
if (nblocks) {
|
||||
kernel_neon_begin();
|
||||
|
||||
nblks = BYTES2BLK8(nbytes);
|
||||
if (nblks) {
|
||||
sm4_neon_crypt_blk8(rkey, dst, src, nblks);
|
||||
dst += nblks * SM4_BLOCK_SIZE;
|
||||
src += nblks * SM4_BLOCK_SIZE;
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
sm4_neon_crypt(rkey, dst, src, nblocks);
|
||||
|
||||
kernel_neon_end();
|
||||
}
|
||||
|
||||
nblks = BYTES2BLKS(nbytes);
|
||||
if (nblks) {
|
||||
sm4_neon_crypt_blk1_8(rkey, dst, src, nblks);
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
err = skcipher_walk_done(&walk, nbytes);
|
||||
err = skcipher_walk_done(&walk, nbytes % SM4_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -138,48 +124,19 @@ static int sm4_cbc_decrypt(struct skcipher_request *req)
|
||||
while ((nbytes = walk.nbytes) > 0) {
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
unsigned int nblks;
|
||||
unsigned int nblocks;
|
||||
|
||||
kernel_neon_begin();
|
||||
nblocks = nbytes / SM4_BLOCK_SIZE;
|
||||
if (nblocks) {
|
||||
kernel_neon_begin();
|
||||
|
||||
nblks = BYTES2BLK8(nbytes);
|
||||
if (nblks) {
|
||||
sm4_neon_cbc_dec_blk8(ctx->rkey_dec, dst, src,
|
||||
walk.iv, nblks);
|
||||
dst += nblks * SM4_BLOCK_SIZE;
|
||||
src += nblks * SM4_BLOCK_SIZE;
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
sm4_neon_cbc_dec(ctx->rkey_dec, dst, src,
|
||||
walk.iv, nblocks);
|
||||
|
||||
kernel_neon_end();
|
||||
}
|
||||
|
||||
nblks = BYTES2BLKS(nbytes);
|
||||
if (nblks) {
|
||||
u8 keystream[SM4_BLOCK_SIZE * 8];
|
||||
u8 iv[SM4_BLOCK_SIZE];
|
||||
int i;
|
||||
|
||||
sm4_neon_crypt_blk1_8(ctx->rkey_dec, keystream,
|
||||
src, nblks);
|
||||
|
||||
src += ((int)nblks - 2) * SM4_BLOCK_SIZE;
|
||||
dst += (nblks - 1) * SM4_BLOCK_SIZE;
|
||||
memcpy(iv, src + SM4_BLOCK_SIZE, SM4_BLOCK_SIZE);
|
||||
|
||||
for (i = nblks - 1; i > 0; i--) {
|
||||
crypto_xor_cpy(dst, src,
|
||||
&keystream[i * SM4_BLOCK_SIZE],
|
||||
SM4_BLOCK_SIZE);
|
||||
src -= SM4_BLOCK_SIZE;
|
||||
dst -= SM4_BLOCK_SIZE;
|
||||
}
|
||||
crypto_xor_cpy(dst, walk.iv,
|
||||
keystream, SM4_BLOCK_SIZE);
|
||||
memcpy(walk.iv, iv, SM4_BLOCK_SIZE);
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
err = skcipher_walk_done(&walk, nbytes);
|
||||
err = skcipher_walk_done(&walk, nbytes % SM4_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -238,42 +195,22 @@ static int sm4_cfb_decrypt(struct skcipher_request *req)
|
||||
while ((nbytes = walk.nbytes) > 0) {
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
unsigned int nblks;
|
||||
unsigned int nblocks;
|
||||
|
||||
kernel_neon_begin();
|
||||
nblocks = nbytes / SM4_BLOCK_SIZE;
|
||||
if (nblocks) {
|
||||
kernel_neon_begin();
|
||||
|
||||
nblks = BYTES2BLK8(nbytes);
|
||||
if (nblks) {
|
||||
sm4_neon_cfb_dec_blk8(ctx->rkey_enc, dst, src,
|
||||
walk.iv, nblks);
|
||||
dst += nblks * SM4_BLOCK_SIZE;
|
||||
src += nblks * SM4_BLOCK_SIZE;
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
sm4_neon_cfb_dec(ctx->rkey_enc, dst, src,
|
||||
walk.iv, nblocks);
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
dst += nblocks * SM4_BLOCK_SIZE;
|
||||
src += nblocks * SM4_BLOCK_SIZE;
|
||||
nbytes -= nblocks * SM4_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
nblks = BYTES2BLKS(nbytes);
|
||||
if (nblks) {
|
||||
u8 keystream[SM4_BLOCK_SIZE * 8];
|
||||
|
||||
memcpy(keystream, walk.iv, SM4_BLOCK_SIZE);
|
||||
if (nblks > 1)
|
||||
memcpy(&keystream[SM4_BLOCK_SIZE], src,
|
||||
(nblks - 1) * SM4_BLOCK_SIZE);
|
||||
memcpy(walk.iv, src + (nblks - 1) * SM4_BLOCK_SIZE,
|
||||
SM4_BLOCK_SIZE);
|
||||
|
||||
sm4_neon_crypt_blk1_8(ctx->rkey_enc, keystream,
|
||||
keystream, nblks);
|
||||
|
||||
crypto_xor_cpy(dst, src, keystream,
|
||||
nblks * SM4_BLOCK_SIZE);
|
||||
dst += nblks * SM4_BLOCK_SIZE;
|
||||
src += nblks * SM4_BLOCK_SIZE;
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
/* tail */
|
||||
if (walk.nbytes == walk.total && nbytes > 0) {
|
||||
u8 keystream[SM4_BLOCK_SIZE];
|
||||
@@ -302,41 +239,22 @@ static int sm4_ctr_crypt(struct skcipher_request *req)
|
||||
while ((nbytes = walk.nbytes) > 0) {
|
||||
const u8 *src = walk.src.virt.addr;
|
||||
u8 *dst = walk.dst.virt.addr;
|
||||
unsigned int nblks;
|
||||
unsigned int nblocks;
|
||||
|
||||
kernel_neon_begin();
|
||||
nblocks = nbytes / SM4_BLOCK_SIZE;
|
||||
if (nblocks) {
|
||||
kernel_neon_begin();
|
||||
|
||||
nblks = BYTES2BLK8(nbytes);
|
||||
if (nblks) {
|
||||
sm4_neon_ctr_enc_blk8(ctx->rkey_enc, dst, src,
|
||||
walk.iv, nblks);
|
||||
dst += nblks * SM4_BLOCK_SIZE;
|
||||
src += nblks * SM4_BLOCK_SIZE;
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
sm4_neon_ctr_crypt(ctx->rkey_enc, dst, src,
|
||||
walk.iv, nblocks);
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
dst += nblocks * SM4_BLOCK_SIZE;
|
||||
src += nblocks * SM4_BLOCK_SIZE;
|
||||
nbytes -= nblocks * SM4_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
nblks = BYTES2BLKS(nbytes);
|
||||
if (nblks) {
|
||||
u8 keystream[SM4_BLOCK_SIZE * 8];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nblks; i++) {
|
||||
memcpy(&keystream[i * SM4_BLOCK_SIZE],
|
||||
walk.iv, SM4_BLOCK_SIZE);
|
||||
crypto_inc(walk.iv, SM4_BLOCK_SIZE);
|
||||
}
|
||||
sm4_neon_crypt_blk1_8(ctx->rkey_enc, keystream,
|
||||
keystream, nblks);
|
||||
|
||||
crypto_xor_cpy(dst, src, keystream,
|
||||
nblks * SM4_BLOCK_SIZE);
|
||||
dst += nblks * SM4_BLOCK_SIZE;
|
||||
src += nblks * SM4_BLOCK_SIZE;
|
||||
nbytes -= nblks * SM4_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
kernel_neon_end();
|
||||
|
||||
/* tail */
|
||||
if (walk.nbytes == walk.total && nbytes > 0) {
|
||||
u8 keystream[SM4_BLOCK_SIZE];
|
||||
|
||||
@@ -27,7 +27,7 @@ ldflags-y := -shared -soname=linux-vdso.so.1 --hash-style=sysv \
|
||||
-Bsymbolic --build-id=sha1 -n $(btildflags-y)
|
||||
|
||||
ifdef CONFIG_LD_ORPHAN_WARN
|
||||
ldflags-y += --orphan-handling=warn
|
||||
ldflags-y += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
|
||||
endif
|
||||
|
||||
ldflags-y += -T
|
||||
|
||||
@@ -104,7 +104,7 @@ VDSO_AFLAGS += -D__ASSEMBLY__
|
||||
VDSO_LDFLAGS += -Bsymbolic --no-undefined -soname=linux-vdso.so.1
|
||||
VDSO_LDFLAGS += -z max-page-size=4096 -z common-page-size=4096
|
||||
VDSO_LDFLAGS += -shared --hash-style=sysv --build-id=sha1
|
||||
VDSO_LDFLAGS += --orphan-handling=warn
|
||||
VDSO_LDFLAGS += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
|
||||
|
||||
|
||||
# Borrow vdsomunge.c from the arm vDSO
|
||||
|
||||
@@ -63,6 +63,7 @@ config IA64
|
||||
select NUMA if !FLATMEM
|
||||
select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
|
||||
select ZONE_DMA32
|
||||
select FUNCTION_ALIGNMENT_32B
|
||||
default y
|
||||
help
|
||||
The Itanium Processor Family is Intel's 64-bit successor to
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ KBUILD_AFLAGS_KERNEL := -mconstant-gp
|
||||
EXTRA :=
|
||||
|
||||
cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \
|
||||
-falign-functions=32 -frename-registers -fno-optimize-sibling-calls
|
||||
-frename-registers -fno-optimize-sibling-calls
|
||||
KBUILD_CFLAGS_KERNEL := -mconstant-gp
|
||||
|
||||
GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)")
|
||||
|
||||
+13
-6
@@ -25,6 +25,7 @@ config RISCV
|
||||
select ARCH_HAS_GIGANTIC_PAGE
|
||||
select ARCH_HAS_KCOV
|
||||
select ARCH_HAS_MMIOWB
|
||||
select ARCH_HAS_PMEM_API
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SET_DIRECT_MAP if MMU
|
||||
select ARCH_HAS_SET_MEMORY if MMU
|
||||
@@ -72,6 +73,8 @@ config RISCV
|
||||
select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
|
||||
select HARDIRQS_SW_RESEND
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP
|
||||
select HAVE_ARCH_HUGE_VMAP if MMU && 64BIT && !XIP_KERNEL
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL
|
||||
select HAVE_ARCH_KASAN if MMU && 64BIT
|
||||
@@ -99,6 +102,7 @@ config RISCV
|
||||
select HAVE_KPROBES if !XIP_KERNEL
|
||||
select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL
|
||||
select HAVE_KRETPROBES if !XIP_KERNEL
|
||||
select HAVE_RETHOOK if !XIP_KERNEL
|
||||
select HAVE_MOVE_PMD
|
||||
select HAVE_MOVE_PUD
|
||||
select HAVE_PCI
|
||||
@@ -123,12 +127,18 @@ config RISCV
|
||||
select PCI_MSI if PCI
|
||||
select RISCV_INTC
|
||||
select RISCV_TIMER if RISCV_SBI
|
||||
select SIFIVE_PLIC
|
||||
select SPARSE_IRQ
|
||||
select SYSCTL_EXCEPTION_TRACE
|
||||
select THREAD_INFO_IN_TASK
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
select UACCESS_MEMCPY if !MMU
|
||||
select ZONE_DMA32 if 64BIT
|
||||
select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && $(cc-option,-fpatchable-function-entry=8)
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER if !XIP_KERNEL
|
||||
|
||||
config ARCH_MMAP_RND_BITS_MIN
|
||||
default 18 if 64BIT
|
||||
@@ -274,11 +284,6 @@ config ARCH_RV64I
|
||||
bool "RV64I"
|
||||
select 64BIT
|
||||
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
|
||||
select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && $(cc-option,-fpatchable-function-entry=8)
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER if !XIP_KERNEL
|
||||
select SWIOTLB if MMU
|
||||
|
||||
endchoice
|
||||
@@ -502,7 +507,7 @@ config KEXEC_FILE
|
||||
select KEXEC_CORE
|
||||
select KEXEC_ELF
|
||||
select HAVE_IMA_KEXEC if IMA
|
||||
depends on 64BIT
|
||||
depends on 64BIT && MMU
|
||||
help
|
||||
This is new version of kexec system call. This system call is
|
||||
file based and takes file descriptors as system call argument
|
||||
@@ -691,6 +696,8 @@ menu "CPU Power Management"
|
||||
|
||||
source "drivers/cpuidle/Kconfig"
|
||||
|
||||
source "drivers/cpufreq/Kconfig"
|
||||
|
||||
endmenu # "CPU Power Management"
|
||||
|
||||
source "arch/riscv/kvm/Kconfig"
|
||||
|
||||
@@ -66,4 +66,17 @@ config ERRATA_THEAD_CMO
|
||||
|
||||
If you don't know what to do here, say "Y".
|
||||
|
||||
config ERRATA_THEAD_PMU
|
||||
bool "Apply T-Head PMU errata"
|
||||
depends on ERRATA_THEAD && RISCV_PMU_SBI
|
||||
default y
|
||||
help
|
||||
The T-Head C9xx cores implement a PMU overflow extension very
|
||||
similar to the core SSCOFPMF extension.
|
||||
|
||||
This will apply the overflow errata to handle the non-standard
|
||||
behaviour via the regular SBI PMU driver and interface.
|
||||
|
||||
If you don't know what to do here, say "Y".
|
||||
|
||||
endmenu # "CPU errata selection"
|
||||
|
||||
@@ -3,7 +3,6 @@ menu "SoC selection"
|
||||
config SOC_MICROCHIP_POLARFIRE
|
||||
bool "Microchip PolarFire SoCs"
|
||||
select MCHP_CLK_MPFS
|
||||
select SIFIVE_PLIC
|
||||
help
|
||||
This enables support for Microchip PolarFire SoC platforms.
|
||||
|
||||
@@ -18,7 +17,6 @@ config SOC_SIFIVE
|
||||
select SERIAL_SIFIVE_CONSOLE if TTY
|
||||
select CLK_SIFIVE
|
||||
select CLK_SIFIVE_PRCI
|
||||
select SIFIVE_PLIC
|
||||
select ERRATA_SIFIVE if !XIP_KERNEL
|
||||
help
|
||||
This enables support for SiFive SoC platform hardware.
|
||||
@@ -27,7 +25,6 @@ config SOC_STARFIVE
|
||||
bool "StarFive SoCs"
|
||||
select PINCTRL
|
||||
select RESET_CONTROLLER
|
||||
select SIFIVE_PLIC
|
||||
help
|
||||
This enables support for StarFive SoC platform hardware.
|
||||
|
||||
@@ -39,7 +36,6 @@ config SOC_VIRT
|
||||
select POWER_RESET_SYSCON_POWEROFF
|
||||
select GOLDFISH
|
||||
select RTC_DRV_GOLDFISH if RTC_CLASS
|
||||
select SIFIVE_PLIC
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
select PM_GENERIC_DOMAINS_OF if PM && OF
|
||||
select RISCV_SBI_CPUIDLE if CPU_IDLE && RISCV_SBI
|
||||
@@ -52,7 +48,6 @@ config SOC_CANAAN
|
||||
select CLINT_TIMER if RISCV_M_MODE
|
||||
select SERIAL_SIFIVE if TTY
|
||||
select SERIAL_SIFIVE_CONSOLE if TTY
|
||||
select SIFIVE_PLIC
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select PINCTRL
|
||||
select COMMON_CLK
|
||||
|
||||
@@ -56,6 +56,9 @@ $(obj)/Image.lzma: $(obj)/Image FORCE
|
||||
$(obj)/Image.lzo: $(obj)/Image FORCE
|
||||
$(call if_changed,lzo)
|
||||
|
||||
$(obj)/Image.zst: $(obj)/Image FORCE
|
||||
$(call if_changed,zstd)
|
||||
|
||||
$(obj)/loader.bin: $(obj)/loader FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ CONFIG_KVM=m
|
||||
CONFIG_JUMP_LABEL=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_SPARSEMEM_MANUAL=y
|
||||
CONFIG_BLK_DEV_THROTTLING=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
@@ -123,6 +124,7 @@ CONFIG_MICROSEMI_PHY=y
|
||||
CONFIG_INPUT_MOUSEDEV=y
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_DW=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
CONFIG_SERIAL_SH_SCI=y
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
@@ -162,6 +164,7 @@ CONFIG_RPMSG_CHAR=y
|
||||
CONFIG_RPMSG_CTRL=y
|
||||
CONFIG_RPMSG_VIRTIO=y
|
||||
CONFIG_ARCH_R9A07G043=y
|
||||
CONFIG_LIBNVDIMM=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
|
||||
@@ -47,6 +47,22 @@ static bool errata_probe_cmo(unsigned int stage,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool errata_probe_pmu(unsigned int stage,
|
||||
unsigned long arch_id, unsigned long impid)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PMU))
|
||||
return false;
|
||||
|
||||
/* target-c9xx cores report arch_id and impid as 0 */
|
||||
if (arch_id != 0 || impid != 0)
|
||||
return false;
|
||||
|
||||
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 thead_errata_probe(unsigned int stage,
|
||||
unsigned long archid, unsigned long impid)
|
||||
{
|
||||
@@ -58,6 +74,9 @@ static u32 thead_errata_probe(unsigned int stage,
|
||||
if (errata_probe_cmo(stage, archid, impid))
|
||||
cpu_req_errata |= BIT(ERRATA_THEAD_CMO);
|
||||
|
||||
if (errata_probe_pmu(stage, archid, impid))
|
||||
cpu_req_errata |= BIT(ERRATA_THEAD_PMU);
|
||||
|
||||
return cpu_req_errata;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro __ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, enable
|
||||
.macro ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, enable
|
||||
886 :
|
||||
.option push
|
||||
.option norvc
|
||||
@@ -44,30 +44,14 @@
|
||||
ALT_NEW_CONTENT \vendor_id, \errata_id, \enable, \new_c
|
||||
.endm
|
||||
|
||||
#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \
|
||||
__ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k)
|
||||
|
||||
.macro __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, enable_2
|
||||
886 :
|
||||
.option push
|
||||
.option norvc
|
||||
.option norelax
|
||||
\old_c
|
||||
.option pop
|
||||
887 :
|
||||
ALT_NEW_CONTENT \vendor_id_1, \errata_id_1, \enable_1, \new_c_1
|
||||
.macro ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, enable_2
|
||||
ALTERNATIVE_CFG \old_c, \new_c_1, \vendor_id_1, \errata_id_1, \enable_1
|
||||
ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2
|
||||
.endm
|
||||
|
||||
#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \
|
||||
CONFIG_k_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, \
|
||||
CONFIG_k_2) \
|
||||
__ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, \
|
||||
IS_ENABLED(CONFIG_k_1), \
|
||||
new_c_2, vendor_id_2, errata_id_2, \
|
||||
IS_ENABLED(CONFIG_k_2)
|
||||
#define __ALTERNATIVE_CFG(...) ALTERNATIVE_CFG __VA_ARGS__
|
||||
#define __ALTERNATIVE_CFG_2(...) ALTERNATIVE_CFG_2 __VA_ARGS__
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -109,63 +93,44 @@
|
||||
"887 :\n" \
|
||||
ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c)
|
||||
|
||||
#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, enable_2) \
|
||||
__ALTERNATIVE_CFG(old_c, new_c_1, vendor_id_1, errata_id_1, enable_1) \
|
||||
ALT_NEW_CONTENT(vendor_id_2, errata_id_2, enable_2, new_c_2)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \
|
||||
__ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k))
|
||||
|
||||
#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \
|
||||
enable_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, \
|
||||
enable_2) \
|
||||
"886 :\n" \
|
||||
".option push\n" \
|
||||
".option norvc\n" \
|
||||
".option norelax\n" \
|
||||
old_c "\n" \
|
||||
".option pop\n" \
|
||||
"887 :\n" \
|
||||
ALT_NEW_CONTENT(vendor_id_1, errata_id_1, enable_1, new_c_1) \
|
||||
ALT_NEW_CONTENT(vendor_id_2, errata_id_2, enable_2, new_c_2)
|
||||
|
||||
#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \
|
||||
CONFIG_k_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, \
|
||||
CONFIG_k_2) \
|
||||
__ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \
|
||||
IS_ENABLED(CONFIG_k_1), \
|
||||
new_c_2, vendor_id_2, errata_id_2, \
|
||||
IS_ENABLED(CONFIG_k_2))
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, CONFIG_k_2) \
|
||||
__ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, IS_ENABLED(CONFIG_k_1), \
|
||||
new_c_2, vendor_id_2, errata_id_2, IS_ENABLED(CONFIG_k_2))
|
||||
|
||||
#else /* CONFIG_RISCV_ALTERNATIVE */
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
.macro __ALTERNATIVE_CFG old_c
|
||||
.macro ALTERNATIVE_CFG old_c
|
||||
\old_c
|
||||
.endm
|
||||
|
||||
#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \
|
||||
__ALTERNATIVE_CFG old_c
|
||||
#define _ALTERNATIVE_CFG(old_c, ...) \
|
||||
ALTERNATIVE_CFG old_c
|
||||
|
||||
#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \
|
||||
CONFIG_k_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, \
|
||||
CONFIG_k_2) \
|
||||
__ALTERNATIVE_CFG old_c
|
||||
#define _ALTERNATIVE_CFG_2(old_c, ...) \
|
||||
ALTERNATIVE_CFG old_c
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
#define __ALTERNATIVE_CFG(old_c) \
|
||||
#define __ALTERNATIVE_CFG(old_c) \
|
||||
old_c "\n"
|
||||
|
||||
#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \
|
||||
#define _ALTERNATIVE_CFG(old_c, ...) \
|
||||
__ALTERNATIVE_CFG(old_c)
|
||||
|
||||
#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \
|
||||
CONFIG_k_1, \
|
||||
new_c_2, vendor_id_2, errata_id_2, \
|
||||
CONFIG_k_2) \
|
||||
__ALTERNATIVE_CFG(old_c)
|
||||
#define _ALTERNATIVE_CFG_2(old_c, ...) \
|
||||
__ALTERNATIVE_CFG(old_c)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* CONFIG_RISCV_ALTERNATIVE */
|
||||
@@ -193,13 +158,9 @@
|
||||
* on the following sample code and then replace ALTERNATIVE() with
|
||||
* ALTERNATIVE_2() to append its customized content.
|
||||
*/
|
||||
#define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, \
|
||||
errata_id_1, CONFIG_k_1, \
|
||||
new_content_2, vendor_id_2, \
|
||||
errata_id_2, CONFIG_k_2) \
|
||||
_ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, \
|
||||
errata_id_1, CONFIG_k_1, \
|
||||
new_content_2, vendor_id_2, \
|
||||
errata_id_2, CONFIG_k_2)
|
||||
#define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
|
||||
new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2) \
|
||||
_ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \
|
||||
new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,13 @@ static inline void local_flush_icache_all(void)
|
||||
|
||||
static inline void flush_dcache_page(struct page *page)
|
||||
{
|
||||
/*
|
||||
* HugeTLB pages are always fully mapped and only head page will be
|
||||
* set PG_dcache_clean (see comments in flush_icache_pte()).
|
||||
*/
|
||||
if (PageHuge(page))
|
||||
page = compound_head(page);
|
||||
|
||||
if (test_bit(PG_dcache_clean, &page->flags))
|
||||
clear_bit(PG_dcache_clean, &page->flags);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define ASM_ERRATA_LIST_H
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/vendorid_list.h>
|
||||
|
||||
#ifdef CONFIG_ERRATA_SIFIVE
|
||||
@@ -17,7 +18,8 @@
|
||||
#ifdef CONFIG_ERRATA_THEAD
|
||||
#define ERRATA_THEAD_PBMT 0
|
||||
#define ERRATA_THEAD_CMO 1
|
||||
#define ERRATA_THEAD_NUMBER 2
|
||||
#define ERRATA_THEAD_PMU 2
|
||||
#define ERRATA_THEAD_NUMBER 3
|
||||
#endif
|
||||
|
||||
#define CPUFEATURE_SVPBMT 0
|
||||
@@ -142,6 +144,18 @@ asm volatile(ALTERNATIVE_2( \
|
||||
"r"((unsigned long)(_start) + (_size)) \
|
||||
: "a0")
|
||||
|
||||
#define THEAD_C9XX_RV_IRQ_PMU 17
|
||||
#define THEAD_C9XX_CSR_SCOUNTEROF 0x5c5
|
||||
|
||||
#define ALT_SBI_PMU_OVERFLOW(__ovl) \
|
||||
asm volatile(ALTERNATIVE( \
|
||||
"csrr %0, " __stringify(CSR_SSCOUNTOVF), \
|
||||
"csrr %0, " __stringify(THEAD_C9XX_CSR_SCOUNTEROF), \
|
||||
THEAD_VENDOR_ID, ERRATA_THEAD_PMU, \
|
||||
CONFIG_ERRATA_THEAD_PMU) \
|
||||
: "=r" (__ovl) : \
|
||||
: "memory")
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,4 +5,10 @@
|
||||
#include <asm-generic/hugetlb.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
||||
{
|
||||
clear_bit(PG_dcache_clean, &page->flags);
|
||||
}
|
||||
#define arch_clear_hugepage_flags arch_clear_hugepage_flags
|
||||
|
||||
#endif /* _ASM_RISCV_HUGETLB_H */
|
||||
|
||||
@@ -59,8 +59,9 @@ enum riscv_isa_ext_id {
|
||||
RISCV_ISA_EXT_ZIHINTPAUSE,
|
||||
RISCV_ISA_EXT_SSTC,
|
||||
RISCV_ISA_EXT_SVINVAL,
|
||||
RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
|
||||
RISCV_ISA_EXT_ID_MAX
|
||||
};
|
||||
static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX);
|
||||
|
||||
/*
|
||||
* This enum represents the logical ID for each RISC-V ISA extension static
|
||||
|
||||
@@ -135,4 +135,9 @@ __io_writes_outs(outs, u64, q, __io_pbr(), __io_paw())
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#define arch_memremap_wb(addr, size) \
|
||||
((__force void *)ioremap_prot((addr), (size), _PAGE_KERNEL))
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_RISCV_IO_H */
|
||||
|
||||
@@ -39,6 +39,7 @@ crash_setup_regs(struct pt_regs *newregs,
|
||||
#define ARCH_HAS_KIMAGE_ARCH
|
||||
|
||||
struct kimage_arch {
|
||||
void *fdt; /* For CONFIG_KEXEC_FILE */
|
||||
unsigned long fdt_addr;
|
||||
};
|
||||
|
||||
@@ -62,6 +63,10 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
|
||||
const Elf_Shdr *relsec,
|
||||
const Elf_Shdr *symtab);
|
||||
#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add
|
||||
|
||||
struct kimage;
|
||||
int arch_kimage_file_post_load_cleanup(struct kimage *image);
|
||||
#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,8 +40,6 @@ void arch_remove_kprobe(struct kprobe *p);
|
||||
int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr);
|
||||
bool kprobe_breakpoint_handler(struct pt_regs *regs);
|
||||
bool kprobe_single_step_handler(struct pt_regs *regs);
|
||||
void __kretprobe_trampoline(void);
|
||||
void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
|
||||
|
||||
#endif /* CONFIG_KPROBES */
|
||||
#endif /* _ASM_RISCV_KPROBES_H */
|
||||
|
||||
@@ -19,6 +19,8 @@ typedef struct {
|
||||
#ifdef CONFIG_SMP
|
||||
/* A local icache flush is needed before user execution can resume. */
|
||||
cpumask_t icache_stale_mask;
|
||||
/* A local tlb flush is needed before user execution can resume. */
|
||||
cpumask_t tlb_stale_mask;
|
||||
#endif
|
||||
} mm_context_t;
|
||||
|
||||
|
||||
@@ -123,20 +123,20 @@ extern phys_addr_t phys_ram_base;
|
||||
((x) >= PAGE_OFFSET && (!IS_ENABLED(CONFIG_64BIT) || (x) < PAGE_OFFSET + KERN_VIRT_SIZE))
|
||||
|
||||
#define linear_mapping_pa_to_va(x) ((void *)((unsigned long)(x) + kernel_map.va_pa_offset))
|
||||
#define kernel_mapping_pa_to_va(y) ({ \
|
||||
unsigned long _y = y; \
|
||||
(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ? \
|
||||
(void *)((unsigned long)(_y) + kernel_map.va_kernel_xip_pa_offset) : \
|
||||
(void *)((unsigned long)(_y) + kernel_map.va_kernel_pa_offset + XIP_OFFSET); \
|
||||
#define kernel_mapping_pa_to_va(y) ({ \
|
||||
unsigned long _y = (unsigned long)(y); \
|
||||
(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ? \
|
||||
(void *)(_y + kernel_map.va_kernel_xip_pa_offset) : \
|
||||
(void *)(_y + kernel_map.va_kernel_pa_offset + XIP_OFFSET); \
|
||||
})
|
||||
#define __pa_to_va_nodebug(x) linear_mapping_pa_to_va(x)
|
||||
|
||||
#define linear_mapping_va_to_pa(x) ((unsigned long)(x) - kernel_map.va_pa_offset)
|
||||
#define kernel_mapping_va_to_pa(y) ({ \
|
||||
unsigned long _y = y; \
|
||||
(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \
|
||||
((unsigned long)(_y) - kernel_map.va_kernel_xip_pa_offset) : \
|
||||
((unsigned long)(_y) - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \
|
||||
unsigned long _y = (unsigned long)(y); \
|
||||
(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \
|
||||
(_y - kernel_map.va_kernel_xip_pa_offset) : \
|
||||
(_y - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \
|
||||
})
|
||||
|
||||
#define __va_to_pa_nodebug(x) ({ \
|
||||
|
||||
@@ -25,7 +25,11 @@ extern bool pgtable_l5_enabled;
|
||||
#define PGDIR_MASK (~(PGDIR_SIZE - 1))
|
||||
|
||||
/* p4d is folded into pgd in case of 4-level page table */
|
||||
#define P4D_SHIFT 39
|
||||
#define P4D_SHIFT_L3 30
|
||||
#define P4D_SHIFT_L4 39
|
||||
#define P4D_SHIFT_L5 39
|
||||
#define P4D_SHIFT (pgtable_l5_enabled ? P4D_SHIFT_L5 : \
|
||||
(pgtable_l4_enabled ? P4D_SHIFT_L4 : P4D_SHIFT_L3))
|
||||
#define P4D_SIZE (_AC(1, UL) << P4D_SHIFT)
|
||||
#define P4D_MASK (~(P4D_SIZE - 1))
|
||||
|
||||
|
||||
@@ -415,9 +415,12 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
|
||||
* Relying on flush_tlb_fix_spurious_fault would suffice, but
|
||||
* the extra traps reduce performance. So, eagerly SFENCE.VMA.
|
||||
*/
|
||||
local_flush_tlb_page(address);
|
||||
flush_tlb_page(vma, address);
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_UPDATE_MMU_TLB
|
||||
#define update_mmu_tlb update_mmu_cache
|
||||
|
||||
static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
|
||||
unsigned long address, pmd_t *pmdp)
|
||||
{
|
||||
|
||||
@@ -327,4 +327,9 @@ int sbi_err_map_linux_errno(int err);
|
||||
static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1; }
|
||||
static inline void sbi_init(void) {}
|
||||
#endif /* CONFIG_RISCV_SBI */
|
||||
|
||||
unsigned long riscv_cached_mvendorid(unsigned int cpu_id);
|
||||
unsigned long riscv_cached_marchid(unsigned int cpu_id);
|
||||
unsigned long riscv_cached_mimpid(unsigned int cpu_id);
|
||||
|
||||
#endif /* _ASM_RISCV_SBI_H */
|
||||
|
||||
@@ -22,6 +22,24 @@ static inline void local_flush_tlb_page(unsigned long addr)
|
||||
{
|
||||
ALT_FLUSH_TLB_PAGE(__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory"));
|
||||
}
|
||||
|
||||
static inline void local_flush_tlb_all_asid(unsigned long asid)
|
||||
{
|
||||
__asm__ __volatile__ ("sfence.vma x0, %0"
|
||||
:
|
||||
: "r" (asid)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void local_flush_tlb_page_asid(unsigned long addr,
|
||||
unsigned long asid)
|
||||
{
|
||||
__asm__ __volatile__ ("sfence.vma %0, %1"
|
||||
:
|
||||
: "r" (addr), "r" (asid)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
#else /* CONFIG_MMU */
|
||||
#define local_flush_tlb_all() do { } while (0)
|
||||
#define local_flush_tlb_page(addr) do { } while (0)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
/*
|
||||
* All systems with an MMU have a VDSO, but systems without an MMU don't
|
||||
* support shared libraries and therefor don't have one.
|
||||
* support shared libraries and therefore don't have one.
|
||||
*/
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
#ifndef _ASM_RISCV_VMALLOC_H
|
||||
#define _ASM_RISCV_VMALLOC_H
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
|
||||
|
||||
#define IOREMAP_MAX_ORDER (PUD_SHIFT)
|
||||
|
||||
#define arch_vmap_pud_supported arch_vmap_pud_supported
|
||||
static inline bool arch_vmap_pud_supported(pgprot_t prot)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#define arch_vmap_pmd_supported arch_vmap_pmd_supported
|
||||
static inline bool arch_vmap_pmd_supported(pgprot_t prot)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_RISCV_VMALLOC_H */
|
||||
|
||||
@@ -15,19 +15,23 @@ struct ucontext {
|
||||
struct ucontext *uc_link;
|
||||
stack_t uc_stack;
|
||||
sigset_t uc_sigmask;
|
||||
/* There's some padding here to allow sigset_t to be expanded in the
|
||||
/*
|
||||
* There's some padding here to allow sigset_t to be expanded in the
|
||||
* future. Though this is unlikely, other architectures put uc_sigmask
|
||||
* at the end of this structure and explicitly state it can be
|
||||
* expanded, so we didn't want to box ourselves in here. */
|
||||
* expanded, so we didn't want to box ourselves in here.
|
||||
*/
|
||||
__u8 __unused[1024 / 8 - sizeof(sigset_t)];
|
||||
/* We can't put uc_sigmask at the end of this structure because we need
|
||||
/*
|
||||
* We can't put uc_sigmask at the end of this structure because we need
|
||||
* to be able to expand sigcontext in the future. For example, the
|
||||
* vector ISA extension will almost certainly add ISA state. We want
|
||||
* to ensure all user-visible ISA state can be saved and restored via a
|
||||
* ucontext, so we're putting this at the end in order to allow for
|
||||
* infinite extensibility. Since we know this will be extended and we
|
||||
* assume sigset_t won't be extended an extreme amount, we're
|
||||
* prioritizing this. */
|
||||
* prioritizing this.
|
||||
*/
|
||||
struct sigcontext uc_mcontext;
|
||||
};
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_KEXEC_CORE) += kexec_relocate.o crash_save_regs.o machine_kexec.o
|
||||
obj-$(CONFIG_KEXEC_FILE) += elf_kexec.o machine_kexec_file.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
||||
obj-$(CONFIG_CRASH_CORE) += crash_core.o
|
||||
|
||||
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
|
||||
|
||||
|
||||
+27
-3
@@ -70,8 +70,6 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
struct riscv_cpuinfo {
|
||||
unsigned long mvendorid;
|
||||
unsigned long marchid;
|
||||
@@ -79,6 +77,30 @@ struct riscv_cpuinfo {
|
||||
};
|
||||
static DEFINE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
|
||||
|
||||
unsigned long riscv_cached_mvendorid(unsigned int cpu_id)
|
||||
{
|
||||
struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id);
|
||||
|
||||
return ci->mvendorid;
|
||||
}
|
||||
EXPORT_SYMBOL(riscv_cached_mvendorid);
|
||||
|
||||
unsigned long riscv_cached_marchid(unsigned int cpu_id)
|
||||
{
|
||||
struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id);
|
||||
|
||||
return ci->marchid;
|
||||
}
|
||||
EXPORT_SYMBOL(riscv_cached_marchid);
|
||||
|
||||
unsigned long riscv_cached_mimpid(unsigned int cpu_id)
|
||||
{
|
||||
struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id);
|
||||
|
||||
return ci->mimpid;
|
||||
}
|
||||
EXPORT_SYMBOL(riscv_cached_mimpid);
|
||||
|
||||
static int riscv_cpuinfo_starting(unsigned int cpu)
|
||||
{
|
||||
struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo);
|
||||
@@ -113,7 +135,9 @@ static int __init riscv_cpuinfo_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(riscv_cpuinfo_init);
|
||||
arch_initcall(riscv_cpuinfo_init);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
#define __RISCV_ISA_EXT_DATA(UPROP, EXTID) \
|
||||
{ \
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <asm/alternative.h>
|
||||
@@ -68,21 +69,38 @@ bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__riscv_isa_extension_available);
|
||||
|
||||
static bool riscv_isa_extension_check(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case RISCV_ISA_EXT_ZICBOM:
|
||||
if (!riscv_cbom_block_size) {
|
||||
pr_err("Zicbom detected in ISA string, but no cbom-block-size found\n");
|
||||
return false;
|
||||
} else if (!is_power_of_2(riscv_cbom_block_size)) {
|
||||
pr_err("cbom-block-size present, but is not a power-of-2\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void __init riscv_fill_hwcap(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
const char *isa;
|
||||
char print_str[NUM_ALPHA_EXTS + 1];
|
||||
int i, j, rc;
|
||||
static unsigned long isa2hwcap[256] = {0};
|
||||
unsigned long isa2hwcap[26] = {0};
|
||||
unsigned long hartid;
|
||||
|
||||
isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I;
|
||||
isa2hwcap['m'] = isa2hwcap['M'] = COMPAT_HWCAP_ISA_M;
|
||||
isa2hwcap['a'] = isa2hwcap['A'] = COMPAT_HWCAP_ISA_A;
|
||||
isa2hwcap['f'] = isa2hwcap['F'] = COMPAT_HWCAP_ISA_F;
|
||||
isa2hwcap['d'] = isa2hwcap['D'] = COMPAT_HWCAP_ISA_D;
|
||||
isa2hwcap['c'] = isa2hwcap['C'] = COMPAT_HWCAP_ISA_C;
|
||||
isa2hwcap['i' - 'a'] = COMPAT_HWCAP_ISA_I;
|
||||
isa2hwcap['m' - 'a'] = COMPAT_HWCAP_ISA_M;
|
||||
isa2hwcap['a' - 'a'] = COMPAT_HWCAP_ISA_A;
|
||||
isa2hwcap['f' - 'a'] = COMPAT_HWCAP_ISA_F;
|
||||
isa2hwcap['d' - 'a'] = COMPAT_HWCAP_ISA_D;
|
||||
isa2hwcap['c' - 'a'] = COMPAT_HWCAP_ISA_C;
|
||||
|
||||
elf_hwcap = 0;
|
||||
|
||||
@@ -189,15 +207,20 @@ void __init riscv_fill_hwcap(void)
|
||||
#define SET_ISA_EXT_MAP(name, bit) \
|
||||
do { \
|
||||
if ((ext_end - ext == sizeof(name) - 1) && \
|
||||
!memcmp(ext, name, sizeof(name) - 1)) \
|
||||
!memcmp(ext, name, sizeof(name) - 1) && \
|
||||
riscv_isa_extension_check(bit)) \
|
||||
set_bit(bit, this_isa); \
|
||||
} while (false) \
|
||||
|
||||
if (unlikely(ext_err))
|
||||
continue;
|
||||
if (!ext_long) {
|
||||
this_hwcap |= isa2hwcap[(unsigned char)(*ext)];
|
||||
set_bit(*ext - 'a', this_isa);
|
||||
int nr = *ext - 'a';
|
||||
|
||||
if (riscv_isa_extension_check(nr)) {
|
||||
this_hwcap |= isa2hwcap[nr];
|
||||
set_bit(nr, this_isa);
|
||||
}
|
||||
} else {
|
||||
SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF);
|
||||
SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/crash_core.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
void arch_crash_save_vmcoreinfo(void)
|
||||
{
|
||||
VMCOREINFO_NUMBER(VA_BITS);
|
||||
VMCOREINFO_NUMBER(phys_ram_base);
|
||||
|
||||
vmcoreinfo_append_str("NUMBER(PAGE_OFFSET)=0x%lx\n", PAGE_OFFSET);
|
||||
vmcoreinfo_append_str("NUMBER(VMALLOC_START)=0x%lx\n", VMALLOC_START);
|
||||
vmcoreinfo_append_str("NUMBER(VMALLOC_END)=0x%lx\n", VMALLOC_END);
|
||||
vmcoreinfo_append_str("NUMBER(VMEMMAP_START)=0x%lx\n", VMEMMAP_START);
|
||||
vmcoreinfo_append_str("NUMBER(VMEMMAP_END)=0x%lx\n", VMEMMAP_END);
|
||||
#ifdef CONFIG_64BIT
|
||||
vmcoreinfo_append_str("NUMBER(MODULES_VADDR)=0x%lx\n", MODULES_VADDR);
|
||||
vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END);
|
||||
#endif
|
||||
vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR);
|
||||
}
|
||||
@@ -21,6 +21,18 @@
|
||||
#include <linux/memblock.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
int arch_kimage_file_post_load_cleanup(struct kimage *image)
|
||||
{
|
||||
kvfree(image->arch.fdt);
|
||||
image->arch.fdt = NULL;
|
||||
|
||||
vfree(image->elf_headers);
|
||||
image->elf_headers = NULL;
|
||||
image->elf_headers_sz = 0;
|
||||
|
||||
return kexec_image_post_load_cleanup_default(image);
|
||||
}
|
||||
|
||||
static int riscv_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
|
||||
struct kexec_elf_info *elf_info, unsigned long old_pbase,
|
||||
unsigned long new_pbase)
|
||||
@@ -298,6 +310,8 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf,
|
||||
pr_err("Error add DTB kbuf ret=%d\n", ret);
|
||||
goto out_free_fdt;
|
||||
}
|
||||
/* Cache the fdt buffer address for memory cleanup */
|
||||
image->arch.fdt = fdt;
|
||||
pr_notice("Loaded device tree at 0x%lx\n", kbuf.mem);
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ ret_from_syscall_rejected:
|
||||
andi t0, t0, _TIF_SYSCALL_WORK
|
||||
bnez t0, handle_syscall_trace_exit
|
||||
|
||||
ret_from_exception:
|
||||
SYM_CODE_START_NOALIGN(ret_from_exception)
|
||||
REG_L s0, PT_STATUS(sp)
|
||||
csrc CSR_STATUS, SR_IE
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
@@ -262,13 +262,13 @@ ret_from_exception:
|
||||
andi s0, s0, SR_SPP
|
||||
#endif
|
||||
bnez s0, resume_kernel
|
||||
SYM_CODE_END(ret_from_exception)
|
||||
|
||||
resume_userspace:
|
||||
/* Interrupts must be disabled here so flags are checked atomically */
|
||||
REG_L s0, TASK_TI_FLAGS(tp) /* current_thread_info->flags */
|
||||
andi s1, s0, _TIF_WORK_MASK
|
||||
bnez s1, work_pending
|
||||
|
||||
bnez s1, resume_userspace_slow
|
||||
resume_userspace:
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_USER
|
||||
call user_enter_callable
|
||||
#endif
|
||||
@@ -368,19 +368,12 @@ resume_kernel:
|
||||
j restore_all
|
||||
#endif
|
||||
|
||||
work_pending:
|
||||
resume_userspace_slow:
|
||||
/* Enter slow path for supplementary processing */
|
||||
la ra, ret_from_exception
|
||||
andi s1, s0, _TIF_NEED_RESCHED
|
||||
bnez s1, work_resched
|
||||
work_notifysig:
|
||||
/* Handle pending signals and notify-resume requests */
|
||||
csrs CSR_STATUS, SR_IE /* Enable interrupts for do_notify_resume() */
|
||||
move a0, sp /* pt_regs */
|
||||
move a1, s0 /* current_thread_info->flags */
|
||||
tail do_notify_resume
|
||||
work_resched:
|
||||
tail schedule
|
||||
call do_work_pending
|
||||
j resume_userspace
|
||||
|
||||
/* Slow paths for ptrace. */
|
||||
handle_syscall_trace_enter:
|
||||
|
||||
+23
-21
@@ -15,8 +15,8 @@
|
||||
|
||||
.macro SAVE_ABI_STATE
|
||||
addi sp, sp, -16
|
||||
sd s0, 0(sp)
|
||||
sd ra, 8(sp)
|
||||
REG_S s0, 0*SZREG(sp)
|
||||
REG_S ra, 1*SZREG(sp)
|
||||
addi s0, sp, 16
|
||||
.endm
|
||||
|
||||
@@ -25,24 +25,26 @@
|
||||
* register if a0 was not saved.
|
||||
*/
|
||||
.macro SAVE_RET_ABI_STATE
|
||||
addi sp, sp, -32
|
||||
sd s0, 16(sp)
|
||||
sd ra, 24(sp)
|
||||
sd a0, 8(sp)
|
||||
addi s0, sp, 32
|
||||
addi sp, sp, -4*SZREG
|
||||
REG_S s0, 2*SZREG(sp)
|
||||
REG_S ra, 3*SZREG(sp)
|
||||
REG_S a0, 1*SZREG(sp)
|
||||
REG_S a1, 0*SZREG(sp)
|
||||
addi s0, sp, 4*SZREG
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ABI_STATE
|
||||
ld ra, 8(sp)
|
||||
ld s0, 0(sp)
|
||||
REG_L ra, 1*SZREG(sp)
|
||||
REG_L s0, 0*SZREG(sp)
|
||||
addi sp, sp, 16
|
||||
.endm
|
||||
|
||||
.macro RESTORE_RET_ABI_STATE
|
||||
ld ra, 24(sp)
|
||||
ld s0, 16(sp)
|
||||
ld a0, 8(sp)
|
||||
addi sp, sp, 32
|
||||
REG_L ra, 3*SZREG(sp)
|
||||
REG_L s0, 2*SZREG(sp)
|
||||
REG_L a0, 1*SZREG(sp)
|
||||
REG_L a1, 0*SZREG(sp)
|
||||
addi sp, sp, 4*SZREG
|
||||
.endm
|
||||
|
||||
ENTRY(ftrace_stub)
|
||||
@@ -71,9 +73,9 @@ ENTRY(return_to_handler)
|
||||
mv a0, t6
|
||||
#endif
|
||||
call ftrace_return_to_handler
|
||||
mv a1, a0
|
||||
mv a2, a0
|
||||
RESTORE_RET_ABI_STATE
|
||||
jalr a1
|
||||
jalr a2
|
||||
ENDPROC(return_to_handler)
|
||||
#endif
|
||||
|
||||
@@ -82,16 +84,16 @@ ENTRY(MCOUNT_NAME)
|
||||
la t4, ftrace_stub
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
la t0, ftrace_graph_return
|
||||
ld t1, 0(t0)
|
||||
REG_L t1, 0(t0)
|
||||
bne t1, t4, do_ftrace_graph_caller
|
||||
|
||||
la t3, ftrace_graph_entry
|
||||
ld t2, 0(t3)
|
||||
REG_L t2, 0(t3)
|
||||
la t6, ftrace_graph_entry_stub
|
||||
bne t2, t6, do_ftrace_graph_caller
|
||||
#endif
|
||||
la t3, ftrace_trace_function
|
||||
ld t5, 0(t3)
|
||||
REG_L t5, 0(t3)
|
||||
bne t5, t4, do_trace
|
||||
ret
|
||||
|
||||
@@ -101,10 +103,10 @@ ENTRY(MCOUNT_NAME)
|
||||
* prepare_to_return(&ra_to_caller_of_caller, ra_to_caller)
|
||||
*/
|
||||
do_ftrace_graph_caller:
|
||||
addi a0, s0, -8
|
||||
addi a0, s0, -SZREG
|
||||
mv a1, ra
|
||||
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
|
||||
ld a2, -16(s0)
|
||||
REG_L a2, -2*SZREG(s0)
|
||||
#endif
|
||||
SAVE_ABI_STATE
|
||||
call prepare_ftrace_return
|
||||
@@ -117,7 +119,7 @@ do_ftrace_graph_caller:
|
||||
* (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller)
|
||||
*/
|
||||
do_trace:
|
||||
ld a1, -8(s0)
|
||||
REG_L a1, -SZREG(s0)
|
||||
mv a0, ra
|
||||
|
||||
SAVE_ABI_STATE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o simulate-insn.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes_trampoline.o
|
||||
obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o
|
||||
obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o
|
||||
obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o simulate-insn.o
|
||||
CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE)
|
||||
|
||||
@@ -345,19 +345,6 @@ int __init arch_populate_kprobe_blacklist(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
|
||||
{
|
||||
return (void *)kretprobe_trampoline_handler(regs, NULL);
|
||||
}
|
||||
|
||||
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
ri->ret_addr = (kprobe_opcode_t *)regs->ra;
|
||||
ri->fp = NULL;
|
||||
regs->ra = (unsigned long) &__kretprobe_trampoline;
|
||||
}
|
||||
|
||||
int __kprobes arch_trampoline_kprobe(struct kprobe *p)
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Generic return hook for riscv.
|
||||
*/
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/rethook.h>
|
||||
#include "rethook.h"
|
||||
|
||||
/* This is called from arch_rethook_trampoline() */
|
||||
unsigned long __used arch_rethook_trampoline_callback(struct pt_regs *regs)
|
||||
{
|
||||
return rethook_trampoline_handler(regs, regs->s0);
|
||||
}
|
||||
|
||||
NOKPROBE_SYMBOL(arch_rethook_trampoline_callback);
|
||||
|
||||
void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount)
|
||||
{
|
||||
rhn->ret_addr = regs->ra;
|
||||
rhn->frame = regs->s0;
|
||||
|
||||
/* replace return addr with trampoline */
|
||||
regs->ra = (unsigned long)arch_rethook_trampoline;
|
||||
}
|
||||
|
||||
NOKPROBE_SYMBOL(arch_rethook_prepare);
|
||||
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __RISCV_RETHOOK_H
|
||||
#define __RISCV_RETHOOK_H
|
||||
|
||||
unsigned long arch_rethook_trampoline_callback(struct pt_regs *regs);
|
||||
void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount);
|
||||
|
||||
#endif
|
||||
+3
-3
@@ -75,13 +75,13 @@
|
||||
REG_L x31, PT_T6(sp)
|
||||
.endm
|
||||
|
||||
ENTRY(__kretprobe_trampoline)
|
||||
ENTRY(arch_rethook_trampoline)
|
||||
addi sp, sp, -(PT_SIZE_ON_STACK)
|
||||
save_all_base_regs
|
||||
|
||||
move a0, sp /* pt_regs */
|
||||
|
||||
call trampoline_probe_handler
|
||||
call arch_rethook_trampoline_callback
|
||||
|
||||
/* use the result as the return-address */
|
||||
move ra, a0
|
||||
@@ -90,4 +90,4 @@ ENTRY(__kretprobe_trampoline)
|
||||
addi sp, sp, PT_SIZE_ON_STACK
|
||||
|
||||
ret
|
||||
ENDPROC(__kretprobe_trampoline)
|
||||
ENDPROC(arch_rethook_trampoline)
|
||||
+21
-13
@@ -313,19 +313,27 @@ static void do_signal(struct pt_regs *regs)
|
||||
}
|
||||
|
||||
/*
|
||||
* notification of userspace execution resumption
|
||||
* - triggered by the _TIF_WORK_MASK flags
|
||||
* Handle any pending work on the resume-to-userspace path, as indicated by
|
||||
* _TIF_WORK_MASK. Entered from assembly with IRQs off.
|
||||
*/
|
||||
asmlinkage __visible void do_notify_resume(struct pt_regs *regs,
|
||||
unsigned long thread_info_flags)
|
||||
asmlinkage __visible void do_work_pending(struct pt_regs *regs,
|
||||
unsigned long thread_info_flags)
|
||||
{
|
||||
if (thread_info_flags & _TIF_UPROBE)
|
||||
uprobe_notify_resume(regs);
|
||||
|
||||
/* Handle pending signal delivery */
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
|
||||
do_signal(regs);
|
||||
|
||||
if (thread_info_flags & _TIF_NOTIFY_RESUME)
|
||||
resume_user_mode_work(regs);
|
||||
do {
|
||||
if (thread_info_flags & _TIF_NEED_RESCHED) {
|
||||
schedule();
|
||||
} else {
|
||||
local_irq_enable();
|
||||
if (thread_info_flags & _TIF_UPROBE)
|
||||
uprobe_notify_resume(regs);
|
||||
/* Handle pending signal delivery */
|
||||
if (thread_info_flags & (_TIF_SIGPENDING |
|
||||
_TIF_NOTIFY_SIGNAL))
|
||||
do_signal(regs);
|
||||
if (thread_info_flags & _TIF_NOTIFY_RESUME)
|
||||
resume_user_mode_work(regs);
|
||||
}
|
||||
local_irq_disable();
|
||||
thread_info_flags = read_thread_flags();
|
||||
} while (thread_info_flags & _TIF_WORK_MASK);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
|
||||
extern asmlinkage void ret_from_exception(void);
|
||||
|
||||
void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
|
||||
bool (*fn)(void *, unsigned long), void *arg)
|
||||
{
|
||||
@@ -58,7 +60,14 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
|
||||
} else {
|
||||
fp = frame->fp;
|
||||
pc = ftrace_graph_ret_addr(current, NULL, frame->ra,
|
||||
(unsigned long *)(fp - 8));
|
||||
&frame->ra);
|
||||
if (pc == (unsigned long)ret_from_exception) {
|
||||
if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc)))
|
||||
break;
|
||||
|
||||
pc = ((struct pt_regs *)sp)->epc;
|
||||
fp = ((struct pt_regs *)sp)->s0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -208,18 +208,18 @@ int is_valid_bugaddr(unsigned long pc)
|
||||
#endif /* CONFIG_GENERIC_BUG */
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
/*
|
||||
* Extra stack space that allows us to provide panic messages when the kernel
|
||||
* has overflowed its stack.
|
||||
*/
|
||||
static DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)],
|
||||
overflow_stack)__aligned(16);
|
||||
/*
|
||||
* shadow stack, handled_ kernel_ stack_ overflow(in kernel/entry.S) is used
|
||||
* to get per-cpu overflow stack(get_overflow_stack).
|
||||
* A temporary stack for use by handle_kernel_stack_overflow. This is used so
|
||||
* we can call into C code to get the per-hart overflow stack. Usage of this
|
||||
* stack must be protected by spin_shadow_stack.
|
||||
*/
|
||||
long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)];
|
||||
asmlinkage unsigned long get_overflow_stack(void)
|
||||
{
|
||||
return (unsigned long)this_cpu_ptr(overflow_stack) +
|
||||
OVERFLOW_STACK_SIZE;
|
||||
}
|
||||
long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)] __aligned(16);
|
||||
|
||||
/*
|
||||
* A pseudo spinlock to protect the shadow stack from being used by multiple
|
||||
@@ -230,6 +230,12 @@ asmlinkage unsigned long get_overflow_stack(void)
|
||||
*/
|
||||
unsigned long spin_shadow_stack;
|
||||
|
||||
asmlinkage unsigned long get_overflow_stack(void)
|
||||
{
|
||||
return (unsigned long)this_cpu_ptr(overflow_stack) +
|
||||
OVERFLOW_STACK_SIZE;
|
||||
}
|
||||
|
||||
asmlinkage void handle_bad_stack(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long tsk_stk = (unsigned long)current->stack;
|
||||
|
||||
@@ -13,6 +13,8 @@ obj-y += extable.o
|
||||
obj-$(CONFIG_MMU) += fault.o pageattr.o
|
||||
obj-y += cacheflush.o
|
||||
obj-y += context.o
|
||||
obj-y += pgtable.o
|
||||
obj-y += pmem.o
|
||||
|
||||
ifeq ($(CONFIG_MMU),y)
|
||||
obj-$(CONFIG_SMP) += tlbflush.o
|
||||
|
||||
@@ -83,6 +83,13 @@ void flush_icache_pte(pte_t pte)
|
||||
{
|
||||
struct page *page = pte_page(pte);
|
||||
|
||||
/*
|
||||
* HugeTLB pages are always fully mapped, so only setting head page's
|
||||
* PG_dcache_clean flag is enough.
|
||||
*/
|
||||
if (PageHuge(page))
|
||||
page = compound_head(page);
|
||||
|
||||
if (!test_and_set_bit(PG_dcache_clean, &page->flags))
|
||||
flush_icache_all();
|
||||
}
|
||||
|
||||
@@ -196,6 +196,16 @@ switch_mm_fast:
|
||||
|
||||
if (need_flush_tlb)
|
||||
local_flush_tlb_all();
|
||||
#ifdef CONFIG_SMP
|
||||
else {
|
||||
cpumask_t *mask = &mm->context.tlb_stale_mask;
|
||||
|
||||
if (cpumask_test_cpu(cpu, mask)) {
|
||||
cpumask_clear_cpu(cpu, mask);
|
||||
local_flush_tlb_all_asid(cntx & asid_mask);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_mm_noasid(struct mm_struct *mm)
|
||||
|
||||
+13
-12
@@ -672,10 +672,11 @@ void __init create_pgd_mapping(pgd_t *pgdp,
|
||||
static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
|
||||
{
|
||||
/* Upgrade to PMD_SIZE mappings whenever possible */
|
||||
if ((base & (PMD_SIZE - 1)) || (size & (PMD_SIZE - 1)))
|
||||
return PAGE_SIZE;
|
||||
base &= PMD_SIZE - 1;
|
||||
if (!base && size >= PMD_SIZE)
|
||||
return PMD_SIZE;
|
||||
|
||||
return PMD_SIZE;
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
@@ -926,15 +927,15 @@ static void __init pt_ops_set_early(void)
|
||||
*/
|
||||
static void __init pt_ops_set_fixmap(void)
|
||||
{
|
||||
pt_ops.alloc_pte = kernel_mapping_pa_to_va((uintptr_t)alloc_pte_fixmap);
|
||||
pt_ops.get_pte_virt = kernel_mapping_pa_to_va((uintptr_t)get_pte_virt_fixmap);
|
||||
pt_ops.alloc_pte = kernel_mapping_pa_to_va(alloc_pte_fixmap);
|
||||
pt_ops.get_pte_virt = kernel_mapping_pa_to_va(get_pte_virt_fixmap);
|
||||
#ifndef __PAGETABLE_PMD_FOLDED
|
||||
pt_ops.alloc_pmd = kernel_mapping_pa_to_va((uintptr_t)alloc_pmd_fixmap);
|
||||
pt_ops.get_pmd_virt = kernel_mapping_pa_to_va((uintptr_t)get_pmd_virt_fixmap);
|
||||
pt_ops.alloc_pud = kernel_mapping_pa_to_va((uintptr_t)alloc_pud_fixmap);
|
||||
pt_ops.get_pud_virt = kernel_mapping_pa_to_va((uintptr_t)get_pud_virt_fixmap);
|
||||
pt_ops.alloc_p4d = kernel_mapping_pa_to_va((uintptr_t)alloc_p4d_fixmap);
|
||||
pt_ops.get_p4d_virt = kernel_mapping_pa_to_va((uintptr_t)get_p4d_virt_fixmap);
|
||||
pt_ops.alloc_pmd = kernel_mapping_pa_to_va(alloc_pmd_fixmap);
|
||||
pt_ops.get_pmd_virt = kernel_mapping_pa_to_va(get_pmd_virt_fixmap);
|
||||
pt_ops.alloc_pud = kernel_mapping_pa_to_va(alloc_pud_fixmap);
|
||||
pt_ops.get_pud_virt = kernel_mapping_pa_to_va(get_pud_virt_fixmap);
|
||||
pt_ops.alloc_p4d = kernel_mapping_pa_to_va(alloc_p4d_fixmap);
|
||||
pt_ops.get_p4d_virt = kernel_mapping_pa_to_va(get_p4d_virt_fixmap);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1110,9 +1111,9 @@ static void __init setup_vm_final(void)
|
||||
if (end >= __pa(PAGE_OFFSET) + memory_limit)
|
||||
end = __pa(PAGE_OFFSET) + memory_limit;
|
||||
|
||||
map_size = best_map_size(start, end - start);
|
||||
for (pa = start; pa < end; pa += map_size) {
|
||||
va = (uintptr_t)__va(pa);
|
||||
map_size = best_map_size(pa, end - pa);
|
||||
|
||||
create_pgd_mapping(swapper_pg_dir, va, pa, map_size,
|
||||
pgprot_from_va(va));
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <asm/pgalloc.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pgtable.h>
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
|
||||
int p4d_set_huge(p4d_t *p4d, phys_addr_t addr, pgprot_t prot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void p4d_clear_huge(p4d_t *p4d)
|
||||
{
|
||||
}
|
||||
|
||||
int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot)
|
||||
{
|
||||
pud_t new_pud = pfn_pud(__phys_to_pfn(phys), prot);
|
||||
|
||||
set_pud(pud, new_pud);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pud_clear_huge(pud_t *pud)
|
||||
{
|
||||
if (!pud_leaf(READ_ONCE(*pud)))
|
||||
return 0;
|
||||
pud_clear(pud);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
{
|
||||
pmd_t *pmd = pud_pgtable(*pud);
|
||||
int i;
|
||||
|
||||
pud_clear(pud);
|
||||
|
||||
flush_tlb_kernel_range(addr, addr + PUD_SIZE);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; i++) {
|
||||
if (!pmd_none(pmd[i])) {
|
||||
pte_t *pte = (pte_t *)pmd_page_vaddr(pmd[i]);
|
||||
|
||||
pte_free_kernel(NULL, pte);
|
||||
}
|
||||
}
|
||||
|
||||
pmd_free(NULL, pmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot)
|
||||
{
|
||||
pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), prot);
|
||||
|
||||
set_pmd(pmd, new_pmd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pmd_clear_huge(pmd_t *pmd)
|
||||
{
|
||||
if (!pmd_leaf(READ_ONCE(*pmd)))
|
||||
return 0;
|
||||
pmd_clear(pmd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
|
||||
{
|
||||
pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd);
|
||||
|
||||
pmd_clear(pmd);
|
||||
|
||||
flush_tlb_kernel_range(addr, addr + PMD_SIZE);
|
||||
pte_free_kernel(NULL, pte);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
|
||||
@@ -22,7 +22,7 @@ EXPORT_SYMBOL(__virt_to_phys);
|
||||
phys_addr_t __phys_addr_symbol(unsigned long x)
|
||||
{
|
||||
unsigned long kernel_start = kernel_map.virt_addr;
|
||||
unsigned long kernel_end = (unsigned long)_end;
|
||||
unsigned long kernel_end = kernel_start + kernel_map.size;
|
||||
|
||||
/*
|
||||
* Boundary checking aginst the kernel image mapping.
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2022 Ventana Micro Systems Inc.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/libnvdimm.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
void arch_wb_cache_pmem(void *addr, size_t size)
|
||||
{
|
||||
ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
|
||||
|
||||
void arch_invalidate_pmem(void *addr, size_t size)
|
||||
{
|
||||
ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
|
||||
+11
-17
@@ -5,23 +5,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
||||
static inline void local_flush_tlb_all_asid(unsigned long asid)
|
||||
{
|
||||
__asm__ __volatile__ ("sfence.vma x0, %0"
|
||||
:
|
||||
: "r" (asid)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void local_flush_tlb_page_asid(unsigned long addr,
|
||||
unsigned long asid)
|
||||
{
|
||||
__asm__ __volatile__ ("sfence.vma %0, %1"
|
||||
:
|
||||
: "r" (addr), "r" (asid)
|
||||
: "memory");
|
||||
}
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
void flush_tlb_all(void)
|
||||
{
|
||||
@@ -31,6 +15,7 @@ void flush_tlb_all(void)
|
||||
static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long size, unsigned long stride)
|
||||
{
|
||||
struct cpumask *pmask = &mm->context.tlb_stale_mask;
|
||||
struct cpumask *cmask = mm_cpumask(mm);
|
||||
unsigned int cpuid;
|
||||
bool broadcast;
|
||||
@@ -44,6 +29,15 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
|
||||
if (static_branch_unlikely(&use_asid_allocator)) {
|
||||
unsigned long asid = atomic_long_read(&mm->context.id);
|
||||
|
||||
/*
|
||||
* TLB will be immediately flushed on harts concurrently
|
||||
* executing this MM context. TLB flush on other harts
|
||||
* is deferred until this MM context migrates there.
|
||||
*/
|
||||
cpumask_setall(pmask);
|
||||
cpumask_clear_cpu(cpuid, pmask);
|
||||
cpumask_andnot(pmask, pmask, cmask);
|
||||
|
||||
if (broadcast) {
|
||||
sbi_remote_sfence_vma_asid(cmask, start, size, asid);
|
||||
} else if (size <= stride) {
|
||||
|
||||
@@ -82,7 +82,6 @@ static int __init rng_init (void)
|
||||
sigio_broken(random_fd);
|
||||
hwrng.name = RNG_MODULE_NAME;
|
||||
hwrng.read = rng_dev_read;
|
||||
hwrng.quality = 1024;
|
||||
|
||||
err = hwrng_register(&hwrng);
|
||||
if (err) {
|
||||
|
||||
@@ -97,7 +97,8 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
|
||||
}
|
||||
|
||||
buf = get_cpu_var(um_pci_msg_bufs);
|
||||
memcpy(buf, cmd, cmd_size);
|
||||
if (buf)
|
||||
memcpy(buf, cmd, cmd_size);
|
||||
|
||||
if (posted) {
|
||||
u8 *ncmd = kmalloc(cmd_size + extra_size, GFP_ATOMIC);
|
||||
@@ -182,6 +183,7 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
|
||||
struct um_pci_message_buffer *buf;
|
||||
u8 *data;
|
||||
unsigned long ret = ULONG_MAX;
|
||||
size_t bytes = sizeof(buf->data);
|
||||
|
||||
if (!dev)
|
||||
return ULONG_MAX;
|
||||
@@ -189,7 +191,8 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
|
||||
buf = get_cpu_var(um_pci_msg_bufs);
|
||||
data = buf->data;
|
||||
|
||||
memset(buf->data, 0xff, sizeof(buf->data));
|
||||
if (buf)
|
||||
memset(data, 0xff, bytes);
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
@@ -204,7 +207,7 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, 8))
|
||||
if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, bytes))
|
||||
goto out;
|
||||
|
||||
switch (size) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user