Merge 1546cd4bfd ("Merge tag 'ata-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata") into android-mainline
Steps on the way to 6.5-rc1 Change-Id: Ia463446d17457b876f2d910fda2c13745d5348e8 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -254,6 +254,7 @@ ForEachMacros:
|
||||
- 'for_each_free_mem_range'
|
||||
- 'for_each_free_mem_range_reverse'
|
||||
- 'for_each_func_rsrc'
|
||||
- 'for_each_group_device'
|
||||
- 'for_each_group_evsel'
|
||||
- 'for_each_group_member'
|
||||
- 'for_each_hstate'
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
acpi= [HW,ACPI,X86,ARM64]
|
||||
acpi= [HW,ACPI,X86,ARM64,RISCV64]
|
||||
Advanced Configuration and Power Interface
|
||||
Format: { force | on | off | strict | noirq | rsdt |
|
||||
copy_dsdt }
|
||||
force -- enable ACPI if default was off
|
||||
on -- enable ACPI but allow fallback to DT [arm64]
|
||||
on -- enable ACPI but allow fallback to DT [arm64,riscv64]
|
||||
off -- disable ACPI if default was on
|
||||
noirq -- do not use ACPI for IRQ routing
|
||||
strict -- Be less tolerant of platforms that are not
|
||||
strictly ACPI specification compliant.
|
||||
rsdt -- prefer RSDT over (default) XSDT
|
||||
copy_dsdt -- copy DSDT to memory
|
||||
For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force"
|
||||
are available
|
||||
For ARM64 and RISCV64, ONLY "acpi=off", "acpi=on" or
|
||||
"acpi=force" are available
|
||||
|
||||
See also Documentation/power/runtime_pm.rst, pci=noacpi
|
||||
|
||||
@@ -323,6 +323,7 @@
|
||||
option with care.
|
||||
pgtbl_v1 - Use v1 page table for DMA-API (Default).
|
||||
pgtbl_v2 - Use v2 page table for DMA-API.
|
||||
irtcachedis - Disable Interrupt Remapping Table (IRT) caching.
|
||||
|
||||
amd_iommu_dump= [HW,X86-64]
|
||||
Enable AMD IOMMU driver option to dump the ACPI table
|
||||
|
||||
@@ -140,6 +140,10 @@ stable kernels.
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | MMU-500 | #841119,826419 | N/A |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | MMU-600 | #1076982,1209401| N/A |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | MMU-700 | #2268618,2812531| N/A |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Broadcom | Brahma-B53 | N/A | ARM64_ERRATUM_845719 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ata/rockchip,dwc-ahci.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Synopsys DWC AHCI SATA controller for Rockchip devices
|
||||
|
||||
maintainers:
|
||||
- Serge Semin <fancer.lancer@gmail.com>
|
||||
|
||||
description:
|
||||
This document defines device tree bindings for the Synopsys DWC
|
||||
implementation of the AHCI SATA controller found in Rockchip
|
||||
devices.
|
||||
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,rk3568-dwc-ahci
|
||||
- rockchip,rk3588-dwc-ahci
|
||||
required:
|
||||
- compatible
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- rockchip,rk3568-dwc-ahci
|
||||
- rockchip,rk3588-dwc-ahci
|
||||
- const: snps,dwc-ahci
|
||||
|
||||
ports-implemented:
|
||||
const: 1
|
||||
|
||||
sata-port@0:
|
||||
$ref: /schemas/ata/snps,dwc-ahci-common.yaml#/$defs/dwc-ahci-port
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[1-9a-e]$": false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- ports-implemented
|
||||
|
||||
allOf:
|
||||
- $ref: snps,dwc-ahci-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,rk3588-dwc-ahci
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 5
|
||||
clock-names:
|
||||
items:
|
||||
- const: sata
|
||||
- const: pmalive
|
||||
- const: rxoob
|
||||
- const: ref
|
||||
- const: asic
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,rk3568-dwc-ahci
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: sata
|
||||
- const: pmalive
|
||||
- const: rxoob
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rockchip,rk3588-cru.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/ata/ahci.h>
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
|
||||
sata@fe210000 {
|
||||
compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci";
|
||||
reg = <0xfe210000 0x1000>;
|
||||
clocks = <&cru ACLK_SATA0>, <&cru CLK_PMALIVE0>,
|
||||
<&cru CLK_RXOOB0>, <&cru CLK_PIPEPHY0_REF>,
|
||||
<&cru CLK_PIPEPHY0_PIPE_ASIC_G>;
|
||||
clock-names = "sata", "pmalive", "rxoob", "ref", "asic";
|
||||
interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
ports-implemented = <0x1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sata-port@0 {
|
||||
reg = <0>;
|
||||
hba-port-cap = <HBA_PORT_FBSCP>;
|
||||
phys = <&combphy0_ps PHY_TYPE_SATA>;
|
||||
phy-names = "sata-phy";
|
||||
snps,rx-ts-max = <32>;
|
||||
snps,tx-ts-max = <32>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -31,11 +31,11 @@ properties:
|
||||
PM-alive clock, RxOOB detection clock, embedded PHYs reference (Rx/Tx)
|
||||
clock, etc.
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
maxItems: 6
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
maxItems: 6
|
||||
items:
|
||||
oneOf:
|
||||
- description: Application APB/AHB/AXI BIU clock
|
||||
@@ -48,6 +48,10 @@ properties:
|
||||
const: pmalive
|
||||
- description: RxOOB detection clock
|
||||
const: rxoob
|
||||
- description: PHY Transmit Clock
|
||||
const: asic
|
||||
- description: PHY Receive Clock
|
||||
const: rbc
|
||||
- description: SATA Ports reference clock
|
||||
const: ref
|
||||
|
||||
|
||||
@@ -13,6 +13,15 @@ description:
|
||||
This document defines device tree bindings for the generic Synopsys DWC
|
||||
implementation of the AHCI SATA controller.
|
||||
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- snps,dwc-ahci
|
||||
- snps,spear-ahci
|
||||
required:
|
||||
- compatible
|
||||
|
||||
allOf:
|
||||
- $ref: snps,dwc-ahci-common.yaml#
|
||||
|
||||
@@ -23,10 +32,6 @@ properties:
|
||||
const: snps,dwc-ahci
|
||||
- description: SPEAr1340 AHCI SATA device
|
||||
const: snps,spear-ahci
|
||||
- description: Rockhip RK3568 AHCI controller
|
||||
items:
|
||||
- const: rockchip,rk3568-dwc-ahci
|
||||
- const: snps,dwc-ahci
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[0-9a-e]$":
|
||||
|
||||
@@ -29,6 +29,7 @@ properties:
|
||||
- qcom,msm8996-smmu-v2
|
||||
- qcom,msm8998-smmu-v2
|
||||
- qcom,sdm630-smmu-v2
|
||||
- qcom,sm6375-smmu-v2
|
||||
- const: qcom,smmu-v2
|
||||
|
||||
- description: Qcom SoCs implementing "qcom,smmu-500" and "arm,mmu-500"
|
||||
@@ -45,6 +46,7 @@ properties:
|
||||
- qcom,sdm845-smmu-500
|
||||
- qcom,sdx55-smmu-500
|
||||
- qcom,sdx65-smmu-500
|
||||
- qcom,sdx75-smmu-500
|
||||
- qcom,sm6115-smmu-500
|
||||
- qcom,sm6125-smmu-500
|
||||
- qcom,sm6350-smmu-500
|
||||
@@ -79,7 +81,9 @@ properties:
|
||||
- description: Qcom Adreno GPUs implementing "qcom,smmu-500" and "arm,mmu-500"
|
||||
items:
|
||||
- enum:
|
||||
- qcom,sa8775p-smmu-500
|
||||
- qcom,sc7280-smmu-500
|
||||
- qcom,sc8280xp-smmu-500
|
||||
- qcom,sm6115-smmu-500
|
||||
- qcom,sm6125-smmu-500
|
||||
- qcom,sm8150-smmu-500
|
||||
@@ -267,6 +271,7 @@ allOf:
|
||||
enum:
|
||||
- qcom,msm8998-smmu-v2
|
||||
- qcom,sdm630-smmu-v2
|
||||
- qcom,sm6375-smmu-v2
|
||||
then:
|
||||
anyOf:
|
||||
- properties:
|
||||
@@ -331,7 +336,10 @@ allOf:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: qcom,sc7280-smmu-500
|
||||
enum:
|
||||
- qcom,sa8775p-smmu-500
|
||||
- qcom,sc7280-smmu-500
|
||||
- qcom,sc8280xp-smmu-500
|
||||
then:
|
||||
properties:
|
||||
clock-names:
|
||||
@@ -413,10 +421,8 @@ allOf:
|
||||
- nvidia,smmu-500
|
||||
- qcom,qcm2290-smmu-500
|
||||
- qcom,qdu1000-smmu-500
|
||||
- qcom,sa8775p-smmu-500
|
||||
- qcom,sc7180-smmu-500
|
||||
- qcom,sc8180x-smmu-500
|
||||
- qcom,sc8280xp-smmu-500
|
||||
- qcom,sdm670-smmu-500
|
||||
- qcom,sdm845-smmu-500
|
||||
- qcom,sdx55-smmu-500
|
||||
|
||||
@@ -31,8 +31,14 @@ properties:
|
||||
- const: pipe
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: exclusive PHY reset line
|
||||
- const: phy
|
||||
- const: apb
|
||||
|
||||
rockchip,enable-ssc:
|
||||
type: boolean
|
||||
@@ -78,6 +84,32 @@ required:
|
||||
- rockchip,pipe-phy-grf
|
||||
- "#phy-cells"
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3568-naneng-combphy
|
||||
then:
|
||||
properties:
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
maxItems: 1
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3588-naneng-combphy
|
||||
then:
|
||||
properties:
|
||||
resets:
|
||||
minItems: 2
|
||||
reset-names:
|
||||
minItems: 2
|
||||
required:
|
||||
- reset-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
||||
@@ -23,6 +23,9 @@ description: |
|
||||
two cores, each of which has two hyperthreads, could be described as
|
||||
having four harts.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/cpu.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
@@ -61,7 +64,7 @@ properties:
|
||||
hart. These values originate from the RISC-V Privileged
|
||||
Specification document, available from
|
||||
https://riscv.org/specifications/
|
||||
$ref: "/schemas/types.yaml#/definitions/string"
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum:
|
||||
- riscv,sv32
|
||||
- riscv,sv39
|
||||
@@ -89,15 +92,18 @@ properties:
|
||||
Due to revisions of the ISA specification, some deviations
|
||||
have arisen over time.
|
||||
Notably, riscv,isa was defined prior to the creation of the
|
||||
Zicsr and Zifencei extensions and thus "i" implies
|
||||
"zicsr_zifencei".
|
||||
Zicntr, Zicsr, Zifencei and Zihpm extensions and thus "i"
|
||||
implies "zicntr_zicsr_zifencei_zihpm".
|
||||
|
||||
While the isa strings in ISA specification are case
|
||||
insensitive, letters in the riscv,isa string must be all
|
||||
lowercase to simplify parsing.
|
||||
$ref: "/schemas/types.yaml#/definitions/string"
|
||||
lowercase.
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
pattern: ^rv(?:64|32)imaf?d?q?c?b?k?j?p?v?h?(?:[hsxz](?:[a-z])+)?(?:_[hsxz](?:[a-z])+)*$
|
||||
|
||||
# RISC-V has multiple properties for cache op block sizes as the sizes
|
||||
# differ between individual CBO extensions
|
||||
cache-op-block-size: false
|
||||
# RISC-V requires 'timebase-frequency' in /cpus, so disallow it here
|
||||
timebase-frequency: false
|
||||
|
||||
@@ -120,7 +126,7 @@ properties:
|
||||
- interrupt-controller
|
||||
|
||||
cpu-idle-states:
|
||||
$ref: '/schemas/types.yaml#/definitions/phandle-array'
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
||||
maxItems: 1
|
||||
description: |
|
||||
@@ -137,7 +143,7 @@ required:
|
||||
- riscv,isa
|
||||
- interrupt-controller
|
||||
|
||||
additionalProperties: true
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
| csky: | ok |
|
||||
| hexagon: | TODO |
|
||||
| ia64: | TODO |
|
||||
| loongarch: | TODO |
|
||||
| loongarch: | ok |
|
||||
| m68k: | TODO |
|
||||
| microblaze: | TODO |
|
||||
| mips: | ok |
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
| csky: | ok |
|
||||
| hexagon: | TODO |
|
||||
| ia64: | TODO |
|
||||
| loongarch: | TODO |
|
||||
| loongarch: | ok |
|
||||
| m68k: | TODO |
|
||||
| microblaze: | ok |
|
||||
| mips: | ok |
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
==========================================
|
||||
DEXCR (Dynamic Execution Control Register)
|
||||
==========================================
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The DEXCR is a privileged special purpose register (SPR) introduced in
|
||||
PowerPC ISA 3.1B (Power10) that allows per-cpu control over several dynamic
|
||||
execution behaviours. These behaviours include speculation (e.g., indirect
|
||||
branch target prediction) and enabling return-oriented programming (ROP)
|
||||
protection instructions.
|
||||
|
||||
The execution control is exposed in hardware as up to 32 bits ('aspects') in
|
||||
the DEXCR. Each aspect controls a certain behaviour, and can be set or cleared
|
||||
to enable/disable the aspect. There are several variants of the DEXCR for
|
||||
different purposes:
|
||||
|
||||
DEXCR
|
||||
A privileged SPR that can control aspects for userspace and kernel space
|
||||
HDEXCR
|
||||
A hypervisor-privileged SPR that can control aspects for the hypervisor and
|
||||
enforce aspects for the kernel and userspace.
|
||||
UDEXCR
|
||||
An optional ultravisor-privileged SPR that can control aspects for the ultravisor.
|
||||
|
||||
Userspace can examine the current DEXCR state using a dedicated SPR that
|
||||
provides a non-privileged read-only view of the userspace DEXCR aspects.
|
||||
There is also an SPR that provides a read-only view of the hypervisor enforced
|
||||
aspects, which ORed with the userspace DEXCR view gives the effective DEXCR
|
||||
state for a process.
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
The DEXCR is currently unconfigurable. All threads are run with the
|
||||
NPHIE aspect enabled.
|
||||
|
||||
|
||||
coredump and ptrace
|
||||
===================
|
||||
|
||||
The userspace values of the DEXCR and HDEXCR (in this order) are exposed under
|
||||
``NT_PPC_DEXCR``. These are each 64 bits and readonly, and are intended to
|
||||
assist with core dumps. The DEXCR may be made writable in future. The top 32
|
||||
bits of both registers (corresponding to the non-userspace bits) are masked off.
|
||||
|
||||
If the kernel config ``CONFIG_CHECKPOINT_RESTORE`` is enabled, then
|
||||
``NT_PPC_HASHKEYR`` is available and exposes the HASHKEYR value of the process
|
||||
for reading and writing. This is a tradeoff between increased security and
|
||||
checkpoint/restore support: a process should normally have no need to know its
|
||||
secret key, but restoring a process requires setting its original key. The key
|
||||
therefore appears in core dumps, and an attacker may be able to retrieve it from
|
||||
a coredump and effectively bypass ROP protection on any threads that share this
|
||||
key (potentially all threads from the same parent that have not run ``exec()``).
|
||||
@@ -15,6 +15,7 @@ powerpc
|
||||
cxl
|
||||
cxlflash
|
||||
dawr-power9
|
||||
dexcr
|
||||
dscr
|
||||
eeh-pci-error-recovery
|
||||
elf_hwcaps
|
||||
|
||||
@@ -64,6 +64,19 @@ The following keys are defined:
|
||||
* :c:macro:`RISCV_HWPROBE_IMA_C`: The C extension is supported, as defined
|
||||
by version 2.2 of the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_IMA_V`: The V extension is supported, as defined by
|
||||
version 1.0 of the RISC-V Vector extension manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBA`: The Zba address generation extension is
|
||||
supported, as defined in version 1.0 of the Bit-Manipulation ISA
|
||||
extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBB`: The Zbb extension is supported, as defined
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBS`: The Zbs extension is supported, as defined
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance
|
||||
information about the selected set of processors.
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ RISC-V architecture
|
||||
hwprobe
|
||||
patch-acceptance
|
||||
uabi
|
||||
vector
|
||||
|
||||
features
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=========================================
|
||||
Vector Extension Support for RISC-V Linux
|
||||
=========================================
|
||||
|
||||
This document briefly outlines the interface provided to userspace by Linux in
|
||||
order to support the use of the RISC-V Vector Extension.
|
||||
|
||||
1. prctl() Interface
|
||||
---------------------
|
||||
|
||||
Two new prctl() calls are added to allow programs to manage the enablement
|
||||
status for the use of Vector in userspace. The intended usage guideline for
|
||||
these interfaces is to give init systems a way to modify the availability of V
|
||||
for processes running under its domain. Calling thess interfaces is not
|
||||
recommended in libraries routines because libraries should not override policies
|
||||
configured from the parant process. Also, users must noted that these interfaces
|
||||
are not portable to non-Linux, nor non-RISC-V environments, so it is discourage
|
||||
to use in a portable code. To get the availability of V in an ELF program,
|
||||
please read :c:macro:`COMPAT_HWCAP_ISA_V` bit of :c:macro:`ELF_HWCAP` in the
|
||||
auxiliary vector.
|
||||
|
||||
* prctl(PR_RISCV_V_SET_CONTROL, unsigned long arg)
|
||||
|
||||
Sets the Vector enablement status of the calling thread, where the control
|
||||
argument consists of two 2-bit enablement statuses and a bit for inheritance
|
||||
mode. Other threads of the calling process are unaffected.
|
||||
|
||||
Enablement status is a tri-state value each occupying 2-bit of space in
|
||||
the control argument:
|
||||
|
||||
* :c:macro:`PR_RISCV_V_VSTATE_CTRL_DEFAULT`: Use the system-wide default
|
||||
enablement status on execve(). The system-wide default setting can be
|
||||
controlled via sysctl interface (see sysctl section below).
|
||||
|
||||
* :c:macro:`PR_RISCV_V_VSTATE_CTRL_ON`: Allow Vector to be run for the
|
||||
thread.
|
||||
|
||||
* :c:macro:`PR_RISCV_V_VSTATE_CTRL_OFF`: Disallow Vector. Executing Vector
|
||||
instructions under such condition will trap and casuse the termination of the thread.
|
||||
|
||||
arg: The control argument is a 5-bit value consisting of 3 parts, and
|
||||
accessed by 3 masks respectively.
|
||||
|
||||
The 3 masks, PR_RISCV_V_VSTATE_CTRL_CUR_MASK,
|
||||
PR_RISCV_V_VSTATE_CTRL_NEXT_MASK, and PR_RISCV_V_VSTATE_CTRL_INHERIT
|
||||
represents bit[1:0], bit[3:2], and bit[4]. bit[1:0] accounts for the
|
||||
enablement status of current thread, and the setting at bit[3:2] takes place
|
||||
at next execve(). bit[4] defines the inheritance mode of the setting in
|
||||
bit[3:2].
|
||||
|
||||
* :c:macro:`PR_RISCV_V_VSTATE_CTRL_CUR_MASK`: bit[1:0]: Account for the
|
||||
Vector enablement status for the calling thread. The calling thread is
|
||||
not able to turn off Vector once it has been enabled. The prctl() call
|
||||
fails with EPERM if the value in this mask is PR_RISCV_V_VSTATE_CTRL_OFF
|
||||
but the current enablement status is not off. Setting
|
||||
PR_RISCV_V_VSTATE_CTRL_DEFAULT here takes no effect but to set back
|
||||
the original enablement status.
|
||||
|
||||
* :c:macro:`PR_RISCV_V_VSTATE_CTRL_NEXT_MASK`: bit[3:2]: Account for the
|
||||
Vector enablement setting for the calling thread at the next execve()
|
||||
system call. If PR_RISCV_V_VSTATE_CTRL_DEFAULT is used in this mask,
|
||||
then the enablement status will be decided by the system-wide
|
||||
enablement status when execve() happen.
|
||||
|
||||
* :c:macro:`PR_RISCV_V_VSTATE_CTRL_INHERIT`: bit[4]: the inheritance
|
||||
mode for the setting at PR_RISCV_V_VSTATE_CTRL_NEXT_MASK. If the bit
|
||||
is set then the following execve() will not clear the setting in both
|
||||
PR_RISCV_V_VSTATE_CTRL_NEXT_MASK and PR_RISCV_V_VSTATE_CTRL_INHERIT.
|
||||
This setting persists across changes in the system-wide default value.
|
||||
|
||||
Return value:
|
||||
* 0 on success;
|
||||
* EINVAL: Vector not supported, invalid enablement status for current or
|
||||
next mask;
|
||||
* EPERM: Turning off Vector in PR_RISCV_V_VSTATE_CTRL_CUR_MASK if Vector
|
||||
was enabled for the calling thread.
|
||||
|
||||
On success:
|
||||
* A valid setting for PR_RISCV_V_VSTATE_CTRL_CUR_MASK takes place
|
||||
immediately. The enablement status specified in
|
||||
PR_RISCV_V_VSTATE_CTRL_NEXT_MASK happens at the next execve() call, or
|
||||
all following execve() calls if PR_RISCV_V_VSTATE_CTRL_INHERIT bit is
|
||||
set.
|
||||
* Every successful call overwrites a previous setting for the calling
|
||||
thread.
|
||||
|
||||
* prctl(PR_RISCV_V_GET_CONTROL)
|
||||
|
||||
Gets the same Vector enablement status for the calling thread. Setting for
|
||||
next execve() call and the inheritance bit are all OR-ed together.
|
||||
|
||||
Note that ELF programs are able to get the availability of V for itself by
|
||||
reading :c:macro:`COMPAT_HWCAP_ISA_V` bit of :c:macro:`ELF_HWCAP` in the
|
||||
auxiliary vector.
|
||||
|
||||
Return value:
|
||||
* a nonnegative value on success;
|
||||
* EINVAL: Vector not supported.
|
||||
|
||||
2. System runtime configuration (sysctl)
|
||||
-----------------------------------------
|
||||
|
||||
To mitigate the ABI impact of expansion of the signal stack, a
|
||||
policy mechanism is provided to the administrators, distro maintainers, and
|
||||
developers to control the default Vector enablement status for userspace
|
||||
processes in form of sysctl knob:
|
||||
|
||||
* /proc/sys/abi/riscv_v_default_allow
|
||||
|
||||
Writing the text representation of 0 or 1 to this file sets the default
|
||||
system enablement status for new starting userspace programs. Valid values
|
||||
are:
|
||||
|
||||
* 0: Do not allow Vector code to be executed as the default for new processes.
|
||||
* 1: Allow Vector code to be executed as the default for new processes.
|
||||
|
||||
Reading this file returns the current system default enablement status.
|
||||
|
||||
At every execve() call, a new enablement status of the new process is set to
|
||||
the system default, unless:
|
||||
|
||||
* PR_RISCV_V_VSTATE_CTRL_INHERIT is set for the calling process, and the
|
||||
setting in PR_RISCV_V_VSTATE_CTRL_NEXT_MASK is not
|
||||
PR_RISCV_V_VSTATE_CTRL_DEFAULT. Or,
|
||||
|
||||
* The setting in PR_RISCV_V_VSTATE_CTRL_NEXT_MASK is not
|
||||
PR_RISCV_V_VSTATE_CTRL_DEFAULT.
|
||||
|
||||
Modifying the system default enablement status does not affect the enablement
|
||||
status of any existing process of thread that do not make an execve() call.
|
||||
@@ -0,0 +1,188 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========================
|
||||
Fprobe-based Event Tracing
|
||||
==========================
|
||||
|
||||
.. Author: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Fprobe event is similar to the kprobe event, but limited to probe on
|
||||
the function entry and exit only. It is good enough for many use cases
|
||||
which only traces some specific functions.
|
||||
|
||||
This document also covers tracepoint probe events (tprobe) since this
|
||||
is also works only on the tracepoint entry. User can trace a part of
|
||||
tracepoint argument, or the tracepoint without trace-event, which is
|
||||
not exposed on tracefs.
|
||||
|
||||
As same as other dynamic events, fprobe events and tracepoint probe
|
||||
events are defined via `dynamic_events` interface file on tracefs.
|
||||
|
||||
Synopsis of fprobe-events
|
||||
-------------------------
|
||||
::
|
||||
|
||||
f[:[GRP1/][EVENT1]] SYM [FETCHARGS] : Probe on function entry
|
||||
f[MAXACTIVE][:[GRP1/][EVENT1]] SYM%return [FETCHARGS] : Probe on function exit
|
||||
t[:[GRP2/][EVENT2]] TRACEPOINT [FETCHARGS] : Probe on tracepoint
|
||||
|
||||
GRP1 : Group name for fprobe. If omitted, use "fprobes" for it.
|
||||
GRP2 : Group name for tprobe. If omitted, use "tracepoints" for it.
|
||||
EVENT1 : Event name for fprobe. If omitted, the event name is
|
||||
"SYM__entry" or "SYM__exit".
|
||||
EVENT2 : Event name for tprobe. If omitted, the event name is
|
||||
the same as "TRACEPOINT", but if the "TRACEPOINT" starts
|
||||
with a digit character, "_TRACEPOINT" is used.
|
||||
MAXACTIVE : Maximum number of instances of the specified function that
|
||||
can be probed simultaneously, or 0 for the default value
|
||||
as defined in Documentation/trace/fprobe.rst
|
||||
|
||||
FETCHARGS : Arguments. Each probe can have up to 128 args.
|
||||
ARG : Fetch "ARG" function argument using BTF (only for function
|
||||
entry or tracepoint.) (\*1)
|
||||
@ADDR : Fetch memory at ADDR (ADDR should be in kernel)
|
||||
@SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol)
|
||||
$stackN : Fetch Nth entry of stack (N >= 0)
|
||||
$stack : Fetch stack address.
|
||||
$argN : Fetch the Nth function argument. (N >= 1) (\*2)
|
||||
$retval : Fetch return value.(\*3)
|
||||
$comm : Fetch current task comm.
|
||||
+|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*4)(\*5)
|
||||
\IMM : Store an immediate value to the argument.
|
||||
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
|
||||
FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
|
||||
(u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
|
||||
(x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr"
|
||||
and bitfield are supported.
|
||||
|
||||
(\*1) This is available only when BTF is enabled.
|
||||
(\*2) only for the probe on function entry (offs == 0).
|
||||
(\*3) only for return probe.
|
||||
(\*4) this is useful for fetching a field of data structures.
|
||||
(\*5) "u" means user-space dereference.
|
||||
|
||||
For the details of TYPE, see :ref:`kprobetrace documentation <kprobetrace_types>`.
|
||||
|
||||
BTF arguments
|
||||
-------------
|
||||
BTF (BPF Type Format) argument allows user to trace function and tracepoint
|
||||
parameters by its name instead of ``$argN``. This feature is available if the
|
||||
kernel is configured with CONFIG_BPF_SYSCALL and CONFIG_DEBUG_INFO_BTF.
|
||||
If user only specify the BTF argument, the event's argument name is also
|
||||
automatically set by the given name. ::
|
||||
|
||||
# echo 'f:myprobe vfs_read count pos' >> dynamic_events
|
||||
# cat dynamic_events
|
||||
f:fprobes/myprobe vfs_read count=count pos=pos
|
||||
|
||||
It also chooses the fetch type from BTF information. For example, in the above
|
||||
example, the ``count`` is unsigned long, and the ``pos`` is a pointer. Thus, both
|
||||
are converted to 64bit unsigned long, but only ``pos`` has "%Lx" print-format as
|
||||
below ::
|
||||
|
||||
# cat events/fprobes/myprobe/format
|
||||
name: myprobe
|
||||
ID: 1313
|
||||
format:
|
||||
field:unsigned short common_type; offset:0; size:2; signed:0;
|
||||
field:unsigned char common_flags; offset:2; size:1; signed:0;
|
||||
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
|
||||
field:int common_pid; offset:4; size:4; signed:1;
|
||||
|
||||
field:unsigned long __probe_ip; offset:8; size:8; signed:0;
|
||||
field:u64 count; offset:16; size:8; signed:0;
|
||||
field:u64 pos; offset:24; size:8; signed:0;
|
||||
|
||||
print fmt: "(%lx) count=%Lu pos=0x%Lx", REC->__probe_ip, REC->count, REC->pos
|
||||
|
||||
If user unsures the name of arguments, ``$arg*`` will be helpful. The ``$arg*``
|
||||
is expanded to all function arguments of the function or the tracepoint. ::
|
||||
|
||||
# echo 'f:myprobe vfs_read $arg*' >> dynamic_events
|
||||
# cat dynamic_events
|
||||
f:fprobes/myprobe vfs_read file=file buf=buf count=count pos=pos
|
||||
|
||||
BTF also affects the ``$retval``. If user doesn't set any type, the retval type is
|
||||
automatically picked from the BTF. If the function returns ``void``, ``$retval``
|
||||
is rejected.
|
||||
|
||||
Usage examples
|
||||
--------------
|
||||
Here is an example to add fprobe events on ``vfs_read()`` function entry
|
||||
and exit, with BTF arguments.
|
||||
::
|
||||
|
||||
# echo 'f vfs_read $arg*' >> dynamic_events
|
||||
# echo 'f vfs_read%return $retval' >> dynamic_events
|
||||
# cat dynamic_events
|
||||
f:fprobes/vfs_read__entry vfs_read file=file buf=buf count=count pos=pos
|
||||
f:fprobes/vfs_read__exit vfs_read%return arg1=$retval
|
||||
# echo 1 > events/fprobes/enable
|
||||
# head -n 20 trace | tail
|
||||
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
|
||||
# | | | ||||| | |
|
||||
sh-70 [000] ...1. 335.883195: vfs_read__entry: (vfs_read+0x4/0x340) file=0xffff888005cf9a80 buf=0x7ffef36c6879 count=1 pos=0xffffc900005aff08
|
||||
sh-70 [000] ..... 335.883208: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=1
|
||||
sh-70 [000] ...1. 335.883220: vfs_read__entry: (vfs_read+0x4/0x340) file=0xffff888005cf9a80 buf=0x7ffef36c6879 count=1 pos=0xffffc900005aff08
|
||||
sh-70 [000] ..... 335.883224: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=1
|
||||
sh-70 [000] ...1. 335.883232: vfs_read__entry: (vfs_read+0x4/0x340) file=0xffff888005cf9a80 buf=0x7ffef36c687a count=1 pos=0xffffc900005aff08
|
||||
sh-70 [000] ..... 335.883237: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=1
|
||||
sh-70 [000] ...1. 336.050329: vfs_read__entry: (vfs_read+0x4/0x340) file=0xffff888005cf9a80 buf=0x7ffef36c6879 count=1 pos=0xffffc900005aff08
|
||||
sh-70 [000] ..... 336.050343: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=1
|
||||
|
||||
You can see all function arguments and return values are recorded as signed int.
|
||||
|
||||
Also, here is an example of tracepoint events on ``sched_switch`` tracepoint.
|
||||
To compare the result, this also enables the ``sched_switch`` traceevent too.
|
||||
::
|
||||
|
||||
# echo 't sched_switch $arg*' >> dynamic_events
|
||||
# echo 1 > events/sched/sched_switch/enable
|
||||
# echo 1 > events/tracepoints/sched_switch/enable
|
||||
# echo > trace
|
||||
# head -n 20 trace | tail
|
||||
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
|
||||
# | | | ||||| | |
|
||||
sh-70 [000] d..2. 3912.083993: sched_switch: prev_comm=sh prev_pid=70 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
|
||||
sh-70 [000] d..3. 3912.083995: sched_switch: (__probestub_sched_switch+0x4/0x10) preempt=0 prev=0xffff88800664e100 next=0xffffffff828229c0 prev_state=1
|
||||
<idle>-0 [000] d..2. 3912.084183: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=rcu_preempt next_pid=16 next_prio=120
|
||||
<idle>-0 [000] d..3. 3912.084184: sched_switch: (__probestub_sched_switch+0x4/0x10) preempt=0 prev=0xffffffff828229c0 next=0xffff888004208000 prev_state=0
|
||||
rcu_preempt-16 [000] d..2. 3912.084196: sched_switch: prev_comm=rcu_preempt prev_pid=16 prev_prio=120 prev_state=I ==> next_comm=swapper/0 next_pid=0 next_prio=120
|
||||
rcu_preempt-16 [000] d..3. 3912.084196: sched_switch: (__probestub_sched_switch+0x4/0x10) preempt=0 prev=0xffff888004208000 next=0xffffffff828229c0 prev_state=1026
|
||||
<idle>-0 [000] d..2. 3912.085191: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=rcu_preempt next_pid=16 next_prio=120
|
||||
<idle>-0 [000] d..3. 3912.085191: sched_switch: (__probestub_sched_switch+0x4/0x10) preempt=0 prev=0xffffffff828229c0 next=0xffff888004208000 prev_state=0
|
||||
|
||||
As you can see, the ``sched_switch`` trace-event shows *cooked* parameters, on
|
||||
the other hand, the ``sched_switch`` tracepoint probe event shows *raw*
|
||||
parameters. This means you can access any field values in the task
|
||||
structure pointed by the ``prev`` and ``next`` arguments.
|
||||
|
||||
For example, usually ``task_struct::start_time`` is not traced, but with this
|
||||
traceprobe event, you can trace it as below.
|
||||
::
|
||||
|
||||
# echo 't sched_switch comm=+1896(next):string start_time=+1728(next):u64' > dynamic_events
|
||||
# head -n 20 trace | tail
|
||||
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
|
||||
# | | | ||||| | |
|
||||
sh-70 [000] d..3. 5606.686577: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="rcu_preempt" usage=1 start_time=245000000
|
||||
rcu_preempt-16 [000] d..3. 5606.686602: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="sh" usage=1 start_time=1596095526
|
||||
sh-70 [000] d..3. 5606.686637: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="swapper/0" usage=2 start_time=0
|
||||
<idle>-0 [000] d..3. 5606.687190: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="rcu_preempt" usage=1 start_time=245000000
|
||||
rcu_preempt-16 [000] d..3. 5606.687202: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="swapper/0" usage=2 start_time=0
|
||||
<idle>-0 [000] d..3. 5606.690317: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="kworker/0:1" usage=1 start_time=137000000
|
||||
kworker/0:1-14 [000] d..3. 5606.690339: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="swapper/0" usage=2 start_time=0
|
||||
<idle>-0 [000] d..3. 5606.692368: sched_switch: (__probestub_sched_switch+0x4/0x10) comm="kworker/0:1" usage=1 start_time=137000000
|
||||
|
||||
Currently, to find the offset of a specific field in the data structure,
|
||||
you need to build kernel with debuginfo and run `perf probe` command with
|
||||
`-D` option. e.g.
|
||||
::
|
||||
|
||||
# perf probe -D "__probestub_sched_switch next->comm:string next->start_time"
|
||||
p:probe/__probestub_sched_switch __probestub_sched_switch+0 comm=+1896(%cx):string start_time=+1728(%cx):u64
|
||||
|
||||
And replace the ``%cx`` with the ``next``.
|
||||
@@ -324,6 +324,12 @@ of ftrace. Here is a list of some of the key files:
|
||||
"set_graph_function", or "set_graph_notrace".
|
||||
(See the section "dynamic ftrace" below for more details.)
|
||||
|
||||
available_filter_functions_addrs:
|
||||
|
||||
Similar to available_filter_functions, but with address displayed
|
||||
for each function. The displayed address is the patch-site address
|
||||
and can differ from /proc/kallsyms address.
|
||||
|
||||
dyn_ftrace_total_info:
|
||||
|
||||
This file is for debugging purposes. The number of functions that
|
||||
@@ -1359,6 +1365,19 @@ Options for function_graph tracer:
|
||||
only a closing curly bracket "}" is displayed for
|
||||
the return of a function.
|
||||
|
||||
funcgraph-retval
|
||||
When set, the return value of each traced function
|
||||
will be printed after an equal sign "=". By default
|
||||
this is off.
|
||||
|
||||
funcgraph-retval-hex
|
||||
When set, the return value will always be printed
|
||||
in hexadecimal format. If the option is not set and
|
||||
the return value is an error code, it will be printed
|
||||
in signed decimal format; otherwise it will also be
|
||||
printed in hexadecimal format. By default, this option
|
||||
is off.
|
||||
|
||||
sleep-time
|
||||
When running function graph tracer, to include
|
||||
the time a task schedules out in its function.
|
||||
@@ -2704,6 +2723,119 @@ It is default disabled.
|
||||
0) 1.757 us | } /* kmem_cache_free() */
|
||||
0) 2.861 us | } /* putname() */
|
||||
|
||||
The return value of each traced function can be displayed after
|
||||
an equal sign "=". When encountering system call failures, it
|
||||
can be verfy helpful to quickly locate the function that first
|
||||
returns an error code.
|
||||
|
||||
- hide: echo nofuncgraph-retval > trace_options
|
||||
- show: echo funcgraph-retval > trace_options
|
||||
|
||||
Example with funcgraph-retval::
|
||||
|
||||
1) | cgroup_migrate() {
|
||||
1) 0.651 us | cgroup_migrate_add_task(); /* = 0xffff93fcfd346c00 */
|
||||
1) | cgroup_migrate_execute() {
|
||||
1) | cpu_cgroup_can_attach() {
|
||||
1) | cgroup_taskset_first() {
|
||||
1) 0.732 us | cgroup_taskset_next(); /* = 0xffff93fc8fb20000 */
|
||||
1) 1.232 us | } /* cgroup_taskset_first = 0xffff93fc8fb20000 */
|
||||
1) 0.380 us | sched_rt_can_attach(); /* = 0x0 */
|
||||
1) 2.335 us | } /* cpu_cgroup_can_attach = -22 */
|
||||
1) 4.369 us | } /* cgroup_migrate_execute = -22 */
|
||||
1) 7.143 us | } /* cgroup_migrate = -22 */
|
||||
|
||||
The above example shows that the function cpu_cgroup_can_attach
|
||||
returned the error code -22 firstly, then we can read the code
|
||||
of this function to get the root cause.
|
||||
|
||||
When the option funcgraph-retval-hex is not set, the return value can
|
||||
be displayed in a smart way. Specifically, if it is an error code,
|
||||
it will be printed in signed decimal format, otherwise it will
|
||||
printed in hexadecimal format.
|
||||
|
||||
- smart: echo nofuncgraph-retval-hex > trace_options
|
||||
- hexadecimal: echo funcgraph-retval-hex > trace_options
|
||||
|
||||
Example with funcgraph-retval-hex::
|
||||
|
||||
1) | cgroup_migrate() {
|
||||
1) 0.651 us | cgroup_migrate_add_task(); /* = 0xffff93fcfd346c00 */
|
||||
1) | cgroup_migrate_execute() {
|
||||
1) | cpu_cgroup_can_attach() {
|
||||
1) | cgroup_taskset_first() {
|
||||
1) 0.732 us | cgroup_taskset_next(); /* = 0xffff93fc8fb20000 */
|
||||
1) 1.232 us | } /* cgroup_taskset_first = 0xffff93fc8fb20000 */
|
||||
1) 0.380 us | sched_rt_can_attach(); /* = 0x0 */
|
||||
1) 2.335 us | } /* cpu_cgroup_can_attach = 0xffffffea */
|
||||
1) 4.369 us | } /* cgroup_migrate_execute = 0xffffffea */
|
||||
1) 7.143 us | } /* cgroup_migrate = 0xffffffea */
|
||||
|
||||
At present, there are some limitations when using the funcgraph-retval
|
||||
option, and these limitations will be eliminated in the future:
|
||||
|
||||
- Even if the function return type is void, a return value will still
|
||||
be printed, and you can just ignore it.
|
||||
|
||||
- Even if return values are stored in multiple registers, only the
|
||||
value contained in the first register will be recorded and printed.
|
||||
To illustrate, in the x86 architecture, eax and edx are used to store
|
||||
a 64-bit return value, with the lower 32 bits saved in eax and the
|
||||
upper 32 bits saved in edx. However, only the value stored in eax
|
||||
will be recorded and printed.
|
||||
|
||||
- In certain procedure call standards, such as arm64's AAPCS64, when a
|
||||
type is smaller than a GPR, it is the responsibility of the consumer
|
||||
to perform the narrowing, and the upper bits may contain UNKNOWN values.
|
||||
Therefore, it is advisable to check the code for such cases. For instance,
|
||||
when using a u8 in a 64-bit GPR, bits [63:8] may contain arbitrary values,
|
||||
especially when larger types are truncated, whether explicitly or implicitly.
|
||||
Here are some specific cases to illustrate this point:
|
||||
|
||||
**Case One**:
|
||||
|
||||
The function narrow_to_u8 is defined as follows::
|
||||
|
||||
u8 narrow_to_u8(u64 val)
|
||||
{
|
||||
// implicitly truncated
|
||||
return val;
|
||||
}
|
||||
|
||||
It may be compiled to::
|
||||
|
||||
narrow_to_u8:
|
||||
< ... ftrace instrumentation ... >
|
||||
RET
|
||||
|
||||
If you pass 0x123456789abcdef to this function and want to narrow it,
|
||||
it may be recorded as 0x123456789abcdef instead of 0xef.
|
||||
|
||||
**Case Two**:
|
||||
|
||||
The function error_if_not_4g_aligned is defined as follows::
|
||||
|
||||
int error_if_not_4g_aligned(u64 val)
|
||||
{
|
||||
if (val & GENMASK(31, 0))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
It could be compiled to::
|
||||
|
||||
error_if_not_4g_aligned:
|
||||
CBNZ w0, .Lnot_aligned
|
||||
RET // bits [31:0] are zero, bits
|
||||
// [63:32] are UNKNOWN
|
||||
.Lnot_aligned:
|
||||
MOV x0, #-EINVAL
|
||||
RET
|
||||
|
||||
When passing 0x2_0000_0000 to it, the return value may be recorded as
|
||||
0x2_0000_0000 instead of 0.
|
||||
|
||||
You can put some comments on specific functions by using
|
||||
trace_printk() For example, if you want to put a comment inside
|
||||
the __might_sleep() function, you just have to include
|
||||
|
||||
@@ -13,6 +13,7 @@ Linux Tracing Technologies
|
||||
kprobes
|
||||
kprobetrace
|
||||
uprobetracer
|
||||
fprobetrace
|
||||
tracepoints
|
||||
events
|
||||
events-kmem
|
||||
|
||||
@@ -66,6 +66,8 @@ Synopsis of kprobe_events
|
||||
(\*3) this is useful for fetching a field of data structures.
|
||||
(\*4) "u" means user-space dereference. See :ref:`user_mem_access`.
|
||||
|
||||
.. _kprobetrace_types:
|
||||
|
||||
Types
|
||||
-----
|
||||
Several types are supported for fetchargs. Kprobe tracer will access memory
|
||||
|
||||
@@ -180,3 +180,81 @@ dummy_load_1ms_pd_init, which had the following code (on purpose)::
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
User-space interface
|
||||
---------------------------
|
||||
|
||||
Timerlat allows user-space threads to use timerlat infra-structure to
|
||||
measure scheduling latency. This interface is accessible via a per-CPU
|
||||
file descriptor inside $tracing_dir/osnoise/per_cpu/cpu$ID/timerlat_fd.
|
||||
|
||||
This interface is accessible under the following conditions:
|
||||
|
||||
- timerlat tracer is enable
|
||||
- osnoise workload option is set to NO_OSNOISE_WORKLOAD
|
||||
- The user-space thread is affined to a single processor
|
||||
- The thread opens the file associated with its single processor
|
||||
- Only one thread can access the file at a time
|
||||
|
||||
The open() syscall will fail if any of these conditions are not met.
|
||||
After opening the file descriptor, the user space can read from it.
|
||||
|
||||
The read() system call will run a timerlat code that will arm the
|
||||
timer in the future and wait for it as the regular kernel thread does.
|
||||
|
||||
When the timer IRQ fires, the timerlat IRQ will execute, report the
|
||||
IRQ latency and wake up the thread waiting in the read. The thread will be
|
||||
scheduled and report the thread latency via tracer - as for the kernel
|
||||
thread.
|
||||
|
||||
The difference from the in-kernel timerlat is that, instead of re-arming
|
||||
the timer, timerlat will return to the read() system call. At this point,
|
||||
the user can run any code.
|
||||
|
||||
If the application rereads the file timerlat file descriptor, the tracer
|
||||
will report the return from user-space latency, which is the total
|
||||
latency. If this is the end of the work, it can be interpreted as the
|
||||
response time for the request.
|
||||
|
||||
After reporting the total latency, timerlat will restart the cycle, arm
|
||||
a timer, and go to sleep for the following activation.
|
||||
|
||||
If at any time one of the conditions is broken, e.g., the thread migrates
|
||||
while in user space, or the timerlat tracer is disabled, the SIG_KILL
|
||||
signal will be sent to the user-space thread.
|
||||
|
||||
Here is an basic example of user-space code for timerlat::
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char buffer[1024];
|
||||
int timerlat_fd;
|
||||
int retval;
|
||||
long cpu = 0; /* place in CPU 0 */
|
||||
cpu_set_t set;
|
||||
|
||||
CPU_ZERO(&set);
|
||||
CPU_SET(cpu, &set);
|
||||
|
||||
if (sched_setaffinity(gettid(), sizeof(set), &set) == -1)
|
||||
return 1;
|
||||
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"/sys/kernel/tracing/osnoise/per_cpu/cpu%ld/timerlat_fd",
|
||||
cpu);
|
||||
|
||||
timerlat_fd = open(buffer, O_RDONLY);
|
||||
if (timerlat_fd < 0) {
|
||||
printf("error opening %s: %s\n", buffer, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
retval = read(timerlat_fd, buffer, 1024);
|
||||
if (retval < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
close(timerlat_fd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
+16
-2
@@ -406,6 +406,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: drivers/acpi/arm64
|
||||
|
||||
ACPI FOR RISC-V (ACPI/riscv)
|
||||
M: Sunil V L <sunilvl@ventanamicro.com>
|
||||
L: linux-acpi@vger.kernel.org
|
||||
L: linux-riscv@lists.infradead.org
|
||||
S: Maintained
|
||||
F: drivers/acpi/riscv/
|
||||
|
||||
ACPI PCC(Platform Communication Channel) MAILBOX DRIVER
|
||||
M: Sudeep Holla <sudeep.holla@arm.com>
|
||||
L: linux-acpi@vger.kernel.org
|
||||
@@ -11455,7 +11462,13 @@ F: arch/mips/include/uapi/asm/kvm*
|
||||
F: arch/mips/kvm/
|
||||
|
||||
KERNEL VIRTUAL MACHINE FOR POWERPC (KVM/powerpc)
|
||||
M: Michael Ellerman <mpe@ellerman.id.au>
|
||||
R: Nicholas Piggin <npiggin@gmail.com>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
L: kvm@vger.kernel.org
|
||||
S: Maintained (Book3S 64-bit HV)
|
||||
S: Odd fixes (Book3S 64-bit PR)
|
||||
S: Orphan (Book3E and 32-bit)
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git topic/ppc-kvm
|
||||
F: arch/powerpc/include/asm/kvm*
|
||||
F: arch/powerpc/include/uapi/asm/kvm*
|
||||
@@ -11988,11 +12001,12 @@ F: lib/linear_ranges.c
|
||||
F: lib/test_linear_ranges.c
|
||||
|
||||
LINUX FOR POWER MACINTOSH
|
||||
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Odd Fixes
|
||||
S: Orphan
|
||||
F: arch/powerpc/platforms/powermac/
|
||||
F: drivers/macintosh/
|
||||
X: drivers/macintosh/adb-iop.c
|
||||
X: drivers/macintosh/via-macii.c
|
||||
|
||||
LINUX FOR POWERPC (32-BIT AND 64-BIT)
|
||||
M: Michael Ellerman <mpe@ellerman.id.au>
|
||||
|
||||
@@ -202,6 +202,7 @@ config ARM64
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_GCC_PLUGINS
|
||||
select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \
|
||||
|
||||
@@ -192,4 +192,26 @@ static inline bool arch_syscall_match_sym_name(const char *sym,
|
||||
}
|
||||
#endif /* ifndef __ASSEMBLY__ */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
struct fgraph_ret_regs {
|
||||
/* x0 - x7 */
|
||||
unsigned long regs[8];
|
||||
|
||||
unsigned long fp;
|
||||
unsigned long __unused;
|
||||
};
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->regs[0];
|
||||
}
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->fp;
|
||||
}
|
||||
#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_FTRACE_H */
|
||||
|
||||
@@ -200,6 +200,19 @@ int main(void)
|
||||
#endif
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
DEFINE(FTRACE_OPS_FUNC, offsetof(struct ftrace_ops, func));
|
||||
#endif
|
||||
BLANK();
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
DEFINE(FGRET_REGS_X0, offsetof(struct fgraph_ret_regs, regs[0]));
|
||||
DEFINE(FGRET_REGS_X1, offsetof(struct fgraph_ret_regs, regs[1]));
|
||||
DEFINE(FGRET_REGS_X2, offsetof(struct fgraph_ret_regs, regs[2]));
|
||||
DEFINE(FGRET_REGS_X3, offsetof(struct fgraph_ret_regs, regs[3]));
|
||||
DEFINE(FGRET_REGS_X4, offsetof(struct fgraph_ret_regs, regs[4]));
|
||||
DEFINE(FGRET_REGS_X5, offsetof(struct fgraph_ret_regs, regs[5]));
|
||||
DEFINE(FGRET_REGS_X6, offsetof(struct fgraph_ret_regs, regs[6]));
|
||||
DEFINE(FGRET_REGS_X7, offsetof(struct fgraph_ret_regs, regs[7]));
|
||||
DEFINE(FGRET_REGS_FP, offsetof(struct fgraph_ret_regs, fp));
|
||||
DEFINE(FGRET_REGS_SIZE, sizeof(struct fgraph_ret_regs));
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
DEFINE(FTRACE_OPS_DIRECT_CALL, offsetof(struct ftrace_ops, direct_call));
|
||||
#endif
|
||||
|
||||
@@ -330,22 +330,23 @@ SYM_FUNC_END(ftrace_stub_graph)
|
||||
*/
|
||||
SYM_CODE_START(return_to_handler)
|
||||
/* save return value regs */
|
||||
sub sp, sp, #64
|
||||
stp x0, x1, [sp]
|
||||
stp x2, x3, [sp, #16]
|
||||
stp x4, x5, [sp, #32]
|
||||
stp x6, x7, [sp, #48]
|
||||
sub sp, sp, #FGRET_REGS_SIZE
|
||||
stp x0, x1, [sp, #FGRET_REGS_X0]
|
||||
stp x2, x3, [sp, #FGRET_REGS_X2]
|
||||
stp x4, x5, [sp, #FGRET_REGS_X4]
|
||||
stp x6, x7, [sp, #FGRET_REGS_X6]
|
||||
str x29, [sp, #FGRET_REGS_FP] // parent's fp
|
||||
|
||||
mov x0, x29 // parent's fp
|
||||
bl ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
|
||||
mov x30, x0 // restore the original return address
|
||||
mov x0, sp
|
||||
bl ftrace_return_to_handler // addr = ftrace_return_to_hander(regs);
|
||||
mov x30, x0 // restore the original return address
|
||||
|
||||
/* restore return value regs */
|
||||
ldp x0, x1, [sp]
|
||||
ldp x2, x3, [sp, #16]
|
||||
ldp x4, x5, [sp, #32]
|
||||
ldp x6, x7, [sp, #48]
|
||||
add sp, sp, #64
|
||||
ldp x0, x1, [sp, #FGRET_REGS_X0]
|
||||
ldp x2, x3, [sp, #FGRET_REGS_X2]
|
||||
ldp x4, x5, [sp, #FGRET_REGS_X4]
|
||||
ldp x6, x7, [sp, #FGRET_REGS_X6]
|
||||
add sp, sp, #FGRET_REGS_SIZE
|
||||
|
||||
ret
|
||||
SYM_CODE_END(return_to_handler)
|
||||
|
||||
@@ -237,7 +237,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs)
|
||||
if (is_write(regs))
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
retry:
|
||||
vma = lock_mm_and_find_vma(mm, address, regs);
|
||||
vma = lock_mm_and_find_vma(mm, addr, regs);
|
||||
if (unlikely(!vma)) {
|
||||
bad_area_nosemaphore(regs, mm, code, addr);
|
||||
return;
|
||||
|
||||
+65
-8
@@ -5,6 +5,7 @@ config LOONGARCH
|
||||
select ACPI
|
||||
select ACPI_GENERIC_GSI if ACPI
|
||||
select ACPI_MCFG if ACPI
|
||||
select ACPI_PPTT if ACPI
|
||||
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
|
||||
select ARCH_BINFMT_ELF_STATE
|
||||
select ARCH_ENABLE_MEMORY_HOTPLUG
|
||||
@@ -49,6 +50,8 @@ config LOONGARCH
|
||||
select ARCH_SUPPORTS_ACPI
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW
|
||||
select ARCH_SUPPORTS_HUGETLBFS
|
||||
select ARCH_SUPPORTS_LTO_CLANG
|
||||
select ARCH_SUPPORTS_LTO_CLANG_THIN
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select ARCH_USE_BUILTIN_BSWAP
|
||||
select ARCH_USE_CMPXCHG_LOCKREF
|
||||
@@ -81,9 +84,12 @@ config LOONGARCH
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_VDSO_TIME_NS
|
||||
select GPIOLIB
|
||||
select HAS_IOPORT
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||
select HAVE_ARCH_MMAP_RND_BITS if MMU
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
@@ -91,6 +97,7 @@ config LOONGARCH
|
||||
select HAVE_ASM_MODVERSIONS
|
||||
select HAVE_CONTEXT_TRACKING_USER
|
||||
select HAVE_C_RECORDMCOUNT
|
||||
select HAVE_DEBUG_KMEMLEAK
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
select HAVE_DMA_CONTIGUOUS
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
@@ -104,6 +111,7 @@ config LOONGARCH
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_FUNCTION_ARG_ACCESS_API
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_GENERIC_VDSO
|
||||
@@ -121,6 +129,7 @@ config LOONGARCH
|
||||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_RETHOOK
|
||||
select HAVE_RSEQ
|
||||
select HAVE_SAMPLE_FTRACE_DIRECT
|
||||
select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
|
||||
@@ -163,14 +172,6 @@ config 32BIT
|
||||
config 64BIT
|
||||
def_bool y
|
||||
|
||||
config CPU_HAS_FPU
|
||||
bool
|
||||
default y
|
||||
|
||||
config CPU_HAS_PREFETCH
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_BUG
|
||||
def_bool y
|
||||
depends on BUG
|
||||
@@ -243,6 +244,15 @@ config SCHED_OMIT_FRAME_POINTER
|
||||
config AS_HAS_EXPLICIT_RELOCS
|
||||
def_bool $(as-instr,x:pcalau12i \$t0$(comma)%pc_hi20(x))
|
||||
|
||||
config AS_HAS_FCSR_CLASS
|
||||
def_bool $(as-instr,movfcsr2gr \$t0$(comma)\$fcsr0)
|
||||
|
||||
config AS_HAS_LSX_EXTENSION
|
||||
def_bool $(as-instr,vld \$vr0$(comma)\$a0$(comma)0)
|
||||
|
||||
config AS_HAS_LASX_EXTENSION
|
||||
def_bool $(as-instr,xvld \$xr0$(comma)\$a0$(comma)0)
|
||||
|
||||
menu "Kernel type and options"
|
||||
|
||||
source "kernel/Kconfig.hz"
|
||||
@@ -374,6 +384,13 @@ config EFI_STUB
|
||||
This kernel feature allows the kernel to be loaded directly by
|
||||
EFI firmware without the use of a bootloader.
|
||||
|
||||
config SCHED_SMT
|
||||
bool "SMT scheduler support"
|
||||
default y
|
||||
help
|
||||
Improves scheduler's performance when there are multiple
|
||||
threads in one physical core.
|
||||
|
||||
config SMP
|
||||
bool "Multi-Processing support"
|
||||
help
|
||||
@@ -483,6 +500,43 @@ config ARCH_STRICT_ALIGN
|
||||
to run kernel only on systems with h/w unaligned access support in
|
||||
order to optimise for performance.
|
||||
|
||||
config CPU_HAS_FPU
|
||||
bool
|
||||
default y
|
||||
|
||||
config CPU_HAS_LSX
|
||||
bool "Support for the Loongson SIMD Extension"
|
||||
depends on AS_HAS_LSX_EXTENSION
|
||||
help
|
||||
Loongson SIMD Extension (LSX) introduces 128 bit wide vector registers
|
||||
and a set of SIMD instructions to operate on them. When this option
|
||||
is enabled the kernel will support allocating & switching LSX
|
||||
vector register contexts. If you know that your kernel will only be
|
||||
running on CPUs which do not support LSX or that your userland will
|
||||
not be making use of it then you may wish to say N here to reduce
|
||||
the size & complexity of your kernel.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config CPU_HAS_LASX
|
||||
bool "Support for the Loongson Advanced SIMD Extension"
|
||||
depends on CPU_HAS_LSX
|
||||
depends on AS_HAS_LASX_EXTENSION
|
||||
help
|
||||
Loongson Advanced SIMD Extension (LASX) introduces 256 bit wide vector
|
||||
registers and a set of SIMD instructions to operate on them. When this
|
||||
option is enabled the kernel will support allocating & switching LASX
|
||||
vector register contexts. If you know that your kernel will only be
|
||||
running on CPUs which do not support LASX or that your userland will
|
||||
not be making use of it then you may wish to say N here to reduce
|
||||
the size & complexity of your kernel.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config CPU_HAS_PREFETCH
|
||||
bool
|
||||
default y
|
||||
|
||||
config KEXEC
|
||||
bool "Kexec system call"
|
||||
select KEXEC_CORE
|
||||
@@ -592,6 +646,9 @@ config ARCH_MMAP_RND_BITS_MIN
|
||||
config ARCH_MMAP_RND_BITS_MAX
|
||||
default 18
|
||||
|
||||
config ARCH_SUPPORTS_UPROBES
|
||||
def_bool y
|
||||
|
||||
menu "Power management options"
|
||||
|
||||
config ARCH_SUSPEND_POSSIBLE
|
||||
|
||||
+14
-9
@@ -46,8 +46,8 @@ ld-emul = $(64bit-emul)
|
||||
cflags-y += -mabi=lp64s
|
||||
endif
|
||||
|
||||
cflags-y += -G0 -pipe -msoft-float
|
||||
LDFLAGS_vmlinux += -G0 -static -n -nostdlib
|
||||
cflags-y += -pipe -msoft-float
|
||||
LDFLAGS_vmlinux += -static -n -nostdlib
|
||||
|
||||
# When the assembler supports explicit relocation hint, we must use it.
|
||||
# GCC may have -mexplicit-relocs off by default if it was built with an old
|
||||
@@ -56,13 +56,18 @@ LDFLAGS_vmlinux += -G0 -static -n -nostdlib
|
||||
# When the assembler does not supports explicit relocation hint, we can't use
|
||||
# it. Disable it if the compiler supports it.
|
||||
#
|
||||
# If you've seen "unknown reloc hint" message building the kernel and you are
|
||||
# now wondering why "-mexplicit-relocs" is not wrapped with cc-option: the
|
||||
# combination of a "new" assembler and "old" compiler is not supported. Either
|
||||
# upgrade the compiler or downgrade the assembler.
|
||||
# The combination of a "new" assembler and "old" GCC is not supported, given
|
||||
# the rarity of this combo and the extra complexity needed to make it work.
|
||||
# Either upgrade the compiler or downgrade the assembler; the build will error
|
||||
# out if it is the case (by probing for the model attribute; all supported
|
||||
# compilers in this case would have support).
|
||||
#
|
||||
# Also, -mdirect-extern-access is useful in case of building with explicit
|
||||
# relocs, for avoiding unnecessary GOT accesses. It is harmless to not have
|
||||
# support though.
|
||||
ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS
|
||||
cflags-y += -mexplicit-relocs
|
||||
KBUILD_CFLAGS_KERNEL += -mdirect-extern-access
|
||||
cflags-y += $(call cc-option,-mexplicit-relocs)
|
||||
KBUILD_CFLAGS_KERNEL += $(call cc-option,-mdirect-extern-access)
|
||||
else
|
||||
cflags-y += $(call cc-option,-mno-explicit-relocs)
|
||||
KBUILD_AFLAGS_KERNEL += -Wa,-mla-global-with-pcrel
|
||||
@@ -107,7 +112,7 @@ KBUILD_CFLAGS += -isystem $(shell $(CC) -print-file-name=include)
|
||||
KBUILD_LDFLAGS += -m $(ld-emul)
|
||||
|
||||
ifdef CONFIG_LOONGARCH
|
||||
CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
|
||||
CHECKFLAGS += $(shell $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
|
||||
grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
|
||||
sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
|
||||
endif
|
||||
|
||||
@@ -5,7 +5,6 @@ generic-y += mcs_spinlock.h
|
||||
generic-y += parport.h
|
||||
generic-y += early_ioremap.h
|
||||
generic-y += qrwlock.h
|
||||
generic-y += qspinlock.h
|
||||
generic-y += rwsem.h
|
||||
generic-y += segment.h
|
||||
generic-y += user.h
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
#ifndef _ASM_LOONGARCH_ACPI_H
|
||||
#define _ASM_LOONGARCH_ACPI_H
|
||||
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
extern int acpi_strict;
|
||||
extern int acpi_disabled;
|
||||
extern int acpi_pci_disabled;
|
||||
extern int acpi_noirq;
|
||||
extern int pptt_enabled;
|
||||
|
||||
#define acpi_os_ioremap acpi_os_ioremap
|
||||
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
|
||||
@@ -30,6 +33,14 @@ static inline bool acpi_has_cpu_in_madt(void)
|
||||
}
|
||||
|
||||
extern struct list_head acpi_wakeup_device_list;
|
||||
extern struct acpi_madt_core_pic acpi_core_pic[NR_CPUS];
|
||||
|
||||
extern int __init parse_acpi_topology(void);
|
||||
|
||||
static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
|
||||
{
|
||||
return acpi_core_pic[cpu_logical_map(cpu)].processor_id;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_ACPI */
|
||||
|
||||
@@ -37,12 +48,10 @@ extern struct list_head acpi_wakeup_device_list;
|
||||
|
||||
extern int loongarch_acpi_suspend(void);
|
||||
extern int (*acpi_suspend_lowlevel)(void);
|
||||
extern void loongarch_suspend_enter(void);
|
||||
|
||||
static inline unsigned long acpi_get_wakeup_address(void)
|
||||
{
|
||||
#ifdef CONFIG_SUSPEND
|
||||
extern void loongarch_wakeup_start(void);
|
||||
return (unsigned long)loongarch_wakeup_start;
|
||||
#endif
|
||||
return 0UL;
|
||||
|
||||
@@ -270,6 +270,399 @@
|
||||
fld.d $f31, \tmp, THREAD_FPR31 - THREAD_FPR0
|
||||
.endm
|
||||
|
||||
.macro lsx_save_data thread tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \tmp, \thread, \tmp
|
||||
vst $vr0, \tmp, THREAD_FPR0 - THREAD_FPR0
|
||||
vst $vr1, \tmp, THREAD_FPR1 - THREAD_FPR0
|
||||
vst $vr2, \tmp, THREAD_FPR2 - THREAD_FPR0
|
||||
vst $vr3, \tmp, THREAD_FPR3 - THREAD_FPR0
|
||||
vst $vr4, \tmp, THREAD_FPR4 - THREAD_FPR0
|
||||
vst $vr5, \tmp, THREAD_FPR5 - THREAD_FPR0
|
||||
vst $vr6, \tmp, THREAD_FPR6 - THREAD_FPR0
|
||||
vst $vr7, \tmp, THREAD_FPR7 - THREAD_FPR0
|
||||
vst $vr8, \tmp, THREAD_FPR8 - THREAD_FPR0
|
||||
vst $vr9, \tmp, THREAD_FPR9 - THREAD_FPR0
|
||||
vst $vr10, \tmp, THREAD_FPR10 - THREAD_FPR0
|
||||
vst $vr11, \tmp, THREAD_FPR11 - THREAD_FPR0
|
||||
vst $vr12, \tmp, THREAD_FPR12 - THREAD_FPR0
|
||||
vst $vr13, \tmp, THREAD_FPR13 - THREAD_FPR0
|
||||
vst $vr14, \tmp, THREAD_FPR14 - THREAD_FPR0
|
||||
vst $vr15, \tmp, THREAD_FPR15 - THREAD_FPR0
|
||||
vst $vr16, \tmp, THREAD_FPR16 - THREAD_FPR0
|
||||
vst $vr17, \tmp, THREAD_FPR17 - THREAD_FPR0
|
||||
vst $vr18, \tmp, THREAD_FPR18 - THREAD_FPR0
|
||||
vst $vr19, \tmp, THREAD_FPR19 - THREAD_FPR0
|
||||
vst $vr20, \tmp, THREAD_FPR20 - THREAD_FPR0
|
||||
vst $vr21, \tmp, THREAD_FPR21 - THREAD_FPR0
|
||||
vst $vr22, \tmp, THREAD_FPR22 - THREAD_FPR0
|
||||
vst $vr23, \tmp, THREAD_FPR23 - THREAD_FPR0
|
||||
vst $vr24, \tmp, THREAD_FPR24 - THREAD_FPR0
|
||||
vst $vr25, \tmp, THREAD_FPR25 - THREAD_FPR0
|
||||
vst $vr26, \tmp, THREAD_FPR26 - THREAD_FPR0
|
||||
vst $vr27, \tmp, THREAD_FPR27 - THREAD_FPR0
|
||||
vst $vr28, \tmp, THREAD_FPR28 - THREAD_FPR0
|
||||
vst $vr29, \tmp, THREAD_FPR29 - THREAD_FPR0
|
||||
vst $vr30, \tmp, THREAD_FPR30 - THREAD_FPR0
|
||||
vst $vr31, \tmp, THREAD_FPR31 - THREAD_FPR0
|
||||
.endm
|
||||
|
||||
.macro lsx_restore_data thread tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \tmp, \thread, \tmp
|
||||
vld $vr0, \tmp, THREAD_FPR0 - THREAD_FPR0
|
||||
vld $vr1, \tmp, THREAD_FPR1 - THREAD_FPR0
|
||||
vld $vr2, \tmp, THREAD_FPR2 - THREAD_FPR0
|
||||
vld $vr3, \tmp, THREAD_FPR3 - THREAD_FPR0
|
||||
vld $vr4, \tmp, THREAD_FPR4 - THREAD_FPR0
|
||||
vld $vr5, \tmp, THREAD_FPR5 - THREAD_FPR0
|
||||
vld $vr6, \tmp, THREAD_FPR6 - THREAD_FPR0
|
||||
vld $vr7, \tmp, THREAD_FPR7 - THREAD_FPR0
|
||||
vld $vr8, \tmp, THREAD_FPR8 - THREAD_FPR0
|
||||
vld $vr9, \tmp, THREAD_FPR9 - THREAD_FPR0
|
||||
vld $vr10, \tmp, THREAD_FPR10 - THREAD_FPR0
|
||||
vld $vr11, \tmp, THREAD_FPR11 - THREAD_FPR0
|
||||
vld $vr12, \tmp, THREAD_FPR12 - THREAD_FPR0
|
||||
vld $vr13, \tmp, THREAD_FPR13 - THREAD_FPR0
|
||||
vld $vr14, \tmp, THREAD_FPR14 - THREAD_FPR0
|
||||
vld $vr15, \tmp, THREAD_FPR15 - THREAD_FPR0
|
||||
vld $vr16, \tmp, THREAD_FPR16 - THREAD_FPR0
|
||||
vld $vr17, \tmp, THREAD_FPR17 - THREAD_FPR0
|
||||
vld $vr18, \tmp, THREAD_FPR18 - THREAD_FPR0
|
||||
vld $vr19, \tmp, THREAD_FPR19 - THREAD_FPR0
|
||||
vld $vr20, \tmp, THREAD_FPR20 - THREAD_FPR0
|
||||
vld $vr21, \tmp, THREAD_FPR21 - THREAD_FPR0
|
||||
vld $vr22, \tmp, THREAD_FPR22 - THREAD_FPR0
|
||||
vld $vr23, \tmp, THREAD_FPR23 - THREAD_FPR0
|
||||
vld $vr24, \tmp, THREAD_FPR24 - THREAD_FPR0
|
||||
vld $vr25, \tmp, THREAD_FPR25 - THREAD_FPR0
|
||||
vld $vr26, \tmp, THREAD_FPR26 - THREAD_FPR0
|
||||
vld $vr27, \tmp, THREAD_FPR27 - THREAD_FPR0
|
||||
vld $vr28, \tmp, THREAD_FPR28 - THREAD_FPR0
|
||||
vld $vr29, \tmp, THREAD_FPR29 - THREAD_FPR0
|
||||
vld $vr30, \tmp, THREAD_FPR30 - THREAD_FPR0
|
||||
vld $vr31, \tmp, THREAD_FPR31 - THREAD_FPR0
|
||||
.endm
|
||||
|
||||
.macro lsx_save_all thread tmp0 tmp1
|
||||
fpu_save_cc \thread, \tmp0, \tmp1
|
||||
fpu_save_csr \thread, \tmp0
|
||||
lsx_save_data \thread, \tmp0
|
||||
.endm
|
||||
|
||||
.macro lsx_restore_all thread tmp0 tmp1
|
||||
lsx_restore_data \thread, \tmp0
|
||||
fpu_restore_cc \thread, \tmp0, \tmp1
|
||||
fpu_restore_csr \thread, \tmp0
|
||||
.endm
|
||||
|
||||
.macro lsx_save_upper vd base tmp off
|
||||
vpickve2gr.d \tmp, \vd, 1
|
||||
st.d \tmp, \base, (\off+8)
|
||||
.endm
|
||||
|
||||
.macro lsx_save_all_upper thread base tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \base, \thread, \tmp
|
||||
lsx_save_upper $vr0, \base, \tmp, (THREAD_FPR0-THREAD_FPR0)
|
||||
lsx_save_upper $vr1, \base, \tmp, (THREAD_FPR1-THREAD_FPR0)
|
||||
lsx_save_upper $vr2, \base, \tmp, (THREAD_FPR2-THREAD_FPR0)
|
||||
lsx_save_upper $vr3, \base, \tmp, (THREAD_FPR3-THREAD_FPR0)
|
||||
lsx_save_upper $vr4, \base, \tmp, (THREAD_FPR4-THREAD_FPR0)
|
||||
lsx_save_upper $vr5, \base, \tmp, (THREAD_FPR5-THREAD_FPR0)
|
||||
lsx_save_upper $vr6, \base, \tmp, (THREAD_FPR6-THREAD_FPR0)
|
||||
lsx_save_upper $vr7, \base, \tmp, (THREAD_FPR7-THREAD_FPR0)
|
||||
lsx_save_upper $vr8, \base, \tmp, (THREAD_FPR8-THREAD_FPR0)
|
||||
lsx_save_upper $vr9, \base, \tmp, (THREAD_FPR9-THREAD_FPR0)
|
||||
lsx_save_upper $vr10, \base, \tmp, (THREAD_FPR10-THREAD_FPR0)
|
||||
lsx_save_upper $vr11, \base, \tmp, (THREAD_FPR11-THREAD_FPR0)
|
||||
lsx_save_upper $vr12, \base, \tmp, (THREAD_FPR12-THREAD_FPR0)
|
||||
lsx_save_upper $vr13, \base, \tmp, (THREAD_FPR13-THREAD_FPR0)
|
||||
lsx_save_upper $vr14, \base, \tmp, (THREAD_FPR14-THREAD_FPR0)
|
||||
lsx_save_upper $vr15, \base, \tmp, (THREAD_FPR15-THREAD_FPR0)
|
||||
lsx_save_upper $vr16, \base, \tmp, (THREAD_FPR16-THREAD_FPR0)
|
||||
lsx_save_upper $vr17, \base, \tmp, (THREAD_FPR17-THREAD_FPR0)
|
||||
lsx_save_upper $vr18, \base, \tmp, (THREAD_FPR18-THREAD_FPR0)
|
||||
lsx_save_upper $vr19, \base, \tmp, (THREAD_FPR19-THREAD_FPR0)
|
||||
lsx_save_upper $vr20, \base, \tmp, (THREAD_FPR20-THREAD_FPR0)
|
||||
lsx_save_upper $vr21, \base, \tmp, (THREAD_FPR21-THREAD_FPR0)
|
||||
lsx_save_upper $vr22, \base, \tmp, (THREAD_FPR22-THREAD_FPR0)
|
||||
lsx_save_upper $vr23, \base, \tmp, (THREAD_FPR23-THREAD_FPR0)
|
||||
lsx_save_upper $vr24, \base, \tmp, (THREAD_FPR24-THREAD_FPR0)
|
||||
lsx_save_upper $vr25, \base, \tmp, (THREAD_FPR25-THREAD_FPR0)
|
||||
lsx_save_upper $vr26, \base, \tmp, (THREAD_FPR26-THREAD_FPR0)
|
||||
lsx_save_upper $vr27, \base, \tmp, (THREAD_FPR27-THREAD_FPR0)
|
||||
lsx_save_upper $vr28, \base, \tmp, (THREAD_FPR28-THREAD_FPR0)
|
||||
lsx_save_upper $vr29, \base, \tmp, (THREAD_FPR29-THREAD_FPR0)
|
||||
lsx_save_upper $vr30, \base, \tmp, (THREAD_FPR30-THREAD_FPR0)
|
||||
lsx_save_upper $vr31, \base, \tmp, (THREAD_FPR31-THREAD_FPR0)
|
||||
.endm
|
||||
|
||||
.macro lsx_restore_upper vd base tmp off
|
||||
ld.d \tmp, \base, (\off+8)
|
||||
vinsgr2vr.d \vd, \tmp, 1
|
||||
.endm
|
||||
|
||||
.macro lsx_restore_all_upper thread base tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \base, \thread, \tmp
|
||||
lsx_restore_upper $vr0, \base, \tmp, (THREAD_FPR0-THREAD_FPR0)
|
||||
lsx_restore_upper $vr1, \base, \tmp, (THREAD_FPR1-THREAD_FPR0)
|
||||
lsx_restore_upper $vr2, \base, \tmp, (THREAD_FPR2-THREAD_FPR0)
|
||||
lsx_restore_upper $vr3, \base, \tmp, (THREAD_FPR3-THREAD_FPR0)
|
||||
lsx_restore_upper $vr4, \base, \tmp, (THREAD_FPR4-THREAD_FPR0)
|
||||
lsx_restore_upper $vr5, \base, \tmp, (THREAD_FPR5-THREAD_FPR0)
|
||||
lsx_restore_upper $vr6, \base, \tmp, (THREAD_FPR6-THREAD_FPR0)
|
||||
lsx_restore_upper $vr7, \base, \tmp, (THREAD_FPR7-THREAD_FPR0)
|
||||
lsx_restore_upper $vr8, \base, \tmp, (THREAD_FPR8-THREAD_FPR0)
|
||||
lsx_restore_upper $vr9, \base, \tmp, (THREAD_FPR9-THREAD_FPR0)
|
||||
lsx_restore_upper $vr10, \base, \tmp, (THREAD_FPR10-THREAD_FPR0)
|
||||
lsx_restore_upper $vr11, \base, \tmp, (THREAD_FPR11-THREAD_FPR0)
|
||||
lsx_restore_upper $vr12, \base, \tmp, (THREAD_FPR12-THREAD_FPR0)
|
||||
lsx_restore_upper $vr13, \base, \tmp, (THREAD_FPR13-THREAD_FPR0)
|
||||
lsx_restore_upper $vr14, \base, \tmp, (THREAD_FPR14-THREAD_FPR0)
|
||||
lsx_restore_upper $vr15, \base, \tmp, (THREAD_FPR15-THREAD_FPR0)
|
||||
lsx_restore_upper $vr16, \base, \tmp, (THREAD_FPR16-THREAD_FPR0)
|
||||
lsx_restore_upper $vr17, \base, \tmp, (THREAD_FPR17-THREAD_FPR0)
|
||||
lsx_restore_upper $vr18, \base, \tmp, (THREAD_FPR18-THREAD_FPR0)
|
||||
lsx_restore_upper $vr19, \base, \tmp, (THREAD_FPR19-THREAD_FPR0)
|
||||
lsx_restore_upper $vr20, \base, \tmp, (THREAD_FPR20-THREAD_FPR0)
|
||||
lsx_restore_upper $vr21, \base, \tmp, (THREAD_FPR21-THREAD_FPR0)
|
||||
lsx_restore_upper $vr22, \base, \tmp, (THREAD_FPR22-THREAD_FPR0)
|
||||
lsx_restore_upper $vr23, \base, \tmp, (THREAD_FPR23-THREAD_FPR0)
|
||||
lsx_restore_upper $vr24, \base, \tmp, (THREAD_FPR24-THREAD_FPR0)
|
||||
lsx_restore_upper $vr25, \base, \tmp, (THREAD_FPR25-THREAD_FPR0)
|
||||
lsx_restore_upper $vr26, \base, \tmp, (THREAD_FPR26-THREAD_FPR0)
|
||||
lsx_restore_upper $vr27, \base, \tmp, (THREAD_FPR27-THREAD_FPR0)
|
||||
lsx_restore_upper $vr28, \base, \tmp, (THREAD_FPR28-THREAD_FPR0)
|
||||
lsx_restore_upper $vr29, \base, \tmp, (THREAD_FPR29-THREAD_FPR0)
|
||||
lsx_restore_upper $vr30, \base, \tmp, (THREAD_FPR30-THREAD_FPR0)
|
||||
lsx_restore_upper $vr31, \base, \tmp, (THREAD_FPR31-THREAD_FPR0)
|
||||
.endm
|
||||
|
||||
.macro lsx_init_upper vd tmp
|
||||
vinsgr2vr.d \vd, \tmp, 1
|
||||
.endm
|
||||
|
||||
.macro lsx_init_all_upper tmp
|
||||
not \tmp, zero
|
||||
lsx_init_upper $vr0 \tmp
|
||||
lsx_init_upper $vr1 \tmp
|
||||
lsx_init_upper $vr2 \tmp
|
||||
lsx_init_upper $vr3 \tmp
|
||||
lsx_init_upper $vr4 \tmp
|
||||
lsx_init_upper $vr5 \tmp
|
||||
lsx_init_upper $vr6 \tmp
|
||||
lsx_init_upper $vr7 \tmp
|
||||
lsx_init_upper $vr8 \tmp
|
||||
lsx_init_upper $vr9 \tmp
|
||||
lsx_init_upper $vr10 \tmp
|
||||
lsx_init_upper $vr11 \tmp
|
||||
lsx_init_upper $vr12 \tmp
|
||||
lsx_init_upper $vr13 \tmp
|
||||
lsx_init_upper $vr14 \tmp
|
||||
lsx_init_upper $vr15 \tmp
|
||||
lsx_init_upper $vr16 \tmp
|
||||
lsx_init_upper $vr17 \tmp
|
||||
lsx_init_upper $vr18 \tmp
|
||||
lsx_init_upper $vr19 \tmp
|
||||
lsx_init_upper $vr20 \tmp
|
||||
lsx_init_upper $vr21 \tmp
|
||||
lsx_init_upper $vr22 \tmp
|
||||
lsx_init_upper $vr23 \tmp
|
||||
lsx_init_upper $vr24 \tmp
|
||||
lsx_init_upper $vr25 \tmp
|
||||
lsx_init_upper $vr26 \tmp
|
||||
lsx_init_upper $vr27 \tmp
|
||||
lsx_init_upper $vr28 \tmp
|
||||
lsx_init_upper $vr29 \tmp
|
||||
lsx_init_upper $vr30 \tmp
|
||||
lsx_init_upper $vr31 \tmp
|
||||
.endm
|
||||
|
||||
.macro lasx_save_data thread tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \tmp, \thread, \tmp
|
||||
xvst $xr0, \tmp, THREAD_FPR0 - THREAD_FPR0
|
||||
xvst $xr1, \tmp, THREAD_FPR1 - THREAD_FPR0
|
||||
xvst $xr2, \tmp, THREAD_FPR2 - THREAD_FPR0
|
||||
xvst $xr3, \tmp, THREAD_FPR3 - THREAD_FPR0
|
||||
xvst $xr4, \tmp, THREAD_FPR4 - THREAD_FPR0
|
||||
xvst $xr5, \tmp, THREAD_FPR5 - THREAD_FPR0
|
||||
xvst $xr6, \tmp, THREAD_FPR6 - THREAD_FPR0
|
||||
xvst $xr7, \tmp, THREAD_FPR7 - THREAD_FPR0
|
||||
xvst $xr8, \tmp, THREAD_FPR8 - THREAD_FPR0
|
||||
xvst $xr9, \tmp, THREAD_FPR9 - THREAD_FPR0
|
||||
xvst $xr10, \tmp, THREAD_FPR10 - THREAD_FPR0
|
||||
xvst $xr11, \tmp, THREAD_FPR11 - THREAD_FPR0
|
||||
xvst $xr12, \tmp, THREAD_FPR12 - THREAD_FPR0
|
||||
xvst $xr13, \tmp, THREAD_FPR13 - THREAD_FPR0
|
||||
xvst $xr14, \tmp, THREAD_FPR14 - THREAD_FPR0
|
||||
xvst $xr15, \tmp, THREAD_FPR15 - THREAD_FPR0
|
||||
xvst $xr16, \tmp, THREAD_FPR16 - THREAD_FPR0
|
||||
xvst $xr17, \tmp, THREAD_FPR17 - THREAD_FPR0
|
||||
xvst $xr18, \tmp, THREAD_FPR18 - THREAD_FPR0
|
||||
xvst $xr19, \tmp, THREAD_FPR19 - THREAD_FPR0
|
||||
xvst $xr20, \tmp, THREAD_FPR20 - THREAD_FPR0
|
||||
xvst $xr21, \tmp, THREAD_FPR21 - THREAD_FPR0
|
||||
xvst $xr22, \tmp, THREAD_FPR22 - THREAD_FPR0
|
||||
xvst $xr23, \tmp, THREAD_FPR23 - THREAD_FPR0
|
||||
xvst $xr24, \tmp, THREAD_FPR24 - THREAD_FPR0
|
||||
xvst $xr25, \tmp, THREAD_FPR25 - THREAD_FPR0
|
||||
xvst $xr26, \tmp, THREAD_FPR26 - THREAD_FPR0
|
||||
xvst $xr27, \tmp, THREAD_FPR27 - THREAD_FPR0
|
||||
xvst $xr28, \tmp, THREAD_FPR28 - THREAD_FPR0
|
||||
xvst $xr29, \tmp, THREAD_FPR29 - THREAD_FPR0
|
||||
xvst $xr30, \tmp, THREAD_FPR30 - THREAD_FPR0
|
||||
xvst $xr31, \tmp, THREAD_FPR31 - THREAD_FPR0
|
||||
.endm
|
||||
|
||||
.macro lasx_restore_data thread tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \tmp, \thread, \tmp
|
||||
xvld $xr0, \tmp, THREAD_FPR0 - THREAD_FPR0
|
||||
xvld $xr1, \tmp, THREAD_FPR1 - THREAD_FPR0
|
||||
xvld $xr2, \tmp, THREAD_FPR2 - THREAD_FPR0
|
||||
xvld $xr3, \tmp, THREAD_FPR3 - THREAD_FPR0
|
||||
xvld $xr4, \tmp, THREAD_FPR4 - THREAD_FPR0
|
||||
xvld $xr5, \tmp, THREAD_FPR5 - THREAD_FPR0
|
||||
xvld $xr6, \tmp, THREAD_FPR6 - THREAD_FPR0
|
||||
xvld $xr7, \tmp, THREAD_FPR7 - THREAD_FPR0
|
||||
xvld $xr8, \tmp, THREAD_FPR8 - THREAD_FPR0
|
||||
xvld $xr9, \tmp, THREAD_FPR9 - THREAD_FPR0
|
||||
xvld $xr10, \tmp, THREAD_FPR10 - THREAD_FPR0
|
||||
xvld $xr11, \tmp, THREAD_FPR11 - THREAD_FPR0
|
||||
xvld $xr12, \tmp, THREAD_FPR12 - THREAD_FPR0
|
||||
xvld $xr13, \tmp, THREAD_FPR13 - THREAD_FPR0
|
||||
xvld $xr14, \tmp, THREAD_FPR14 - THREAD_FPR0
|
||||
xvld $xr15, \tmp, THREAD_FPR15 - THREAD_FPR0
|
||||
xvld $xr16, \tmp, THREAD_FPR16 - THREAD_FPR0
|
||||
xvld $xr17, \tmp, THREAD_FPR17 - THREAD_FPR0
|
||||
xvld $xr18, \tmp, THREAD_FPR18 - THREAD_FPR0
|
||||
xvld $xr19, \tmp, THREAD_FPR19 - THREAD_FPR0
|
||||
xvld $xr20, \tmp, THREAD_FPR20 - THREAD_FPR0
|
||||
xvld $xr21, \tmp, THREAD_FPR21 - THREAD_FPR0
|
||||
xvld $xr22, \tmp, THREAD_FPR22 - THREAD_FPR0
|
||||
xvld $xr23, \tmp, THREAD_FPR23 - THREAD_FPR0
|
||||
xvld $xr24, \tmp, THREAD_FPR24 - THREAD_FPR0
|
||||
xvld $xr25, \tmp, THREAD_FPR25 - THREAD_FPR0
|
||||
xvld $xr26, \tmp, THREAD_FPR26 - THREAD_FPR0
|
||||
xvld $xr27, \tmp, THREAD_FPR27 - THREAD_FPR0
|
||||
xvld $xr28, \tmp, THREAD_FPR28 - THREAD_FPR0
|
||||
xvld $xr29, \tmp, THREAD_FPR29 - THREAD_FPR0
|
||||
xvld $xr30, \tmp, THREAD_FPR30 - THREAD_FPR0
|
||||
xvld $xr31, \tmp, THREAD_FPR31 - THREAD_FPR0
|
||||
.endm
|
||||
|
||||
.macro lasx_save_all thread tmp0 tmp1
|
||||
fpu_save_cc \thread, \tmp0, \tmp1
|
||||
fpu_save_csr \thread, \tmp0
|
||||
lasx_save_data \thread, \tmp0
|
||||
.endm
|
||||
|
||||
.macro lasx_restore_all thread tmp0 tmp1
|
||||
lasx_restore_data \thread, \tmp0
|
||||
fpu_restore_cc \thread, \tmp0, \tmp1
|
||||
fpu_restore_csr \thread, \tmp0
|
||||
.endm
|
||||
|
||||
.macro lasx_save_upper xd base tmp off
|
||||
/* Nothing */
|
||||
.endm
|
||||
|
||||
.macro lasx_save_all_upper thread base tmp
|
||||
/* Nothing */
|
||||
.endm
|
||||
|
||||
.macro lasx_restore_upper xd base tmp0 tmp1 off
|
||||
vld \tmp0, \base, (\off+16)
|
||||
xvpermi.q \xd, \tmp1, 0x2
|
||||
.endm
|
||||
|
||||
.macro lasx_restore_all_upper thread base tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \base, \thread, \tmp
|
||||
/* Save $vr31 ($xr31 lower bits) with xvpickve2gr */
|
||||
xvpickve2gr.d $r17, $xr31, 0
|
||||
xvpickve2gr.d $r18, $xr31, 1
|
||||
lasx_restore_upper $xr0, \base, $vr31, $xr31, (THREAD_FPR0-THREAD_FPR0)
|
||||
lasx_restore_upper $xr1, \base, $vr31, $xr31, (THREAD_FPR1-THREAD_FPR0)
|
||||
lasx_restore_upper $xr2, \base, $vr31, $xr31, (THREAD_FPR2-THREAD_FPR0)
|
||||
lasx_restore_upper $xr3, \base, $vr31, $xr31, (THREAD_FPR3-THREAD_FPR0)
|
||||
lasx_restore_upper $xr4, \base, $vr31, $xr31, (THREAD_FPR4-THREAD_FPR0)
|
||||
lasx_restore_upper $xr5, \base, $vr31, $xr31, (THREAD_FPR5-THREAD_FPR0)
|
||||
lasx_restore_upper $xr6, \base, $vr31, $xr31, (THREAD_FPR6-THREAD_FPR0)
|
||||
lasx_restore_upper $xr7, \base, $vr31, $xr31, (THREAD_FPR7-THREAD_FPR0)
|
||||
lasx_restore_upper $xr8, \base, $vr31, $xr31, (THREAD_FPR8-THREAD_FPR0)
|
||||
lasx_restore_upper $xr9, \base, $vr31, $xr31, (THREAD_FPR9-THREAD_FPR0)
|
||||
lasx_restore_upper $xr10, \base, $vr31, $xr31, (THREAD_FPR10-THREAD_FPR0)
|
||||
lasx_restore_upper $xr11, \base, $vr31, $xr31, (THREAD_FPR11-THREAD_FPR0)
|
||||
lasx_restore_upper $xr12, \base, $vr31, $xr31, (THREAD_FPR12-THREAD_FPR0)
|
||||
lasx_restore_upper $xr13, \base, $vr31, $xr31, (THREAD_FPR13-THREAD_FPR0)
|
||||
lasx_restore_upper $xr14, \base, $vr31, $xr31, (THREAD_FPR14-THREAD_FPR0)
|
||||
lasx_restore_upper $xr15, \base, $vr31, $xr31, (THREAD_FPR15-THREAD_FPR0)
|
||||
lasx_restore_upper $xr16, \base, $vr31, $xr31, (THREAD_FPR16-THREAD_FPR0)
|
||||
lasx_restore_upper $xr17, \base, $vr31, $xr31, (THREAD_FPR17-THREAD_FPR0)
|
||||
lasx_restore_upper $xr18, \base, $vr31, $xr31, (THREAD_FPR18-THREAD_FPR0)
|
||||
lasx_restore_upper $xr19, \base, $vr31, $xr31, (THREAD_FPR19-THREAD_FPR0)
|
||||
lasx_restore_upper $xr20, \base, $vr31, $xr31, (THREAD_FPR20-THREAD_FPR0)
|
||||
lasx_restore_upper $xr21, \base, $vr31, $xr31, (THREAD_FPR21-THREAD_FPR0)
|
||||
lasx_restore_upper $xr22, \base, $vr31, $xr31, (THREAD_FPR22-THREAD_FPR0)
|
||||
lasx_restore_upper $xr23, \base, $vr31, $xr31, (THREAD_FPR23-THREAD_FPR0)
|
||||
lasx_restore_upper $xr24, \base, $vr31, $xr31, (THREAD_FPR24-THREAD_FPR0)
|
||||
lasx_restore_upper $xr25, \base, $vr31, $xr31, (THREAD_FPR25-THREAD_FPR0)
|
||||
lasx_restore_upper $xr26, \base, $vr31, $xr31, (THREAD_FPR26-THREAD_FPR0)
|
||||
lasx_restore_upper $xr27, \base, $vr31, $xr31, (THREAD_FPR27-THREAD_FPR0)
|
||||
lasx_restore_upper $xr28, \base, $vr31, $xr31, (THREAD_FPR28-THREAD_FPR0)
|
||||
lasx_restore_upper $xr29, \base, $vr31, $xr31, (THREAD_FPR29-THREAD_FPR0)
|
||||
lasx_restore_upper $xr30, \base, $vr31, $xr31, (THREAD_FPR30-THREAD_FPR0)
|
||||
lasx_restore_upper $xr31, \base, $vr31, $xr31, (THREAD_FPR31-THREAD_FPR0)
|
||||
/* Restore $vr31 ($xr31 lower bits) with xvinsgr2vr */
|
||||
xvinsgr2vr.d $xr31, $r17, 0
|
||||
xvinsgr2vr.d $xr31, $r18, 1
|
||||
.endm
|
||||
|
||||
.macro lasx_init_upper xd tmp
|
||||
xvinsgr2vr.d \xd, \tmp, 2
|
||||
xvinsgr2vr.d \xd, \tmp, 3
|
||||
.endm
|
||||
|
||||
.macro lasx_init_all_upper tmp
|
||||
not \tmp, zero
|
||||
lasx_init_upper $xr0 \tmp
|
||||
lasx_init_upper $xr1 \tmp
|
||||
lasx_init_upper $xr2 \tmp
|
||||
lasx_init_upper $xr3 \tmp
|
||||
lasx_init_upper $xr4 \tmp
|
||||
lasx_init_upper $xr5 \tmp
|
||||
lasx_init_upper $xr6 \tmp
|
||||
lasx_init_upper $xr7 \tmp
|
||||
lasx_init_upper $xr8 \tmp
|
||||
lasx_init_upper $xr9 \tmp
|
||||
lasx_init_upper $xr10 \tmp
|
||||
lasx_init_upper $xr11 \tmp
|
||||
lasx_init_upper $xr12 \tmp
|
||||
lasx_init_upper $xr13 \tmp
|
||||
lasx_init_upper $xr14 \tmp
|
||||
lasx_init_upper $xr15 \tmp
|
||||
lasx_init_upper $xr16 \tmp
|
||||
lasx_init_upper $xr17 \tmp
|
||||
lasx_init_upper $xr18 \tmp
|
||||
lasx_init_upper $xr19 \tmp
|
||||
lasx_init_upper $xr20 \tmp
|
||||
lasx_init_upper $xr21 \tmp
|
||||
lasx_init_upper $xr22 \tmp
|
||||
lasx_init_upper $xr23 \tmp
|
||||
lasx_init_upper $xr24 \tmp
|
||||
lasx_init_upper $xr25 \tmp
|
||||
lasx_init_upper $xr26 \tmp
|
||||
lasx_init_upper $xr27 \tmp
|
||||
lasx_init_upper $xr28 \tmp
|
||||
lasx_init_upper $xr29 \tmp
|
||||
lasx_init_upper $xr30 \tmp
|
||||
lasx_init_upper $xr31 \tmp
|
||||
.endm
|
||||
|
||||
.macro not dst src
|
||||
nor \dst, \src, zero
|
||||
.endm
|
||||
|
||||
@@ -5,27 +5,56 @@
|
||||
#ifndef __ASM_BARRIER_H
|
||||
#define __ASM_BARRIER_H
|
||||
|
||||
#define __sync() __asm__ __volatile__("dbar 0" : : : "memory")
|
||||
/*
|
||||
* Hint encoding:
|
||||
*
|
||||
* Bit4: ordering or completion (0: completion, 1: ordering)
|
||||
* Bit3: barrier for previous read (0: true, 1: false)
|
||||
* Bit2: barrier for previous write (0: true, 1: false)
|
||||
* Bit1: barrier for succeeding read (0: true, 1: false)
|
||||
* Bit0: barrier for succeeding write (0: true, 1: false)
|
||||
*
|
||||
* Hint 0x700: barrier for "read after read" from the same address
|
||||
*/
|
||||
|
||||
#define fast_wmb() __sync()
|
||||
#define fast_rmb() __sync()
|
||||
#define fast_mb() __sync()
|
||||
#define fast_iob() __sync()
|
||||
#define wbflush() __sync()
|
||||
#define DBAR(hint) __asm__ __volatile__("dbar %0 " : : "I"(hint) : "memory")
|
||||
|
||||
#define wmb() fast_wmb()
|
||||
#define rmb() fast_rmb()
|
||||
#define mb() fast_mb()
|
||||
#define iob() fast_iob()
|
||||
#define crwrw 0b00000
|
||||
#define cr_r_ 0b00101
|
||||
#define c_w_w 0b01010
|
||||
|
||||
#define __smp_mb() __asm__ __volatile__("dbar 0" : : : "memory")
|
||||
#define __smp_rmb() __asm__ __volatile__("dbar 0" : : : "memory")
|
||||
#define __smp_wmb() __asm__ __volatile__("dbar 0" : : : "memory")
|
||||
#define orwrw 0b10000
|
||||
#define or_r_ 0b10101
|
||||
#define o_w_w 0b11010
|
||||
|
||||
#define orw_w 0b10010
|
||||
#define or_rw 0b10100
|
||||
|
||||
#define c_sync() DBAR(crwrw)
|
||||
#define c_rsync() DBAR(cr_r_)
|
||||
#define c_wsync() DBAR(c_w_w)
|
||||
|
||||
#define o_sync() DBAR(orwrw)
|
||||
#define o_rsync() DBAR(or_r_)
|
||||
#define o_wsync() DBAR(o_w_w)
|
||||
|
||||
#define ldacq_mb() DBAR(or_rw)
|
||||
#define strel_mb() DBAR(orw_w)
|
||||
|
||||
#define mb() c_sync()
|
||||
#define rmb() c_rsync()
|
||||
#define wmb() c_wsync()
|
||||
#define iob() c_sync()
|
||||
#define wbflush() c_sync()
|
||||
|
||||
#define __smp_mb() o_sync()
|
||||
#define __smp_rmb() o_rsync()
|
||||
#define __smp_wmb() o_wsync()
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define __WEAK_LLSC_MB " dbar 0 \n"
|
||||
#define __WEAK_LLSC_MB " dbar 0x700 \n"
|
||||
#else
|
||||
#define __WEAK_LLSC_MB " \n"
|
||||
#define __WEAK_LLSC_MB " \n"
|
||||
#endif
|
||||
|
||||
#define __smp_mb__before_atomic() barrier()
|
||||
@@ -59,68 +88,19 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
|
||||
return mask;
|
||||
}
|
||||
|
||||
#define __smp_load_acquire(p) \
|
||||
({ \
|
||||
union { typeof(*p) __val; char __c[1]; } __u; \
|
||||
unsigned long __tmp = 0; \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
switch (sizeof(*p)) { \
|
||||
case 1: \
|
||||
*(__u8 *)__u.__c = *(volatile __u8 *)p; \
|
||||
__smp_mb(); \
|
||||
break; \
|
||||
case 2: \
|
||||
*(__u16 *)__u.__c = *(volatile __u16 *)p; \
|
||||
__smp_mb(); \
|
||||
break; \
|
||||
case 4: \
|
||||
__asm__ __volatile__( \
|
||||
"amor_db.w %[val], %[tmp], %[mem] \n" \
|
||||
: [val] "=&r" (*(__u32 *)__u.__c) \
|
||||
: [mem] "ZB" (*(u32 *) p), [tmp] "r" (__tmp) \
|
||||
: "memory"); \
|
||||
break; \
|
||||
case 8: \
|
||||
__asm__ __volatile__( \
|
||||
"amor_db.d %[val], %[tmp], %[mem] \n" \
|
||||
: [val] "=&r" (*(__u64 *)__u.__c) \
|
||||
: [mem] "ZB" (*(u64 *) p), [tmp] "r" (__tmp) \
|
||||
: "memory"); \
|
||||
break; \
|
||||
} \
|
||||
(typeof(*p))__u.__val; \
|
||||
#define __smp_load_acquire(p) \
|
||||
({ \
|
||||
typeof(*p) ___p1 = READ_ONCE(*p); \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
ldacq_mb(); \
|
||||
___p1; \
|
||||
})
|
||||
|
||||
#define __smp_store_release(p, v) \
|
||||
do { \
|
||||
union { typeof(*p) __val; char __c[1]; } __u = \
|
||||
{ .__val = (__force typeof(*p)) (v) }; \
|
||||
unsigned long __tmp; \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
switch (sizeof(*p)) { \
|
||||
case 1: \
|
||||
__smp_mb(); \
|
||||
*(volatile __u8 *)p = *(__u8 *)__u.__c; \
|
||||
break; \
|
||||
case 2: \
|
||||
__smp_mb(); \
|
||||
*(volatile __u16 *)p = *(__u16 *)__u.__c; \
|
||||
break; \
|
||||
case 4: \
|
||||
__asm__ __volatile__( \
|
||||
"amswap_db.w %[tmp], %[val], %[mem] \n" \
|
||||
: [mem] "+ZB" (*(u32 *)p), [tmp] "=&r" (__tmp) \
|
||||
: [val] "r" (*(__u32 *)__u.__c) \
|
||||
: ); \
|
||||
break; \
|
||||
case 8: \
|
||||
__asm__ __volatile__( \
|
||||
"amswap_db.d %[tmp], %[val], %[mem] \n" \
|
||||
: [mem] "+ZB" (*(u64 *)p), [tmp] "=&r" (__tmp) \
|
||||
: [val] "r" (*(__u64 *)__u.__c) \
|
||||
: ); \
|
||||
break; \
|
||||
} \
|
||||
#define __smp_store_release(p, v) \
|
||||
do { \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
strel_mb(); \
|
||||
WRITE_ONCE(*p, v); \
|
||||
} while (0)
|
||||
|
||||
#define __smp_store_mb(p, v) \
|
||||
|
||||
@@ -64,6 +64,6 @@
|
||||
#define cpu_has_eiodecode cpu_opt(LOONGARCH_CPU_EIODECODE)
|
||||
#define cpu_has_guestid cpu_opt(LOONGARCH_CPU_GUESTID)
|
||||
#define cpu_has_hypervisor cpu_opt(LOONGARCH_CPU_HYPERVISOR)
|
||||
|
||||
#define cpu_has_ptw cpu_opt(LOONGARCH_CPU_PTW)
|
||||
|
||||
#endif /* __ASM_CPU_FEATURES_H */
|
||||
|
||||
@@ -54,6 +54,7 @@ struct cpuinfo_loongarch {
|
||||
struct cache_desc cache_leaves[CACHE_LEAVES_MAX];
|
||||
int core; /* physical core number in package */
|
||||
int package;/* physical package number */
|
||||
int global_id; /* physical global thread number */
|
||||
int vabits; /* Virtual Address size in bits */
|
||||
int pabits; /* Physical Address size in bits */
|
||||
unsigned int ksave_mask; /* Usable KSave mask. */
|
||||
|
||||
@@ -98,6 +98,7 @@ enum cpu_type_enum {
|
||||
#define CPU_FEATURE_EIODECODE 23 /* CPU has EXTIOI interrupt pin decode mode */
|
||||
#define CPU_FEATURE_GUESTID 24 /* CPU has GuestID feature */
|
||||
#define CPU_FEATURE_HYPERVISOR 25 /* CPU has hypervisor (running in VM) */
|
||||
#define CPU_FEATURE_PTW 26 /* CPU has hardware page table walker */
|
||||
|
||||
#define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG)
|
||||
#define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM)
|
||||
@@ -125,5 +126,6 @@ enum cpu_type_enum {
|
||||
#define LOONGARCH_CPU_EIODECODE BIT_ULL(CPU_FEATURE_EIODECODE)
|
||||
#define LOONGARCH_CPU_GUESTID BIT_ULL(CPU_FEATURE_GUESTID)
|
||||
#define LOONGARCH_CPU_HYPERVISOR BIT_ULL(CPU_FEATURE_HYPERVISOR)
|
||||
#define LOONGARCH_CPU_PTW BIT_ULL(CPU_FEATURE_PTW)
|
||||
|
||||
#endif /* _ASM_CPU_H */
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define fs6 $f30
|
||||
#define fs7 $f31
|
||||
|
||||
#ifndef CONFIG_AS_HAS_FCSR_CLASS
|
||||
/*
|
||||
* Current binutils expects *GPRs* at FCSR position for the FCSR
|
||||
* operation instructions, so define aliases for those used.
|
||||
@@ -48,5 +49,11 @@
|
||||
#define fcsr1 $r1
|
||||
#define fcsr2 $r2
|
||||
#define fcsr3 $r3
|
||||
#else
|
||||
#define fcsr0 $fcsr0
|
||||
#define fcsr1 $fcsr1
|
||||
#define fcsr2 $fcsr2
|
||||
#define fcsr3 $fcsr3
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_FPREGDEF_H */
|
||||
|
||||
@@ -28,6 +28,26 @@ extern void _init_fpu(unsigned int);
|
||||
extern void _save_fp(struct loongarch_fpu *);
|
||||
extern void _restore_fp(struct loongarch_fpu *);
|
||||
|
||||
extern void _save_lsx(struct loongarch_fpu *fpu);
|
||||
extern void _restore_lsx(struct loongarch_fpu *fpu);
|
||||
extern void _init_lsx_upper(void);
|
||||
extern void _restore_lsx_upper(struct loongarch_fpu *fpu);
|
||||
|
||||
extern void _save_lasx(struct loongarch_fpu *fpu);
|
||||
extern void _restore_lasx(struct loongarch_fpu *fpu);
|
||||
extern void _init_lasx_upper(void);
|
||||
extern void _restore_lasx_upper(struct loongarch_fpu *fpu);
|
||||
|
||||
static inline void enable_lsx(void);
|
||||
static inline void disable_lsx(void);
|
||||
static inline void save_lsx(struct task_struct *t);
|
||||
static inline void restore_lsx(struct task_struct *t);
|
||||
|
||||
static inline void enable_lasx(void);
|
||||
static inline void disable_lasx(void);
|
||||
static inline void save_lasx(struct task_struct *t);
|
||||
static inline void restore_lasx(struct task_struct *t);
|
||||
|
||||
/*
|
||||
* Mask the FCSR Cause bits according to the Enable bits, observing
|
||||
* that Unimplemented is always enabled.
|
||||
@@ -44,6 +64,29 @@ static inline int is_fp_enabled(void)
|
||||
1 : 0;
|
||||
}
|
||||
|
||||
static inline int is_lsx_enabled(void)
|
||||
{
|
||||
if (!cpu_has_lsx)
|
||||
return 0;
|
||||
|
||||
return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_LSXEN) ?
|
||||
1 : 0;
|
||||
}
|
||||
|
||||
static inline int is_lasx_enabled(void)
|
||||
{
|
||||
if (!cpu_has_lasx)
|
||||
return 0;
|
||||
|
||||
return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_LASXEN) ?
|
||||
1 : 0;
|
||||
}
|
||||
|
||||
static inline int is_simd_enabled(void)
|
||||
{
|
||||
return is_lsx_enabled() | is_lasx_enabled();
|
||||
}
|
||||
|
||||
#define enable_fpu() set_csr_euen(CSR_EUEN_FPEN)
|
||||
|
||||
#define disable_fpu() clear_csr_euen(CSR_EUEN_FPEN)
|
||||
@@ -81,9 +124,22 @@ static inline void own_fpu(int restore)
|
||||
static inline void lose_fpu_inatomic(int save, struct task_struct *tsk)
|
||||
{
|
||||
if (is_fpu_owner()) {
|
||||
if (save)
|
||||
_save_fp(&tsk->thread.fpu);
|
||||
disable_fpu();
|
||||
if (!is_simd_enabled()) {
|
||||
if (save)
|
||||
_save_fp(&tsk->thread.fpu);
|
||||
disable_fpu();
|
||||
} else {
|
||||
if (save) {
|
||||
if (!is_lasx_enabled())
|
||||
save_lsx(tsk);
|
||||
else
|
||||
save_lasx(tsk);
|
||||
}
|
||||
disable_fpu();
|
||||
disable_lsx();
|
||||
disable_lasx();
|
||||
clear_tsk_thread_flag(tsk, TIF_USEDSIMD);
|
||||
}
|
||||
clear_tsk_thread_flag(tsk, TIF_USEDFPU);
|
||||
}
|
||||
KSTK_EUEN(tsk) &= ~(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN);
|
||||
@@ -129,4 +185,127 @@ static inline union fpureg *get_fpu_regs(struct task_struct *tsk)
|
||||
return tsk->thread.fpu.fpr;
|
||||
}
|
||||
|
||||
static inline int is_simd_owner(void)
|
||||
{
|
||||
return test_thread_flag(TIF_USEDSIMD);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
|
||||
static inline void enable_lsx(void)
|
||||
{
|
||||
if (cpu_has_lsx)
|
||||
csr_xchg32(CSR_EUEN_LSXEN, CSR_EUEN_LSXEN, LOONGARCH_CSR_EUEN);
|
||||
}
|
||||
|
||||
static inline void disable_lsx(void)
|
||||
{
|
||||
if (cpu_has_lsx)
|
||||
csr_xchg32(0, CSR_EUEN_LSXEN, LOONGARCH_CSR_EUEN);
|
||||
}
|
||||
|
||||
static inline void save_lsx(struct task_struct *t)
|
||||
{
|
||||
if (cpu_has_lsx)
|
||||
_save_lsx(&t->thread.fpu);
|
||||
}
|
||||
|
||||
static inline void restore_lsx(struct task_struct *t)
|
||||
{
|
||||
if (cpu_has_lsx)
|
||||
_restore_lsx(&t->thread.fpu);
|
||||
}
|
||||
|
||||
static inline void init_lsx_upper(void)
|
||||
{
|
||||
/*
|
||||
* Check cpu_has_lsx only if it's a constant. This will allow the
|
||||
* compiler to optimise out code for CPUs without LSX without adding
|
||||
* an extra redundant check for CPUs with LSX.
|
||||
*/
|
||||
if (__builtin_constant_p(cpu_has_lsx) && !cpu_has_lsx)
|
||||
return;
|
||||
|
||||
_init_lsx_upper();
|
||||
}
|
||||
|
||||
static inline void restore_lsx_upper(struct task_struct *t)
|
||||
{
|
||||
if (cpu_has_lsx)
|
||||
_restore_lsx_upper(&t->thread.fpu);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void enable_lsx(void) {}
|
||||
static inline void disable_lsx(void) {}
|
||||
static inline void save_lsx(struct task_struct *t) {}
|
||||
static inline void restore_lsx(struct task_struct *t) {}
|
||||
static inline void init_lsx_upper(void) {}
|
||||
static inline void restore_lsx_upper(struct task_struct *t) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
|
||||
static inline void enable_lasx(void)
|
||||
{
|
||||
|
||||
if (cpu_has_lasx)
|
||||
csr_xchg32(CSR_EUEN_LASXEN, CSR_EUEN_LASXEN, LOONGARCH_CSR_EUEN);
|
||||
}
|
||||
|
||||
static inline void disable_lasx(void)
|
||||
{
|
||||
if (cpu_has_lasx)
|
||||
csr_xchg32(0, CSR_EUEN_LASXEN, LOONGARCH_CSR_EUEN);
|
||||
}
|
||||
|
||||
static inline void save_lasx(struct task_struct *t)
|
||||
{
|
||||
if (cpu_has_lasx)
|
||||
_save_lasx(&t->thread.fpu);
|
||||
}
|
||||
|
||||
static inline void restore_lasx(struct task_struct *t)
|
||||
{
|
||||
if (cpu_has_lasx)
|
||||
_restore_lasx(&t->thread.fpu);
|
||||
}
|
||||
|
||||
static inline void init_lasx_upper(void)
|
||||
{
|
||||
if (cpu_has_lasx)
|
||||
_init_lasx_upper();
|
||||
}
|
||||
|
||||
static inline void restore_lasx_upper(struct task_struct *t)
|
||||
{
|
||||
if (cpu_has_lasx)
|
||||
_restore_lasx_upper(&t->thread.fpu);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void enable_lasx(void) {}
|
||||
static inline void disable_lasx(void) {}
|
||||
static inline void save_lasx(struct task_struct *t) {}
|
||||
static inline void restore_lasx(struct task_struct *t) {}
|
||||
static inline void init_lasx_upper(void) {}
|
||||
static inline void restore_lasx_upper(struct task_struct *t) {}
|
||||
#endif
|
||||
|
||||
static inline int thread_lsx_context_live(void)
|
||||
{
|
||||
if (__builtin_constant_p(cpu_has_lsx) && !cpu_has_lsx)
|
||||
return 0;
|
||||
|
||||
return test_thread_flag(TIF_LSX_CTX_LIVE);
|
||||
}
|
||||
|
||||
static inline int thread_lasx_context_live(void)
|
||||
{
|
||||
if (__builtin_constant_p(cpu_has_lasx) && !cpu_has_lasx)
|
||||
return 0;
|
||||
|
||||
return test_thread_flag(TIF_LASX_CTX_LIVE);
|
||||
}
|
||||
|
||||
#endif /* _ASM_FPU_H */
|
||||
|
||||
@@ -100,4 +100,26 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
|
||||
|
||||
#endif /* CONFIG_FUNCTION_TRACER */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
struct fgraph_ret_regs {
|
||||
/* a0 - a1 */
|
||||
unsigned long regs[2];
|
||||
|
||||
unsigned long fp;
|
||||
unsigned long __unused;
|
||||
};
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->regs[0];
|
||||
}
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->fp;
|
||||
}
|
||||
#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_LOONGARCH_FTRACE_H */
|
||||
|
||||
@@ -9,6 +9,22 @@
|
||||
.equ .L__gpr_num_$r\num, \num
|
||||
.endr
|
||||
|
||||
/* ABI names of registers */
|
||||
.equ .L__gpr_num_$ra, 1
|
||||
.equ .L__gpr_num_$tp, 2
|
||||
.equ .L__gpr_num_$sp, 3
|
||||
.irp num,0,1,2,3,4,5,6,7
|
||||
.equ .L__gpr_num_$a\num, 4 + \num
|
||||
.endr
|
||||
.irp num,0,1,2,3,4,5,6,7,8
|
||||
.equ .L__gpr_num_$t\num, 12 + \num
|
||||
.endr
|
||||
.equ .L__gpr_num_$s9, 22
|
||||
.equ .L__gpr_num_$fp, 22
|
||||
.irp num,0,1,2,3,4,5,6,7,8
|
||||
.equ .L__gpr_num_$s\num, 23 + \num
|
||||
.endr
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#define __DEFINE_ASM_GPR_NUMS \
|
||||
@@ -16,6 +32,20 @@
|
||||
" .irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31\n" \
|
||||
" .equ .L__gpr_num_$r\\num, \\num\n" \
|
||||
" .endr\n" \
|
||||
" .equ .L__gpr_num_$ra, 1\n" \
|
||||
" .equ .L__gpr_num_$tp, 2\n" \
|
||||
" .equ .L__gpr_num_$sp, 3\n" \
|
||||
" .irp num,0,1,2,3,4,5,6,7\n" \
|
||||
" .equ .L__gpr_num_$a\\num, 4 + \\num\n" \
|
||||
" .endr\n" \
|
||||
" .irp num,0,1,2,3,4,5,6,7,8\n" \
|
||||
" .equ .L__gpr_num_$t\\num, 12 + \\num\n" \
|
||||
" .endr\n" \
|
||||
" .equ .L__gpr_num_$s9, 22\n" \
|
||||
" .equ .L__gpr_num_$fp, 22\n" \
|
||||
" .irp num,0,1,2,3,4,5,6,7,8\n" \
|
||||
" .equ .L__gpr_num_$s\\num, 23 + \\num\n" \
|
||||
" .endr\n" \
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef _ASM_INST_H
|
||||
#define _ASM_INST_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/ptrace.h>
|
||||
@@ -15,14 +16,22 @@
|
||||
#define ADDR_IMMMASK_LU52ID 0xFFF0000000000000
|
||||
#define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000
|
||||
#define ADDR_IMMMASK_LU12IW 0x00000000FFFFF000
|
||||
#define ADDR_IMMMASK_ORI 0x0000000000000FFF
|
||||
#define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000
|
||||
|
||||
#define ADDR_IMMSHIFT_LU52ID 52
|
||||
#define ADDR_IMMSBIDX_LU52ID 11
|
||||
#define ADDR_IMMSHIFT_LU32ID 32
|
||||
#define ADDR_IMMSBIDX_LU32ID 19
|
||||
#define ADDR_IMMSHIFT_LU12IW 12
|
||||
#define ADDR_IMMSBIDX_LU12IW 19
|
||||
#define ADDR_IMMSHIFT_ORI 0
|
||||
#define ADDR_IMMSBIDX_ORI 63
|
||||
#define ADDR_IMMSHIFT_ADDU16ID 16
|
||||
#define ADDR_IMMSBIDX_ADDU16ID 15
|
||||
|
||||
#define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN)
|
||||
#define ADDR_IMM(addr, INSN) \
|
||||
(sign_extend64(((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN), ADDR_IMMSBIDX_##INSN))
|
||||
|
||||
enum reg0i15_op {
|
||||
break_op = 0x54,
|
||||
@@ -178,6 +187,32 @@ enum reg3_op {
|
||||
amord_op = 0x70c7,
|
||||
amxorw_op = 0x70c8,
|
||||
amxord_op = 0x70c9,
|
||||
ammaxw_op = 0x70ca,
|
||||
ammaxd_op = 0x70cb,
|
||||
amminw_op = 0x70cc,
|
||||
ammind_op = 0x70cd,
|
||||
ammaxwu_op = 0x70ce,
|
||||
ammaxdu_op = 0x70cf,
|
||||
amminwu_op = 0x70d0,
|
||||
ammindu_op = 0x70d1,
|
||||
amswapdbw_op = 0x70d2,
|
||||
amswapdbd_op = 0x70d3,
|
||||
amadddbw_op = 0x70d4,
|
||||
amadddbd_op = 0x70d5,
|
||||
amanddbw_op = 0x70d6,
|
||||
amanddbd_op = 0x70d7,
|
||||
amordbw_op = 0x70d8,
|
||||
amordbd_op = 0x70d9,
|
||||
amxordbw_op = 0x70da,
|
||||
amxordbd_op = 0x70db,
|
||||
ammaxdbw_op = 0x70dc,
|
||||
ammaxdbd_op = 0x70dd,
|
||||
ammindbw_op = 0x70de,
|
||||
ammindbd_op = 0x70df,
|
||||
ammaxdbwu_op = 0x70e0,
|
||||
ammaxdbdu_op = 0x70e1,
|
||||
ammindbwu_op = 0x70e2,
|
||||
ammindbdu_op = 0x70e3,
|
||||
fldgts_op = 0x70e8,
|
||||
fldgtd_op = 0x70e9,
|
||||
fldles_op = 0x70ea,
|
||||
@@ -435,6 +470,10 @@ static inline bool is_self_loop_ins(union loongarch_instruction *ip, struct pt_r
|
||||
void simu_pc(struct pt_regs *regs, union loongarch_instruction insn);
|
||||
void simu_branch(struct pt_regs *regs, union loongarch_instruction insn);
|
||||
|
||||
bool insns_not_supported(union loongarch_instruction insn);
|
||||
bool insns_need_simulation(union loongarch_instruction insn);
|
||||
void arch_simulate_insn(union loongarch_instruction insn, struct pt_regs *regs);
|
||||
|
||||
int larch_insn_read(void *addr, u32 *insnp);
|
||||
int larch_insn_write(void *addr, u32 insn);
|
||||
int larch_insn_patch_text(void *addr, u32 insn);
|
||||
@@ -443,13 +482,15 @@ u32 larch_insn_gen_nop(void);
|
||||
u32 larch_insn_gen_b(unsigned long pc, unsigned long dest);
|
||||
u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest);
|
||||
|
||||
u32 larch_insn_gen_break(int imm);
|
||||
|
||||
u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk);
|
||||
u32 larch_insn_gen_move(enum loongarch_gpr rd, enum loongarch_gpr rj);
|
||||
|
||||
u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm);
|
||||
u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm);
|
||||
u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
|
||||
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest);
|
||||
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
|
||||
|
||||
static inline bool signed_imm_check(long val, unsigned int bit)
|
||||
{
|
||||
@@ -461,6 +502,16 @@ static inline bool unsigned_imm_check(unsigned long val, unsigned int bit)
|
||||
return val < (1UL << bit);
|
||||
}
|
||||
|
||||
#define DEF_EMIT_REG0I15_FORMAT(NAME, OP) \
|
||||
static inline void emit_##NAME(union loongarch_instruction *insn, \
|
||||
int imm) \
|
||||
{ \
|
||||
insn->reg0i15_format.opcode = OP; \
|
||||
insn->reg0i15_format.immediate = imm; \
|
||||
}
|
||||
|
||||
DEF_EMIT_REG0I15_FORMAT(break, break_op)
|
||||
|
||||
#define DEF_EMIT_REG0I26_FORMAT(NAME, OP) \
|
||||
static inline void emit_##NAME(union loongarch_instruction *insn, \
|
||||
int offset) \
|
||||
|
||||
@@ -62,7 +62,7 @@ extern pgprot_t pgprot_wc;
|
||||
#define ioremap_cache(offset, size) \
|
||||
ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
|
||||
|
||||
#define mmiowb() asm volatile ("dbar 0" ::: "memory")
|
||||
#define mmiowb() wmb()
|
||||
|
||||
/*
|
||||
* String version of I/O memory access operations.
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2023 Loongson Technology Corporation Limited
|
||||
*
|
||||
* Based on arch/arm64/include/asm/jump_label.h
|
||||
*/
|
||||
#ifndef __ASM_JUMP_LABEL_H
|
||||
#define __ASM_JUMP_LABEL_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define JUMP_LABEL_NOP_SIZE 4
|
||||
|
||||
#define JUMP_TABLE_ENTRY \
|
||||
".pushsection __jump_table, \"aw\" \n\t" \
|
||||
".align 3 \n\t" \
|
||||
".long 1b - ., %l[l_yes] - . \n\t" \
|
||||
".quad %0 - . \n\t" \
|
||||
".popsection \n\t"
|
||||
|
||||
static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
|
||||
{
|
||||
asm_volatile_goto(
|
||||
"1: nop \n\t"
|
||||
JUMP_TABLE_ENTRY
|
||||
: : "i"(&((char *)key)[branch]) : : l_yes);
|
||||
|
||||
return false;
|
||||
|
||||
l_yes:
|
||||
return true;
|
||||
}
|
||||
|
||||
static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
|
||||
{
|
||||
asm_volatile_goto(
|
||||
"1: b %l[l_yes] \n\t"
|
||||
JUMP_TABLE_ENTRY
|
||||
: : "i"(&((char *)key)[branch]) : : l_yes);
|
||||
|
||||
return false;
|
||||
|
||||
l_yes:
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASM_JUMP_LABEL_H */
|
||||
@@ -13,11 +13,6 @@ enum die_val {
|
||||
DIE_FP,
|
||||
DIE_SIMD,
|
||||
DIE_TRAP,
|
||||
DIE_PAGE_FAULT,
|
||||
DIE_BREAK,
|
||||
DIE_SSTEPBP,
|
||||
DIE_UPROBE,
|
||||
DIE_UPROBE_XOL,
|
||||
};
|
||||
|
||||
#endif /* _ASM_LOONGARCH_KDEBUG_H */
|
||||
|
||||
@@ -22,7 +22,7 @@ do { \
|
||||
|
||||
#define kretprobe_blacklist_size 0
|
||||
|
||||
typedef union loongarch_instruction kprobe_opcode_t;
|
||||
typedef u32 kprobe_opcode_t;
|
||||
|
||||
/* Architecture specific copy of original instruction */
|
||||
struct arch_specific_insn {
|
||||
@@ -49,9 +49,6 @@ bool kprobe_fault_handler(struct pt_regs *regs, int trapnr);
|
||||
bool kprobe_breakpoint_handler(struct pt_regs *regs);
|
||||
bool kprobe_singlestep_handler(struct pt_regs *regs);
|
||||
|
||||
void __kretprobe_trampoline(void);
|
||||
void *trampoline_probe_handler(struct pt_regs *regs);
|
||||
|
||||
#else /* !CONFIG_KPROBES */
|
||||
|
||||
static inline bool kprobe_breakpoint_handler(struct pt_regs *regs) { return false; }
|
||||
|
||||
@@ -56,10 +56,7 @@ __asm__(".macro parse_r var r\n\t"
|
||||
#undef _IFC_REG
|
||||
|
||||
/* CPUCFG */
|
||||
static inline u32 read_cpucfg(u32 reg)
|
||||
{
|
||||
return __cpucfg(reg);
|
||||
}
|
||||
#define read_cpucfg(reg) __cpucfg(reg)
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -138,6 +135,7 @@ static inline u32 read_cpucfg(u32 reg)
|
||||
#define CPUCFG2_MIPSBT BIT(20)
|
||||
#define CPUCFG2_LSPW BIT(21)
|
||||
#define CPUCFG2_LAM BIT(22)
|
||||
#define CPUCFG2_PTW BIT(24)
|
||||
|
||||
#define LOONGARCH_CPUCFG3 0x3
|
||||
#define CPUCFG3_CCDMA BIT(0)
|
||||
@@ -206,56 +204,18 @@ static inline u32 read_cpucfg(u32 reg)
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* CSR */
|
||||
static __always_inline u32 csr_read32(u32 reg)
|
||||
{
|
||||
return __csrrd_w(reg);
|
||||
}
|
||||
|
||||
static __always_inline u64 csr_read64(u32 reg)
|
||||
{
|
||||
return __csrrd_d(reg);
|
||||
}
|
||||
|
||||
static __always_inline void csr_write32(u32 val, u32 reg)
|
||||
{
|
||||
__csrwr_w(val, reg);
|
||||
}
|
||||
|
||||
static __always_inline void csr_write64(u64 val, u32 reg)
|
||||
{
|
||||
__csrwr_d(val, reg);
|
||||
}
|
||||
|
||||
static __always_inline u32 csr_xchg32(u32 val, u32 mask, u32 reg)
|
||||
{
|
||||
return __csrxchg_w(val, mask, reg);
|
||||
}
|
||||
|
||||
static __always_inline u64 csr_xchg64(u64 val, u64 mask, u32 reg)
|
||||
{
|
||||
return __csrxchg_d(val, mask, reg);
|
||||
}
|
||||
#define csr_read32(reg) __csrrd_w(reg)
|
||||
#define csr_read64(reg) __csrrd_d(reg)
|
||||
#define csr_write32(val, reg) __csrwr_w(val, reg)
|
||||
#define csr_write64(val, reg) __csrwr_d(val, reg)
|
||||
#define csr_xchg32(val, mask, reg) __csrxchg_w(val, mask, reg)
|
||||
#define csr_xchg64(val, mask, reg) __csrxchg_d(val, mask, reg)
|
||||
|
||||
/* IOCSR */
|
||||
static __always_inline u32 iocsr_read32(u32 reg)
|
||||
{
|
||||
return __iocsrrd_w(reg);
|
||||
}
|
||||
|
||||
static __always_inline u64 iocsr_read64(u32 reg)
|
||||
{
|
||||
return __iocsrrd_d(reg);
|
||||
}
|
||||
|
||||
static __always_inline void iocsr_write32(u32 val, u32 reg)
|
||||
{
|
||||
__iocsrwr_w(val, reg);
|
||||
}
|
||||
|
||||
static __always_inline void iocsr_write64(u64 val, u32 reg)
|
||||
{
|
||||
__iocsrwr_d(val, reg);
|
||||
}
|
||||
#define iocsr_read32(reg) __iocsrrd_w(reg)
|
||||
#define iocsr_read64(reg) __iocsrrd_d(reg)
|
||||
#define iocsr_write32(val, reg) __iocsrwr_w(val, reg)
|
||||
#define iocsr_write64(val, reg) __iocsrwr_d(val, reg)
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -453,6 +413,9 @@ static __always_inline void iocsr_write64(u64 val, u32 reg)
|
||||
#define CSR_PWCTL0_PTBASE (_ULCAST_(0x1f) << CSR_PWCTL0_PTBASE_SHIFT)
|
||||
|
||||
#define LOONGARCH_CSR_PWCTL1 0x1d /* PWCtl1 */
|
||||
#define CSR_PWCTL1_PTW_SHIFT 24
|
||||
#define CSR_PWCTL1_PTW_WIDTH 1
|
||||
#define CSR_PWCTL1_PTW (_ULCAST_(0x1) << CSR_PWCTL1_PTW_SHIFT)
|
||||
#define CSR_PWCTL1_DIR3WIDTH_SHIFT 18
|
||||
#define CSR_PWCTL1_DIR3WIDTH_WIDTH 5
|
||||
#define CSR_PWCTL1_DIR3WIDTH (_ULCAST_(0x1f) << CSR_PWCTL1_DIR3WIDTH_SHIFT)
|
||||
@@ -1441,11 +1404,18 @@ __BUILD_CSR_OP(tlbidx)
|
||||
#define EXCCODE_INT_START 64
|
||||
#define EXCCODE_INT_END (EXCCODE_INT_START + EXCCODE_INT_NUM - 1)
|
||||
|
||||
/* FPU register names */
|
||||
/* FPU Status Register Names */
|
||||
#ifndef CONFIG_AS_HAS_FCSR_CLASS
|
||||
#define LOONGARCH_FCSR0 $r0
|
||||
#define LOONGARCH_FCSR1 $r1
|
||||
#define LOONGARCH_FCSR2 $r2
|
||||
#define LOONGARCH_FCSR3 $r3
|
||||
#else
|
||||
#define LOONGARCH_FCSR0 $fcsr0
|
||||
#define LOONGARCH_FCSR1 $fcsr1
|
||||
#define LOONGARCH_FCSR2 $fcsr2
|
||||
#define LOONGARCH_FCSR3 $fcsr3
|
||||
#endif
|
||||
|
||||
/* FPU Status Register Values */
|
||||
#define FPU_CSR_RSVD 0xe0e0fce0
|
||||
|
||||
@@ -55,7 +55,7 @@ static inline struct plt_entry emit_plt_entry(unsigned long val)
|
||||
lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW));
|
||||
lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID));
|
||||
lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID));
|
||||
jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, 0, (val & 0xfff));
|
||||
jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, ADDR_IMM(val, ORI));
|
||||
|
||||
return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl };
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
|
||||
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
|
||||
|
||||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
|
||||
|
||||
#define virt_to_pfn(kaddr) PFN_DOWN(PHYSADDR(kaddr))
|
||||
#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
* loaded. Tell the compiler this fact when using explicit relocs.
|
||||
*/
|
||||
#if defined(MODULE) && defined(CONFIG_AS_HAS_EXPLICIT_RELOCS)
|
||||
#define PER_CPU_ATTRIBUTES __attribute__((model("extreme")))
|
||||
# if __has_attribute(model)
|
||||
# define PER_CPU_ATTRIBUTES __attribute__((model("extreme")))
|
||||
# else
|
||||
# error compiler support for the model attribute is necessary when a recent assembler is used
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Use r21 for fast access */
|
||||
|
||||
@@ -362,7 +362,7 @@ extern pgd_t invalid_pg_dir[];
|
||||
*/
|
||||
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
|
||||
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
|
||||
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
|
||||
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & (_PAGE_DIRTY | _PAGE_MODIFIED); }
|
||||
|
||||
static inline pte_t pte_mkold(pte_t pte)
|
||||
{
|
||||
@@ -506,7 +506,7 @@ static inline pmd_t pmd_wrprotect(pmd_t pmd)
|
||||
|
||||
static inline int pmd_dirty(pmd_t pmd)
|
||||
{
|
||||
return !!(pmd_val(pmd) & _PAGE_MODIFIED);
|
||||
return !!(pmd_val(pmd) & (_PAGE_DIRTY | _PAGE_MODIFIED));
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkclean(pmd_t pmd)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_QSPINLOCK_H
|
||||
#define _ASM_QSPINLOCK_H
|
||||
|
||||
#include <asm-generic/qspinlock_types.h>
|
||||
|
||||
#define queued_spin_unlock queued_spin_unlock
|
||||
|
||||
static inline void queued_spin_unlock(struct qspinlock *lock)
|
||||
{
|
||||
compiletime_assert_atomic_type(lock->locked);
|
||||
c_sync();
|
||||
WRITE_ONCE(lock->locked, 0);
|
||||
}
|
||||
|
||||
#include <asm-generic/qspinlock.h>
|
||||
|
||||
#endif /* _ASM_QSPINLOCK_H */
|
||||
@@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_SUSPEND_H
|
||||
#define __ASM_SUSPEND_H
|
||||
|
||||
void loongarch_common_suspend(void);
|
||||
void loongarch_common_resume(void);
|
||||
void loongarch_suspend_enter(void);
|
||||
void loongarch_wakeup_start(void);
|
||||
|
||||
#endif
|
||||
@@ -88,52 +88,47 @@ enum invtlb_ops {
|
||||
INVTLB_GID_ADDR = 0x16,
|
||||
};
|
||||
|
||||
/*
|
||||
* invtlb op info addr
|
||||
* (0x1 << 26) | (0x24 << 20) | (0x13 << 15) |
|
||||
* (addr << 10) | (info << 5) | op
|
||||
*/
|
||||
static inline void invtlb(u32 op, u32 info, u64 addr)
|
||||
static __always_inline void invtlb(u32 op, u32 info, u64 addr)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"parse_r addr,%0\n\t"
|
||||
"parse_r info,%1\n\t"
|
||||
".word ((0x6498000) | (addr << 10) | (info << 5) | %2)\n\t"
|
||||
:
|
||||
: "r"(addr), "r"(info), "i"(op)
|
||||
"invtlb %0, %1, %2\n\t"
|
||||
:
|
||||
: "i"(op), "r"(info), "r"(addr)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void invtlb_addr(u32 op, u32 info, u64 addr)
|
||||
static __always_inline void invtlb_addr(u32 op, u32 info, u64 addr)
|
||||
{
|
||||
BUILD_BUG_ON(!__builtin_constant_p(info) || info != 0);
|
||||
__asm__ __volatile__(
|
||||
"parse_r addr,%0\n\t"
|
||||
".word ((0x6498000) | (addr << 10) | (0 << 5) | %1)\n\t"
|
||||
:
|
||||
: "r"(addr), "i"(op)
|
||||
"invtlb %0, $zero, %1\n\t"
|
||||
:
|
||||
: "i"(op), "r"(addr)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void invtlb_info(u32 op, u32 info, u64 addr)
|
||||
static __always_inline void invtlb_info(u32 op, u32 info, u64 addr)
|
||||
{
|
||||
BUILD_BUG_ON(!__builtin_constant_p(addr) || addr != 0);
|
||||
__asm__ __volatile__(
|
||||
"parse_r info,%0\n\t"
|
||||
".word ((0x6498000) | (0 << 10) | (info << 5) | %1)\n\t"
|
||||
:
|
||||
: "r"(info), "i"(op)
|
||||
"invtlb %0, %1, $zero\n\t"
|
||||
:
|
||||
: "i"(op), "r"(info)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void invtlb_all(u32 op, u32 info, u64 addr)
|
||||
static __always_inline void invtlb_all(u32 op, u32 info, u64 addr)
|
||||
{
|
||||
BUILD_BUG_ON(!__builtin_constant_p(info) || info != 0);
|
||||
BUILD_BUG_ON(!__builtin_constant_p(addr) || addr != 0);
|
||||
__asm__ __volatile__(
|
||||
".word ((0x6498000) | (0 << 10) | (0 << 5) | %0)\n\t"
|
||||
"invtlb %0, $zero, $zero\n\t"
|
||||
:
|
||||
: "i"(op)
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -163,6 +158,9 @@ extern void handle_tlb_store(void);
|
||||
extern void handle_tlb_modify(void);
|
||||
extern void handle_tlb_refill(void);
|
||||
extern void handle_tlb_protect(void);
|
||||
extern void handle_tlb_load_ptw(void);
|
||||
extern void handle_tlb_store_ptw(void);
|
||||
extern void handle_tlb_modify_ptw(void);
|
||||
|
||||
extern void dump_tlb_all(void);
|
||||
extern void dump_tlb_regs(void);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __ASM_LOONGARCH_UPROBES_H
|
||||
#define __ASM_LOONGARCH_UPROBES_H
|
||||
|
||||
#include <asm/inst.h>
|
||||
|
||||
typedef u32 uprobe_opcode_t;
|
||||
|
||||
#define MAX_UINSN_BYTES 8
|
||||
#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES
|
||||
|
||||
#define UPROBE_SWBP_INSN larch_insn_gen_break(BRK_UPROBE_BP)
|
||||
#define UPROBE_SWBP_INSN_SIZE LOONGARCH_INSN_SIZE
|
||||
|
||||
#define UPROBE_XOLBP_INSN larch_insn_gen_break(BRK_UPROBE_XOLBP)
|
||||
|
||||
struct arch_uprobe {
|
||||
unsigned long resume_era;
|
||||
u32 insn[2];
|
||||
u32 ixol[2];
|
||||
bool simulate;
|
||||
};
|
||||
|
||||
struct arch_uprobe_task {
|
||||
unsigned long saved_trap_nr;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_UPROBES
|
||||
bool uprobe_breakpoint_handler(struct pt_regs *regs);
|
||||
bool uprobe_singlestep_handler(struct pt_regs *regs);
|
||||
#else /* !CONFIG_UPROBES */
|
||||
static inline bool uprobe_breakpoint_handler(struct pt_regs *regs) { return false; }
|
||||
static inline bool uprobe_singlestep_handler(struct pt_regs *regs) { return false; }
|
||||
#endif /* CONFIG_UPROBES */
|
||||
|
||||
#endif /* __ASM_LOONGARCH_UPROBES_H */
|
||||
@@ -91,9 +91,16 @@ static inline bool loongarch_vdso_hres_capable(void)
|
||||
|
||||
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
|
||||
{
|
||||
return get_vdso_data();
|
||||
return (const struct vdso_data *)get_vdso_data();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TIME_NS
|
||||
static __always_inline
|
||||
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
|
||||
{
|
||||
return (const struct vdso_data *)(get_vdso_data() + VVAR_TIMENS_PAGE_OFFSET * PAGE_SIZE);
|
||||
}
|
||||
#endif
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
|
||||
|
||||
@@ -16,10 +16,33 @@ struct vdso_pcpu_data {
|
||||
|
||||
struct loongarch_vdso_data {
|
||||
struct vdso_pcpu_data pdata[NR_CPUS];
|
||||
struct vdso_data data[CS_BASES]; /* Arch-independent data */
|
||||
};
|
||||
|
||||
#define VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data))
|
||||
/*
|
||||
* The layout of vvar:
|
||||
*
|
||||
* high
|
||||
* +---------------------+--------------------------+
|
||||
* | loongarch vdso data | LOONGARCH_VDSO_DATA_SIZE |
|
||||
* +---------------------+--------------------------+
|
||||
* | time-ns vdso data | PAGE_SIZE |
|
||||
* +---------------------+--------------------------+
|
||||
* | generic vdso data | PAGE_SIZE |
|
||||
* +---------------------+--------------------------+
|
||||
* low
|
||||
*/
|
||||
#define LOONGARCH_VDSO_DATA_SIZE PAGE_ALIGN(sizeof(struct loongarch_vdso_data))
|
||||
#define LOONGARCH_VDSO_DATA_PAGES (LOONGARCH_VDSO_DATA_SIZE >> PAGE_SHIFT)
|
||||
|
||||
enum vvar_pages {
|
||||
VVAR_GENERIC_PAGE_OFFSET,
|
||||
VVAR_TIMENS_PAGE_OFFSET,
|
||||
VVAR_LOONGARCH_PAGES_START,
|
||||
VVAR_LOONGARCH_PAGES_END = VVAR_LOONGARCH_PAGES_START + LOONGARCH_VDSO_DATA_PAGES - 1,
|
||||
VVAR_NR_PAGES,
|
||||
};
|
||||
|
||||
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
|
||||
|
||||
static inline unsigned long get_vdso_base(void)
|
||||
{
|
||||
@@ -34,10 +57,9 @@ static inline unsigned long get_vdso_base(void)
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline const struct vdso_data *get_vdso_data(void)
|
||||
static inline unsigned long get_vdso_data(void)
|
||||
{
|
||||
return (const struct vdso_data *)(get_vdso_base()
|
||||
- VDSO_DATA_SIZE + SMP_CACHE_BYTES * NR_CPUS);
|
||||
return get_vdso_base() - VVAR_SIZE;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
#define HWCAP_LOONGARCH_LBT_X86 (1 << 10)
|
||||
#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
|
||||
#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
|
||||
#define HWCAP_LOONGARCH_PTW (1 << 13)
|
||||
|
||||
#endif /* _UAPI_ASM_HWCAP_H */
|
||||
|
||||
@@ -41,9 +41,19 @@ struct user_pt_regs {
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct user_fp_state {
|
||||
uint64_t fpr[32];
|
||||
uint64_t fcc;
|
||||
uint32_t fcsr;
|
||||
uint64_t fpr[32];
|
||||
uint64_t fcc;
|
||||
uint32_t fcsr;
|
||||
};
|
||||
|
||||
struct user_lsx_state {
|
||||
/* 32 registers, 128 bits width per register. */
|
||||
uint64_t vregs[32*2];
|
||||
};
|
||||
|
||||
struct user_lasx_state {
|
||||
/* 32 registers, 256 bits width per register. */
|
||||
uint64_t vregs[32*4];
|
||||
};
|
||||
|
||||
struct user_watch_state {
|
||||
|
||||
@@ -41,4 +41,22 @@ struct fpu_context {
|
||||
__u32 fcsr;
|
||||
};
|
||||
|
||||
/* LSX context */
|
||||
#define LSX_CTX_MAGIC 0x53580001
|
||||
#define LSX_CTX_ALIGN 16
|
||||
struct lsx_context {
|
||||
__u64 regs[2*32];
|
||||
__u64 fcc;
|
||||
__u32 fcsr;
|
||||
};
|
||||
|
||||
/* LASX context */
|
||||
#define LASX_CTX_MAGIC 0x41535801
|
||||
#define LASX_CTX_ALIGN 32
|
||||
struct lasx_context {
|
||||
__u64 regs[4*32];
|
||||
__u64 fcc;
|
||||
__u32 fcsr;
|
||||
};
|
||||
|
||||
#endif /* _UAPI_ASM_SIGCONTEXT_H */
|
||||
|
||||
@@ -28,6 +28,8 @@ ifdef CONFIG_FUNCTION_TRACER
|
||||
CFLAGS_REMOVE_inst.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_time.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_perf_event.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE)
|
||||
CFLAGS_REMOVE_rethook_trampoline.o = $(CC_FLAGS_FTRACE)
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_MODULES) += module.o module-sections.o
|
||||
@@ -52,6 +54,10 @@ obj-$(CONFIG_UNWINDER_PROLOGUE) += unwind_prologue.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_regs.o
|
||||
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
|
||||
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o kprobes_trampoline.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||
obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o
|
||||
obj-$(CONFIG_UPROBES) += uprobes.o
|
||||
|
||||
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
|
||||
|
||||
CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
|
||||
|
||||
@@ -33,6 +33,8 @@ u64 acpi_saved_sp;
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
struct acpi_madt_core_pic acpi_core_pic[NR_CPUS];
|
||||
|
||||
void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size)
|
||||
{
|
||||
|
||||
@@ -99,6 +101,7 @@ acpi_parse_processor(union acpi_subtable_headers *header, const unsigned long en
|
||||
|
||||
acpi_table_print_madt_entry(&header->common);
|
||||
#ifdef CONFIG_SMP
|
||||
acpi_core_pic[processor->core_id] = *processor;
|
||||
set_processor_mask(processor->core_id, processor->flags);
|
||||
#endif
|
||||
|
||||
@@ -140,6 +143,35 @@ static void __init acpi_process_madt(void)
|
||||
loongson_sysconf.nr_cpus = num_processors;
|
||||
}
|
||||
|
||||
int pptt_enabled;
|
||||
|
||||
int __init parse_acpi_topology(void)
|
||||
{
|
||||
int cpu, topology_id;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
topology_id = find_acpi_cpu_topology(cpu, 0);
|
||||
if (topology_id < 0) {
|
||||
pr_warn("Invalid BIOS PPTT\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (acpi_pptt_cpu_is_thread(cpu) <= 0)
|
||||
cpu_data[cpu].core = topology_id;
|
||||
else {
|
||||
topology_id = find_acpi_cpu_topology(cpu, 1);
|
||||
if (topology_id < 0)
|
||||
return -ENOENT;
|
||||
|
||||
cpu_data[cpu].core = topology_id;
|
||||
}
|
||||
}
|
||||
|
||||
pptt_enabled = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SUSPEND
|
||||
int (*acpi_suspend_lowlevel)(void);
|
||||
#else
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <asm/cpu-info.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
void output_ptreg_defines(void)
|
||||
{
|
||||
@@ -264,7 +265,7 @@ void output_smpboot_defines(void)
|
||||
#ifdef CONFIG_HIBERNATION
|
||||
void output_pbe_defines(void)
|
||||
{
|
||||
COMMENT(" Linux struct pbe offsets. ");
|
||||
COMMENT("Linux struct pbe offsets.");
|
||||
OFFSET(PBE_ADDRESS, pbe, address);
|
||||
OFFSET(PBE_ORIG_ADDRESS, pbe, orig_address);
|
||||
OFFSET(PBE_NEXT, pbe, next);
|
||||
@@ -272,3 +273,15 @@ void output_pbe_defines(void)
|
||||
BLANK();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
void output_fgraph_ret_regs_defines(void)
|
||||
{
|
||||
COMMENT("LoongArch fgraph_ret_regs offsets.");
|
||||
OFFSET(FGRET_REGS_A0, fgraph_ret_regs, regs[0]);
|
||||
OFFSET(FGRET_REGS_A1, fgraph_ret_regs, regs[1]);
|
||||
OFFSET(FGRET_REGS_FP, fgraph_ret_regs, fp);
|
||||
DEFINE(FGRET_REGS_SIZE, sizeof(struct fgraph_ret_regs));
|
||||
BLANK();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -116,6 +116,18 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
|
||||
c->options |= LOONGARCH_CPU_FPU;
|
||||
elf_hwcap |= HWCAP_LOONGARCH_FPU;
|
||||
}
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
if (config & CPUCFG2_LSX) {
|
||||
c->options |= LOONGARCH_CPU_LSX;
|
||||
elf_hwcap |= HWCAP_LOONGARCH_LSX;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
if (config & CPUCFG2_LASX) {
|
||||
c->options |= LOONGARCH_CPU_LASX;
|
||||
elf_hwcap |= HWCAP_LOONGARCH_LASX;
|
||||
}
|
||||
#endif
|
||||
if (config & CPUCFG2_COMPLEX) {
|
||||
c->options |= LOONGARCH_CPU_COMPLEX;
|
||||
elf_hwcap |= HWCAP_LOONGARCH_COMPLEX;
|
||||
@@ -124,6 +136,10 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
|
||||
c->options |= LOONGARCH_CPU_CRYPTO;
|
||||
elf_hwcap |= HWCAP_LOONGARCH_CRYPTO;
|
||||
}
|
||||
if (config & CPUCFG2_PTW) {
|
||||
c->options |= LOONGARCH_CPU_PTW;
|
||||
elf_hwcap |= HWCAP_LOONGARCH_PTW;
|
||||
}
|
||||
if (config & CPUCFG2_LVZP) {
|
||||
c->options |= LOONGARCH_CPU_LVZ;
|
||||
elf_hwcap |= HWCAP_LOONGARCH_LVZ;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
.byte 0x02 /* MajorLinkerVersion */
|
||||
.byte 0x14 /* MinorLinkerVersion */
|
||||
.long __inittext_end - .Lefi_header_end /* SizeOfCode */
|
||||
.long _end - __initdata_begin /* SizeOfInitializedData */
|
||||
.long _kernel_vsize /* SizeOfInitializedData */
|
||||
.long 0 /* SizeOfUninitializedData */
|
||||
.long __efistub_efi_pe_entry - _head /* AddressOfEntryPoint */
|
||||
.long .Lefi_header_end - _head /* BaseOfCode */
|
||||
@@ -79,9 +79,9 @@
|
||||
IMAGE_SCN_MEM_EXECUTE /* Characteristics */
|
||||
|
||||
.ascii ".data\0\0\0"
|
||||
.long _end - __initdata_begin /* VirtualSize */
|
||||
.long _kernel_vsize /* VirtualSize */
|
||||
.long __initdata_begin - _head /* VirtualAddress */
|
||||
.long _edata - __initdata_begin /* SizeOfRawData */
|
||||
.long _kernel_rsize /* SizeOfRawData */
|
||||
.long __initdata_begin - _head /* PointerToRawData */
|
||||
|
||||
.long 0 /* PointerToRelocations */
|
||||
|
||||
@@ -145,6 +145,154 @@
|
||||
movgr2fcsr fcsr0, \tmp0
|
||||
.endm
|
||||
|
||||
.macro sc_save_lsx base
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
EX vst $vr0, \base, (0 * LSX_REG_WIDTH)
|
||||
EX vst $vr1, \base, (1 * LSX_REG_WIDTH)
|
||||
EX vst $vr2, \base, (2 * LSX_REG_WIDTH)
|
||||
EX vst $vr3, \base, (3 * LSX_REG_WIDTH)
|
||||
EX vst $vr4, \base, (4 * LSX_REG_WIDTH)
|
||||
EX vst $vr5, \base, (5 * LSX_REG_WIDTH)
|
||||
EX vst $vr6, \base, (6 * LSX_REG_WIDTH)
|
||||
EX vst $vr7, \base, (7 * LSX_REG_WIDTH)
|
||||
EX vst $vr8, \base, (8 * LSX_REG_WIDTH)
|
||||
EX vst $vr9, \base, (9 * LSX_REG_WIDTH)
|
||||
EX vst $vr10, \base, (10 * LSX_REG_WIDTH)
|
||||
EX vst $vr11, \base, (11 * LSX_REG_WIDTH)
|
||||
EX vst $vr12, \base, (12 * LSX_REG_WIDTH)
|
||||
EX vst $vr13, \base, (13 * LSX_REG_WIDTH)
|
||||
EX vst $vr14, \base, (14 * LSX_REG_WIDTH)
|
||||
EX vst $vr15, \base, (15 * LSX_REG_WIDTH)
|
||||
EX vst $vr16, \base, (16 * LSX_REG_WIDTH)
|
||||
EX vst $vr17, \base, (17 * LSX_REG_WIDTH)
|
||||
EX vst $vr18, \base, (18 * LSX_REG_WIDTH)
|
||||
EX vst $vr19, \base, (19 * LSX_REG_WIDTH)
|
||||
EX vst $vr20, \base, (20 * LSX_REG_WIDTH)
|
||||
EX vst $vr21, \base, (21 * LSX_REG_WIDTH)
|
||||
EX vst $vr22, \base, (22 * LSX_REG_WIDTH)
|
||||
EX vst $vr23, \base, (23 * LSX_REG_WIDTH)
|
||||
EX vst $vr24, \base, (24 * LSX_REG_WIDTH)
|
||||
EX vst $vr25, \base, (25 * LSX_REG_WIDTH)
|
||||
EX vst $vr26, \base, (26 * LSX_REG_WIDTH)
|
||||
EX vst $vr27, \base, (27 * LSX_REG_WIDTH)
|
||||
EX vst $vr28, \base, (28 * LSX_REG_WIDTH)
|
||||
EX vst $vr29, \base, (29 * LSX_REG_WIDTH)
|
||||
EX vst $vr30, \base, (30 * LSX_REG_WIDTH)
|
||||
EX vst $vr31, \base, (31 * LSX_REG_WIDTH)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro sc_restore_lsx base
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
EX vld $vr0, \base, (0 * LSX_REG_WIDTH)
|
||||
EX vld $vr1, \base, (1 * LSX_REG_WIDTH)
|
||||
EX vld $vr2, \base, (2 * LSX_REG_WIDTH)
|
||||
EX vld $vr3, \base, (3 * LSX_REG_WIDTH)
|
||||
EX vld $vr4, \base, (4 * LSX_REG_WIDTH)
|
||||
EX vld $vr5, \base, (5 * LSX_REG_WIDTH)
|
||||
EX vld $vr6, \base, (6 * LSX_REG_WIDTH)
|
||||
EX vld $vr7, \base, (7 * LSX_REG_WIDTH)
|
||||
EX vld $vr8, \base, (8 * LSX_REG_WIDTH)
|
||||
EX vld $vr9, \base, (9 * LSX_REG_WIDTH)
|
||||
EX vld $vr10, \base, (10 * LSX_REG_WIDTH)
|
||||
EX vld $vr11, \base, (11 * LSX_REG_WIDTH)
|
||||
EX vld $vr12, \base, (12 * LSX_REG_WIDTH)
|
||||
EX vld $vr13, \base, (13 * LSX_REG_WIDTH)
|
||||
EX vld $vr14, \base, (14 * LSX_REG_WIDTH)
|
||||
EX vld $vr15, \base, (15 * LSX_REG_WIDTH)
|
||||
EX vld $vr16, \base, (16 * LSX_REG_WIDTH)
|
||||
EX vld $vr17, \base, (17 * LSX_REG_WIDTH)
|
||||
EX vld $vr18, \base, (18 * LSX_REG_WIDTH)
|
||||
EX vld $vr19, \base, (19 * LSX_REG_WIDTH)
|
||||
EX vld $vr20, \base, (20 * LSX_REG_WIDTH)
|
||||
EX vld $vr21, \base, (21 * LSX_REG_WIDTH)
|
||||
EX vld $vr22, \base, (22 * LSX_REG_WIDTH)
|
||||
EX vld $vr23, \base, (23 * LSX_REG_WIDTH)
|
||||
EX vld $vr24, \base, (24 * LSX_REG_WIDTH)
|
||||
EX vld $vr25, \base, (25 * LSX_REG_WIDTH)
|
||||
EX vld $vr26, \base, (26 * LSX_REG_WIDTH)
|
||||
EX vld $vr27, \base, (27 * LSX_REG_WIDTH)
|
||||
EX vld $vr28, \base, (28 * LSX_REG_WIDTH)
|
||||
EX vld $vr29, \base, (29 * LSX_REG_WIDTH)
|
||||
EX vld $vr30, \base, (30 * LSX_REG_WIDTH)
|
||||
EX vld $vr31, \base, (31 * LSX_REG_WIDTH)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro sc_save_lasx base
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
EX xvst $xr0, \base, (0 * LASX_REG_WIDTH)
|
||||
EX xvst $xr1, \base, (1 * LASX_REG_WIDTH)
|
||||
EX xvst $xr2, \base, (2 * LASX_REG_WIDTH)
|
||||
EX xvst $xr3, \base, (3 * LASX_REG_WIDTH)
|
||||
EX xvst $xr4, \base, (4 * LASX_REG_WIDTH)
|
||||
EX xvst $xr5, \base, (5 * LASX_REG_WIDTH)
|
||||
EX xvst $xr6, \base, (6 * LASX_REG_WIDTH)
|
||||
EX xvst $xr7, \base, (7 * LASX_REG_WIDTH)
|
||||
EX xvst $xr8, \base, (8 * LASX_REG_WIDTH)
|
||||
EX xvst $xr9, \base, (9 * LASX_REG_WIDTH)
|
||||
EX xvst $xr10, \base, (10 * LASX_REG_WIDTH)
|
||||
EX xvst $xr11, \base, (11 * LASX_REG_WIDTH)
|
||||
EX xvst $xr12, \base, (12 * LASX_REG_WIDTH)
|
||||
EX xvst $xr13, \base, (13 * LASX_REG_WIDTH)
|
||||
EX xvst $xr14, \base, (14 * LASX_REG_WIDTH)
|
||||
EX xvst $xr15, \base, (15 * LASX_REG_WIDTH)
|
||||
EX xvst $xr16, \base, (16 * LASX_REG_WIDTH)
|
||||
EX xvst $xr17, \base, (17 * LASX_REG_WIDTH)
|
||||
EX xvst $xr18, \base, (18 * LASX_REG_WIDTH)
|
||||
EX xvst $xr19, \base, (19 * LASX_REG_WIDTH)
|
||||
EX xvst $xr20, \base, (20 * LASX_REG_WIDTH)
|
||||
EX xvst $xr21, \base, (21 * LASX_REG_WIDTH)
|
||||
EX xvst $xr22, \base, (22 * LASX_REG_WIDTH)
|
||||
EX xvst $xr23, \base, (23 * LASX_REG_WIDTH)
|
||||
EX xvst $xr24, \base, (24 * LASX_REG_WIDTH)
|
||||
EX xvst $xr25, \base, (25 * LASX_REG_WIDTH)
|
||||
EX xvst $xr26, \base, (26 * LASX_REG_WIDTH)
|
||||
EX xvst $xr27, \base, (27 * LASX_REG_WIDTH)
|
||||
EX xvst $xr28, \base, (28 * LASX_REG_WIDTH)
|
||||
EX xvst $xr29, \base, (29 * LASX_REG_WIDTH)
|
||||
EX xvst $xr30, \base, (30 * LASX_REG_WIDTH)
|
||||
EX xvst $xr31, \base, (31 * LASX_REG_WIDTH)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro sc_restore_lasx base
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
EX xvld $xr0, \base, (0 * LASX_REG_WIDTH)
|
||||
EX xvld $xr1, \base, (1 * LASX_REG_WIDTH)
|
||||
EX xvld $xr2, \base, (2 * LASX_REG_WIDTH)
|
||||
EX xvld $xr3, \base, (3 * LASX_REG_WIDTH)
|
||||
EX xvld $xr4, \base, (4 * LASX_REG_WIDTH)
|
||||
EX xvld $xr5, \base, (5 * LASX_REG_WIDTH)
|
||||
EX xvld $xr6, \base, (6 * LASX_REG_WIDTH)
|
||||
EX xvld $xr7, \base, (7 * LASX_REG_WIDTH)
|
||||
EX xvld $xr8, \base, (8 * LASX_REG_WIDTH)
|
||||
EX xvld $xr9, \base, (9 * LASX_REG_WIDTH)
|
||||
EX xvld $xr10, \base, (10 * LASX_REG_WIDTH)
|
||||
EX xvld $xr11, \base, (11 * LASX_REG_WIDTH)
|
||||
EX xvld $xr12, \base, (12 * LASX_REG_WIDTH)
|
||||
EX xvld $xr13, \base, (13 * LASX_REG_WIDTH)
|
||||
EX xvld $xr14, \base, (14 * LASX_REG_WIDTH)
|
||||
EX xvld $xr15, \base, (15 * LASX_REG_WIDTH)
|
||||
EX xvld $xr16, \base, (16 * LASX_REG_WIDTH)
|
||||
EX xvld $xr17, \base, (17 * LASX_REG_WIDTH)
|
||||
EX xvld $xr18, \base, (18 * LASX_REG_WIDTH)
|
||||
EX xvld $xr19, \base, (19 * LASX_REG_WIDTH)
|
||||
EX xvld $xr20, \base, (20 * LASX_REG_WIDTH)
|
||||
EX xvld $xr21, \base, (21 * LASX_REG_WIDTH)
|
||||
EX xvld $xr22, \base, (22 * LASX_REG_WIDTH)
|
||||
EX xvld $xr23, \base, (23 * LASX_REG_WIDTH)
|
||||
EX xvld $xr24, \base, (24 * LASX_REG_WIDTH)
|
||||
EX xvld $xr25, \base, (25 * LASX_REG_WIDTH)
|
||||
EX xvld $xr26, \base, (26 * LASX_REG_WIDTH)
|
||||
EX xvld $xr27, \base, (27 * LASX_REG_WIDTH)
|
||||
EX xvld $xr28, \base, (28 * LASX_REG_WIDTH)
|
||||
EX xvld $xr29, \base, (29 * LASX_REG_WIDTH)
|
||||
EX xvld $xr30, \base, (30 * LASX_REG_WIDTH)
|
||||
EX xvld $xr31, \base, (31 * LASX_REG_WIDTH)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Save a thread's fp context.
|
||||
*/
|
||||
@@ -166,6 +314,76 @@ SYM_FUNC_START(_restore_fp)
|
||||
jr ra
|
||||
SYM_FUNC_END(_restore_fp)
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
|
||||
/*
|
||||
* Save a thread's LSX vector context.
|
||||
*/
|
||||
SYM_FUNC_START(_save_lsx)
|
||||
lsx_save_all a0 t1 t2
|
||||
jr ra
|
||||
SYM_FUNC_END(_save_lsx)
|
||||
EXPORT_SYMBOL(_save_lsx)
|
||||
|
||||
/*
|
||||
* Restore a thread's LSX vector context.
|
||||
*/
|
||||
SYM_FUNC_START(_restore_lsx)
|
||||
lsx_restore_all a0 t1 t2
|
||||
jr ra
|
||||
SYM_FUNC_END(_restore_lsx)
|
||||
|
||||
SYM_FUNC_START(_save_lsx_upper)
|
||||
lsx_save_all_upper a0 t0 t1
|
||||
jr ra
|
||||
SYM_FUNC_END(_save_lsx_upper)
|
||||
|
||||
SYM_FUNC_START(_restore_lsx_upper)
|
||||
lsx_restore_all_upper a0 t0 t1
|
||||
jr ra
|
||||
SYM_FUNC_END(_restore_lsx_upper)
|
||||
|
||||
SYM_FUNC_START(_init_lsx_upper)
|
||||
lsx_init_all_upper t1
|
||||
jr ra
|
||||
SYM_FUNC_END(_init_lsx_upper)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
|
||||
/*
|
||||
* Save a thread's LASX vector context.
|
||||
*/
|
||||
SYM_FUNC_START(_save_lasx)
|
||||
lasx_save_all a0 t1 t2
|
||||
jr ra
|
||||
SYM_FUNC_END(_save_lasx)
|
||||
EXPORT_SYMBOL(_save_lasx)
|
||||
|
||||
/*
|
||||
* Restore a thread's LASX vector context.
|
||||
*/
|
||||
SYM_FUNC_START(_restore_lasx)
|
||||
lasx_restore_all a0 t1 t2
|
||||
jr ra
|
||||
SYM_FUNC_END(_restore_lasx)
|
||||
|
||||
SYM_FUNC_START(_save_lasx_upper)
|
||||
lasx_save_all_upper a0 t0 t1
|
||||
jr ra
|
||||
SYM_FUNC_END(_save_lasx_upper)
|
||||
|
||||
SYM_FUNC_START(_restore_lasx_upper)
|
||||
lasx_restore_all_upper a0 t0 t1
|
||||
jr ra
|
||||
SYM_FUNC_END(_restore_lasx_upper)
|
||||
|
||||
SYM_FUNC_START(_init_lasx_upper)
|
||||
lasx_init_all_upper t1
|
||||
jr ra
|
||||
SYM_FUNC_END(_init_lasx_upper)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Load the FPU with signalling NANS. This bit pattern we're using has
|
||||
* the property that no matter whether considered as single or as double
|
||||
@@ -244,6 +462,58 @@ SYM_FUNC_START(_restore_fp_context)
|
||||
jr ra
|
||||
SYM_FUNC_END(_restore_fp_context)
|
||||
|
||||
/*
|
||||
* a0: fpregs
|
||||
* a1: fcc
|
||||
* a2: fcsr
|
||||
*/
|
||||
SYM_FUNC_START(_save_lsx_context)
|
||||
sc_save_fcc a1, t0, t1
|
||||
sc_save_fcsr a2, t0
|
||||
sc_save_lsx a0
|
||||
li.w a0, 0 # success
|
||||
jr ra
|
||||
SYM_FUNC_END(_save_lsx_context)
|
||||
|
||||
/*
|
||||
* a0: fpregs
|
||||
* a1: fcc
|
||||
* a2: fcsr
|
||||
*/
|
||||
SYM_FUNC_START(_restore_lsx_context)
|
||||
sc_restore_lsx a0
|
||||
sc_restore_fcc a1, t1, t2
|
||||
sc_restore_fcsr a2, t1
|
||||
li.w a0, 0 # success
|
||||
jr ra
|
||||
SYM_FUNC_END(_restore_lsx_context)
|
||||
|
||||
/*
|
||||
* a0: fpregs
|
||||
* a1: fcc
|
||||
* a2: fcsr
|
||||
*/
|
||||
SYM_FUNC_START(_save_lasx_context)
|
||||
sc_save_fcc a1, t0, t1
|
||||
sc_save_fcsr a2, t0
|
||||
sc_save_lasx a0
|
||||
li.w a0, 0 # success
|
||||
jr ra
|
||||
SYM_FUNC_END(_save_lasx_context)
|
||||
|
||||
/*
|
||||
* a0: fpregs
|
||||
* a1: fcc
|
||||
* a2: fcsr
|
||||
*/
|
||||
SYM_FUNC_START(_restore_lasx_context)
|
||||
sc_restore_lasx a0
|
||||
sc_restore_fcc a1, t1, t2
|
||||
sc_restore_fcsr a2, t1
|
||||
li.w a0, 0 # success
|
||||
jr ra
|
||||
SYM_FUNC_END(_restore_lasx_context)
|
||||
|
||||
SYM_FUNC_START(fault)
|
||||
li.w a0, -EFAULT # failure
|
||||
jr ra
|
||||
|
||||
@@ -23,7 +23,7 @@ _head:
|
||||
.word MZ_MAGIC /* "MZ", MS-DOS header */
|
||||
.org 0x8
|
||||
.dword kernel_entry /* Kernel entry point */
|
||||
.dword _end - _text /* Kernel image effective size */
|
||||
.dword _kernel_asize /* Kernel image effective size */
|
||||
.quad PHYS_LINK_KADDR /* Kernel image load offset from start of RAM */
|
||||
.org 0x38 /* 0x20 ~ 0x37 reserved */
|
||||
.long LINUX_PE_MAGIC
|
||||
@@ -32,9 +32,9 @@ _head:
|
||||
pe_header:
|
||||
__EFI_PE_HEADER
|
||||
|
||||
SYM_DATA(kernel_asize, .long _end - _text);
|
||||
SYM_DATA(kernel_fsize, .long _edata - _text);
|
||||
SYM_DATA(kernel_offset, .long kernel_offset - _text);
|
||||
SYM_DATA(kernel_asize, .long _kernel_asize);
|
||||
SYM_DATA(kernel_fsize, .long _kernel_fsize);
|
||||
SYM_DATA(kernel_offset, .long _kernel_offset);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -133,6 +133,51 @@ void simu_branch(struct pt_regs *regs, union loongarch_instruction insn)
|
||||
}
|
||||
}
|
||||
|
||||
bool insns_not_supported(union loongarch_instruction insn)
|
||||
{
|
||||
switch (insn.reg3_format.opcode) {
|
||||
case amswapw_op ... ammindbdu_op:
|
||||
pr_notice("atomic memory access instructions are not supported\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (insn.reg2i14_format.opcode) {
|
||||
case llw_op:
|
||||
case lld_op:
|
||||
case scw_op:
|
||||
case scd_op:
|
||||
pr_notice("ll and sc instructions are not supported\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (insn.reg1i21_format.opcode) {
|
||||
case bceqz_op:
|
||||
pr_notice("bceqz and bcnez instructions are not supported\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool insns_need_simulation(union loongarch_instruction insn)
|
||||
{
|
||||
if (is_pc_ins(&insn))
|
||||
return true;
|
||||
|
||||
if (is_branch_ins(&insn))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void arch_simulate_insn(union loongarch_instruction insn, struct pt_regs *regs)
|
||||
{
|
||||
if (is_pc_ins(&insn))
|
||||
simu_pc(regs, insn);
|
||||
else if (is_branch_ins(&insn))
|
||||
simu_branch(regs, insn);
|
||||
}
|
||||
|
||||
int larch_insn_read(void *addr, u32 *insnp)
|
||||
{
|
||||
int ret;
|
||||
@@ -208,6 +253,20 @@ u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest)
|
||||
return insn.word;
|
||||
}
|
||||
|
||||
u32 larch_insn_gen_break(int imm)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
|
||||
if (imm < 0 || imm >= SZ_32K) {
|
||||
pr_warn("The generated break instruction is out of range.\n");
|
||||
return INSN_BREAK;
|
||||
}
|
||||
|
||||
emit_break(&insn, imm);
|
||||
|
||||
return insn.word;
|
||||
}
|
||||
|
||||
u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
@@ -226,6 +285,11 @@ u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
|
||||
if (imm < -SZ_512K || imm >= SZ_512K) {
|
||||
pr_warn("The generated lu12i.w instruction is out of range.\n");
|
||||
return INSN_BREAK;
|
||||
}
|
||||
|
||||
emit_lu12iw(&insn, rd, imm);
|
||||
|
||||
return insn.word;
|
||||
@@ -235,6 +299,11 @@ u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
|
||||
if (imm < -SZ_512K || imm >= SZ_512K) {
|
||||
pr_warn("The generated lu32i.d instruction is out of range.\n");
|
||||
return INSN_BREAK;
|
||||
}
|
||||
|
||||
emit_lu32id(&insn, rd, imm);
|
||||
|
||||
return insn.word;
|
||||
@@ -244,16 +313,26 @@ u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
|
||||
if (imm < -SZ_2K || imm >= SZ_2K) {
|
||||
pr_warn("The generated lu52i.d instruction is out of range.\n");
|
||||
return INSN_BREAK;
|
||||
}
|
||||
|
||||
emit_lu52id(&insn, rd, rj, imm);
|
||||
|
||||
return insn.word;
|
||||
}
|
||||
|
||||
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest)
|
||||
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
|
||||
emit_jirl(&insn, rj, rd, (dest - pc) >> 2);
|
||||
if ((imm & 3) || imm < -SZ_128K || imm >= SZ_128K) {
|
||||
pr_warn("The generated jirl instruction is out of range.\n");
|
||||
return INSN_BREAK;
|
||||
}
|
||||
|
||||
emit_jirl(&insn, rj, rd, imm >> 2);
|
||||
|
||||
return insn.word;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2023 Loongson Technology Corporation Limited
|
||||
*
|
||||
* Based on arch/arm64/kernel/jump_label.c
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/jump_label.h>
|
||||
#include <asm/inst.h>
|
||||
|
||||
void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type)
|
||||
{
|
||||
u32 insn;
|
||||
void *addr = (void *)jump_entry_code(entry);
|
||||
|
||||
if (type == JUMP_LABEL_JMP)
|
||||
insn = larch_insn_gen_b(jump_entry_code(entry), jump_entry_target(entry));
|
||||
else
|
||||
insn = larch_insn_gen_nop();
|
||||
|
||||
larch_insn_patch_text(addr, insn);
|
||||
}
|
||||
@@ -4,69 +4,16 @@
|
||||
#include <linux/preempt.h>
|
||||
#include <asm/break.h>
|
||||
|
||||
static const union loongarch_instruction breakpoint_insn = {
|
||||
.reg0i15_format = {
|
||||
.opcode = break_op,
|
||||
.immediate = BRK_KPROBE_BP,
|
||||
}
|
||||
};
|
||||
|
||||
static const union loongarch_instruction singlestep_insn = {
|
||||
.reg0i15_format = {
|
||||
.opcode = break_op,
|
||||
.immediate = BRK_KPROBE_SSTEPBP,
|
||||
}
|
||||
};
|
||||
#define KPROBE_BP_INSN larch_insn_gen_break(BRK_KPROBE_BP)
|
||||
#define KPROBE_SSTEPBP_INSN larch_insn_gen_break(BRK_KPROBE_SSTEPBP)
|
||||
|
||||
DEFINE_PER_CPU(struct kprobe *, current_kprobe);
|
||||
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
|
||||
|
||||
static bool insns_not_supported(union loongarch_instruction insn)
|
||||
{
|
||||
switch (insn.reg2i14_format.opcode) {
|
||||
case llw_op:
|
||||
case lld_op:
|
||||
case scw_op:
|
||||
case scd_op:
|
||||
pr_notice("kprobe: ll and sc instructions are not supported\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (insn.reg1i21_format.opcode) {
|
||||
case bceqz_op:
|
||||
pr_notice("kprobe: bceqz and bcnez instructions are not supported\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
NOKPROBE_SYMBOL(insns_not_supported);
|
||||
|
||||
static bool insns_need_simulation(struct kprobe *p)
|
||||
{
|
||||
if (is_pc_ins(&p->opcode))
|
||||
return true;
|
||||
|
||||
if (is_branch_ins(&p->opcode))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
NOKPROBE_SYMBOL(insns_need_simulation);
|
||||
|
||||
static void arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)
|
||||
{
|
||||
if (is_pc_ins(&p->opcode))
|
||||
simu_pc(regs, p->opcode);
|
||||
else if (is_branch_ins(&p->opcode))
|
||||
simu_branch(regs, p->opcode);
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_simulate_insn);
|
||||
|
||||
static void arch_prepare_ss_slot(struct kprobe *p)
|
||||
{
|
||||
p->ainsn.insn[0] = *p->addr;
|
||||
p->ainsn.insn[1] = singlestep_insn;
|
||||
p->ainsn.insn[1] = KPROBE_SSTEPBP_INSN;
|
||||
p->ainsn.restore = (unsigned long)p->addr + LOONGARCH_INSN_SIZE;
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_prepare_ss_slot);
|
||||
@@ -79,17 +26,20 @@ NOKPROBE_SYMBOL(arch_prepare_simulate);
|
||||
|
||||
int arch_prepare_kprobe(struct kprobe *p)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
|
||||
if ((unsigned long)p->addr & 0x3)
|
||||
return -EILSEQ;
|
||||
|
||||
/* copy instruction */
|
||||
p->opcode = *p->addr;
|
||||
insn.word = p->opcode;
|
||||
|
||||
/* decode instruction */
|
||||
if (insns_not_supported(p->opcode))
|
||||
if (insns_not_supported(insn))
|
||||
return -EINVAL;
|
||||
|
||||
if (insns_need_simulation(p)) {
|
||||
if (insns_need_simulation(insn)) {
|
||||
p->ainsn.insn = NULL;
|
||||
} else {
|
||||
p->ainsn.insn = get_insn_slot();
|
||||
@@ -110,7 +60,7 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
|
||||
/* Install breakpoint in text */
|
||||
void arch_arm_kprobe(struct kprobe *p)
|
||||
{
|
||||
*p->addr = breakpoint_insn;
|
||||
*p->addr = KPROBE_BP_INSN;
|
||||
flush_insn_slot(p);
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_arm_kprobe);
|
||||
@@ -205,6 +155,8 @@ NOKPROBE_SYMBOL(post_kprobe_handler);
|
||||
static void setup_singlestep(struct kprobe *p, struct pt_regs *regs,
|
||||
struct kprobe_ctlblk *kcb, int reenter)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
|
||||
if (reenter) {
|
||||
save_previous_kprobe(kcb);
|
||||
set_current_kprobe(p);
|
||||
@@ -220,7 +172,8 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs,
|
||||
regs->csr_era = (unsigned long)p->ainsn.insn;
|
||||
} else {
|
||||
/* simulate single steping */
|
||||
arch_simulate_insn(p, regs);
|
||||
insn.word = p->opcode;
|
||||
arch_simulate_insn(insn, regs);
|
||||
/* now go for post processing */
|
||||
post_kprobe_handler(p, kcb, regs);
|
||||
}
|
||||
@@ -295,7 +248,7 @@ bool kprobe_breakpoint_handler(struct pt_regs *regs)
|
||||
}
|
||||
}
|
||||
|
||||
if (addr->word != breakpoint_insn.word) {
|
||||
if (*addr != KPROBE_BP_INSN) {
|
||||
/*
|
||||
* The breakpoint instruction was removed right
|
||||
* after we hit it. Another cpu has removed
|
||||
@@ -378,27 +331,6 @@ int __init arch_init_kprobes(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ASM function that handles the kretprobes must not be probed */
|
||||
NOKPROBE_SYMBOL(__kretprobe_trampoline);
|
||||
|
||||
/* Called from __kretprobe_trampoline */
|
||||
void __used *trampoline_probe_handler(struct pt_regs *regs)
|
||||
{
|
||||
return (void *)kretprobe_trampoline_handler(regs, NULL);
|
||||
}
|
||||
NOKPROBE_SYMBOL(trampoline_probe_handler);
|
||||
|
||||
void arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
ri->ret_addr = (kprobe_opcode_t *)regs->regs[1];
|
||||
ri->fp = NULL;
|
||||
|
||||
/* Replace the return addr with trampoline addr */
|
||||
regs->regs[1] = (unsigned long)&__kretprobe_trampoline;
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_prepare_kretprobe);
|
||||
|
||||
int arch_trampoline_kprobe(struct kprobe *p)
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -79,18 +79,20 @@ SYM_FUNC_START(ftrace_graph_caller)
|
||||
SYM_FUNC_END(ftrace_graph_caller)
|
||||
|
||||
SYM_FUNC_START(return_to_handler)
|
||||
PTR_ADDI sp, sp, -2 * SZREG
|
||||
PTR_S a0, sp, 0
|
||||
PTR_S a1, sp, SZREG
|
||||
PTR_ADDI sp, sp, -FGRET_REGS_SIZE
|
||||
PTR_S a0, sp, FGRET_REGS_A0
|
||||
PTR_S a1, sp, FGRET_REGS_A1
|
||||
PTR_S zero, sp, FGRET_REGS_FP
|
||||
|
||||
move a0, sp
|
||||
bl ftrace_return_to_handler
|
||||
|
||||
/* Restore the real parent address: a0 -> ra */
|
||||
move ra, a0
|
||||
|
||||
PTR_L a0, sp, 0
|
||||
PTR_L a1, sp, SZREG
|
||||
PTR_ADDI sp, sp, 2 * SZREG
|
||||
PTR_L a0, sp, FGRET_REGS_A0
|
||||
PTR_L a1, sp, FGRET_REGS_A1
|
||||
PTR_ADDI sp, sp, FGRET_REGS_SIZE
|
||||
jr ra
|
||||
SYM_FUNC_END(return_to_handler)
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
||||
@@ -136,18 +136,19 @@ SYM_CODE_END(ftrace_graph_caller)
|
||||
|
||||
SYM_CODE_START(return_to_handler)
|
||||
/* Save return value regs */
|
||||
PTR_ADDI sp, sp, -2 * SZREG
|
||||
PTR_S a0, sp, 0
|
||||
PTR_S a1, sp, SZREG
|
||||
PTR_ADDI sp, sp, -FGRET_REGS_SIZE
|
||||
PTR_S a0, sp, FGRET_REGS_A0
|
||||
PTR_S a1, sp, FGRET_REGS_A1
|
||||
PTR_S zero, sp, FGRET_REGS_FP
|
||||
|
||||
move a0, zero
|
||||
move a0, sp
|
||||
bl ftrace_return_to_handler
|
||||
move ra, a0
|
||||
|
||||
/* Restore return value regs */
|
||||
PTR_L a0, sp, 0
|
||||
PTR_L a1, sp, SZREG
|
||||
PTR_ADDI sp, sp, 2 * SZREG
|
||||
PTR_L a0, sp, FGRET_REGS_A0
|
||||
PTR_L a1, sp, FGRET_REGS_A1
|
||||
PTR_ADDI sp, sp, FGRET_REGS_SIZE
|
||||
|
||||
jr ra
|
||||
SYM_CODE_END(return_to_handler)
|
||||
|
||||
@@ -49,6 +49,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
seq_printf(m, "processor\t\t: %ld\n", n);
|
||||
seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package);
|
||||
seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
|
||||
seq_printf(m, "global_id\t\t: %d\n", cpu_data[n].global_id);
|
||||
seq_printf(m, "CPU Family\t\t: %s\n", __cpu_family[n]);
|
||||
seq_printf(m, "Model Name\t\t: %s\n", __cpu_full_name[n]);
|
||||
seq_printf(m, "CPU Revision\t\t: 0x%02x\n", version);
|
||||
@@ -79,6 +80,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
if (cpu_has_crc32) seq_printf(m, " crc32");
|
||||
if (cpu_has_complex) seq_printf(m, " complex");
|
||||
if (cpu_has_crypto) seq_printf(m, " crypto");
|
||||
if (cpu_has_ptw) seq_printf(m, " ptw");
|
||||
if (cpu_has_lvz) seq_printf(m, " lvz");
|
||||
if (cpu_has_lbt_x86) seq_printf(m, " lbt_x86");
|
||||
if (cpu_has_lbt_arm) seq_printf(m, " lbt_arm");
|
||||
|
||||
@@ -117,8 +117,14 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
|
||||
*/
|
||||
preempt_disable();
|
||||
|
||||
if (is_fpu_owner())
|
||||
save_fp(current);
|
||||
if (is_fpu_owner()) {
|
||||
if (is_lasx_enabled())
|
||||
save_lasx(current);
|
||||
else if (is_lsx_enabled())
|
||||
save_lsx(current);
|
||||
else
|
||||
save_fp(current);
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
|
||||
@@ -285,7 +291,7 @@ unsigned long stack_top(void)
|
||||
|
||||
/* Space for the VDSO & data page */
|
||||
top -= PAGE_ALIGN(current->thread.vdso->size);
|
||||
top -= PAGE_SIZE;
|
||||
top -= VVAR_SIZE;
|
||||
|
||||
/* Space to randomize the VDSO base */
|
||||
if (current->flags & PF_RANDOMIZE)
|
||||
|
||||
@@ -250,6 +250,90 @@ static int cfg_set(struct task_struct *target,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
|
||||
static void copy_pad_fprs(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
struct membuf *to, unsigned int live_sz)
|
||||
{
|
||||
int i, j;
|
||||
unsigned long long fill = ~0ull;
|
||||
unsigned int cp_sz, pad_sz;
|
||||
|
||||
cp_sz = min(regset->size, live_sz);
|
||||
pad_sz = regset->size - cp_sz;
|
||||
WARN_ON(pad_sz % sizeof(fill));
|
||||
|
||||
for (i = 0; i < NUM_FPU_REGS; i++) {
|
||||
membuf_write(to, &target->thread.fpu.fpr[i], cp_sz);
|
||||
for (j = 0; j < (pad_sz / sizeof(fill)); j++) {
|
||||
membuf_store(to, fill);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int simd_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
struct membuf to)
|
||||
{
|
||||
const unsigned int wr_size = NUM_FPU_REGS * regset->size;
|
||||
|
||||
if (!tsk_used_math(target)) {
|
||||
/* The task hasn't used FP or LSX, fill with 0xff */
|
||||
copy_pad_fprs(target, regset, &to, 0);
|
||||
} else if (!test_tsk_thread_flag(target, TIF_LSX_CTX_LIVE)) {
|
||||
/* Copy scalar FP context, fill the rest with 0xff */
|
||||
copy_pad_fprs(target, regset, &to, 8);
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
} else if (!test_tsk_thread_flag(target, TIF_LASX_CTX_LIVE)) {
|
||||
/* Copy LSX 128 Bit context, fill the rest with 0xff */
|
||||
copy_pad_fprs(target, regset, &to, 16);
|
||||
#endif
|
||||
} else if (sizeof(target->thread.fpu.fpr[0]) == regset->size) {
|
||||
/* Trivially copy the vector registers */
|
||||
membuf_write(&to, &target->thread.fpu.fpr, wr_size);
|
||||
} else {
|
||||
/* Copy as much context as possible, fill the rest with 0xff */
|
||||
copy_pad_fprs(target, regset, &to, sizeof(target->thread.fpu.fpr[0]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int simd_set(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
const unsigned int wr_size = NUM_FPU_REGS * regset->size;
|
||||
unsigned int cp_sz;
|
||||
int i, err, start;
|
||||
|
||||
init_fp_ctx(target);
|
||||
|
||||
if (sizeof(target->thread.fpu.fpr[0]) == regset->size) {
|
||||
/* Trivially copy the vector registers */
|
||||
err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fpu.fpr,
|
||||
0, wr_size);
|
||||
} else {
|
||||
/* Copy as much context as possible */
|
||||
cp_sz = min_t(unsigned int, regset->size,
|
||||
sizeof(target->thread.fpu.fpr[0]));
|
||||
|
||||
i = start = err = 0;
|
||||
for (; i < NUM_FPU_REGS; i++, start += regset->size) {
|
||||
err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fpu.fpr[i],
|
||||
start, start + cp_sz);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CPU_HAS_LSX */
|
||||
|
||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
|
||||
/*
|
||||
@@ -708,6 +792,12 @@ enum loongarch_regset {
|
||||
REGSET_GPR,
|
||||
REGSET_FPR,
|
||||
REGSET_CPUCFG,
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
REGSET_LSX,
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
REGSET_LASX,
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
REGSET_HW_BREAK,
|
||||
REGSET_HW_WATCH,
|
||||
@@ -739,6 +829,26 @@ static const struct user_regset loongarch64_regsets[] = {
|
||||
.regset_get = cfg_get,
|
||||
.set = cfg_set,
|
||||
},
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
[REGSET_LSX] = {
|
||||
.core_note_type = NT_LOONGARCH_LSX,
|
||||
.n = NUM_FPU_REGS,
|
||||
.size = 16,
|
||||
.align = 16,
|
||||
.regset_get = simd_get,
|
||||
.set = simd_set,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
[REGSET_LASX] = {
|
||||
.core_note_type = NT_LOONGARCH_LASX,
|
||||
.n = NUM_FPU_REGS,
|
||||
.size = 32,
|
||||
.align = 32,
|
||||
.regset_get = simd_get,
|
||||
.set = simd_set,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
[REGSET_HW_BREAK] = {
|
||||
.core_note_type = NT_LOONGARCH_HW_BREAK,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Generic return hook for LoongArch.
|
||||
*/
|
||||
|
||||
#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, 0);
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_rethook_trampoline_callback);
|
||||
|
||||
void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount)
|
||||
{
|
||||
rhn->frame = 0;
|
||||
rhn->ret_addr = regs->regs[1];
|
||||
|
||||
/* replace return addr with trampoline */
|
||||
regs->regs[1] = (unsigned long)arch_rethook_trampoline;
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_rethook_prepare);
|
||||
|
||||
/* ASM function that handles the rethook must not be probed itself */
|
||||
NOKPROBE_SYMBOL(arch_rethook_trampoline);
|
||||
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LOONGARCH_RETHOOK_H
|
||||
#define __LOONGARCH_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,7 +75,7 @@
|
||||
csrxchg t0, t1, LOONGARCH_CSR_CRMD
|
||||
.endm
|
||||
|
||||
SYM_CODE_START(__kretprobe_trampoline)
|
||||
SYM_CODE_START(arch_rethook_trampoline)
|
||||
addi.d sp, sp, -PT_SIZE
|
||||
save_all_base_regs
|
||||
|
||||
@@ -84,7 +84,7 @@ SYM_CODE_START(__kretprobe_trampoline)
|
||||
|
||||
move a0, sp /* pt_regs */
|
||||
|
||||
bl trampoline_probe_handler
|
||||
bl arch_rethook_trampoline_callback
|
||||
|
||||
/* use the result as the return-address */
|
||||
move ra, a0
|
||||
@@ -93,4 +93,4 @@ SYM_CODE_START(__kretprobe_trampoline)
|
||||
addi.d sp, sp, PT_SIZE
|
||||
|
||||
jr ra
|
||||
SYM_CODE_END(__kretprobe_trampoline)
|
||||
SYM_CODE_END(arch_rethook_trampoline)
|
||||
@@ -50,6 +50,14 @@ extern asmlinkage int
|
||||
_save_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
|
||||
extern asmlinkage int
|
||||
_restore_fp_context(void __user *fpregs, void __user *fcc, void __user *csr);
|
||||
extern asmlinkage int
|
||||
_save_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
|
||||
extern asmlinkage int
|
||||
_restore_lsx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
|
||||
extern asmlinkage int
|
||||
_save_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
|
||||
extern asmlinkage int
|
||||
_restore_lasx_context(void __user *fpregs, void __user *fcc, void __user *fcsr);
|
||||
|
||||
struct rt_sigframe {
|
||||
struct siginfo rs_info;
|
||||
@@ -65,6 +73,8 @@ struct extctx_layout {
|
||||
unsigned long size;
|
||||
unsigned int flags;
|
||||
struct _ctx_layout fpu;
|
||||
struct _ctx_layout lsx;
|
||||
struct _ctx_layout lasx;
|
||||
struct _ctx_layout end;
|
||||
};
|
||||
|
||||
@@ -115,6 +125,96 @@ static int copy_fpu_from_sigcontext(struct fpu_context __user *ctx)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int copy_lsx_to_sigcontext(struct lsx_context __user *ctx)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
uint64_t __user *regs = (uint64_t *)&ctx->regs;
|
||||
uint64_t __user *fcc = &ctx->fcc;
|
||||
uint32_t __user *fcsr = &ctx->fcsr;
|
||||
|
||||
for (i = 0; i < NUM_FPU_REGS; i++) {
|
||||
err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0),
|
||||
®s[2*i]);
|
||||
err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 1),
|
||||
®s[2*i+1]);
|
||||
}
|
||||
err |= __put_user(current->thread.fpu.fcc, fcc);
|
||||
err |= __put_user(current->thread.fpu.fcsr, fcsr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int copy_lsx_from_sigcontext(struct lsx_context __user *ctx)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
u64 fpr_val;
|
||||
uint64_t __user *regs = (uint64_t *)&ctx->regs;
|
||||
uint64_t __user *fcc = &ctx->fcc;
|
||||
uint32_t __user *fcsr = &ctx->fcsr;
|
||||
|
||||
for (i = 0; i < NUM_FPU_REGS; i++) {
|
||||
err |= __get_user(fpr_val, ®s[2*i]);
|
||||
set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val);
|
||||
err |= __get_user(fpr_val, ®s[2*i+1]);
|
||||
set_fpr64(¤t->thread.fpu.fpr[i], 1, fpr_val);
|
||||
}
|
||||
err |= __get_user(current->thread.fpu.fcc, fcc);
|
||||
err |= __get_user(current->thread.fpu.fcsr, fcsr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int copy_lasx_to_sigcontext(struct lasx_context __user *ctx)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
uint64_t __user *regs = (uint64_t *)&ctx->regs;
|
||||
uint64_t __user *fcc = &ctx->fcc;
|
||||
uint32_t __user *fcsr = &ctx->fcsr;
|
||||
|
||||
for (i = 0; i < NUM_FPU_REGS; i++) {
|
||||
err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0),
|
||||
®s[4*i]);
|
||||
err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 1),
|
||||
®s[4*i+1]);
|
||||
err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 2),
|
||||
®s[4*i+2]);
|
||||
err |= __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 3),
|
||||
®s[4*i+3]);
|
||||
}
|
||||
err |= __put_user(current->thread.fpu.fcc, fcc);
|
||||
err |= __put_user(current->thread.fpu.fcsr, fcsr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int copy_lasx_from_sigcontext(struct lasx_context __user *ctx)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
u64 fpr_val;
|
||||
uint64_t __user *regs = (uint64_t *)&ctx->regs;
|
||||
uint64_t __user *fcc = &ctx->fcc;
|
||||
uint32_t __user *fcsr = &ctx->fcsr;
|
||||
|
||||
for (i = 0; i < NUM_FPU_REGS; i++) {
|
||||
err |= __get_user(fpr_val, ®s[4*i]);
|
||||
set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val);
|
||||
err |= __get_user(fpr_val, ®s[4*i+1]);
|
||||
set_fpr64(¤t->thread.fpu.fpr[i], 1, fpr_val);
|
||||
err |= __get_user(fpr_val, ®s[4*i+2]);
|
||||
set_fpr64(¤t->thread.fpu.fpr[i], 2, fpr_val);
|
||||
err |= __get_user(fpr_val, ®s[4*i+3]);
|
||||
set_fpr64(¤t->thread.fpu.fpr[i], 3, fpr_val);
|
||||
}
|
||||
err |= __get_user(current->thread.fpu.fcc, fcc);
|
||||
err |= __get_user(current->thread.fpu.fcsr, fcsr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrappers for the assembly _{save,restore}_fp_context functions.
|
||||
*/
|
||||
@@ -136,6 +236,42 @@ static int restore_hw_fpu_context(struct fpu_context __user *ctx)
|
||||
return _restore_fp_context(regs, fcc, fcsr);
|
||||
}
|
||||
|
||||
static int save_hw_lsx_context(struct lsx_context __user *ctx)
|
||||
{
|
||||
uint64_t __user *regs = (uint64_t *)&ctx->regs;
|
||||
uint64_t __user *fcc = &ctx->fcc;
|
||||
uint32_t __user *fcsr = &ctx->fcsr;
|
||||
|
||||
return _save_lsx_context(regs, fcc, fcsr);
|
||||
}
|
||||
|
||||
static int restore_hw_lsx_context(struct lsx_context __user *ctx)
|
||||
{
|
||||
uint64_t __user *regs = (uint64_t *)&ctx->regs;
|
||||
uint64_t __user *fcc = &ctx->fcc;
|
||||
uint32_t __user *fcsr = &ctx->fcsr;
|
||||
|
||||
return _restore_lsx_context(regs, fcc, fcsr);
|
||||
}
|
||||
|
||||
static int save_hw_lasx_context(struct lasx_context __user *ctx)
|
||||
{
|
||||
uint64_t __user *regs = (uint64_t *)&ctx->regs;
|
||||
uint64_t __user *fcc = &ctx->fcc;
|
||||
uint32_t __user *fcsr = &ctx->fcsr;
|
||||
|
||||
return _save_lasx_context(regs, fcc, fcsr);
|
||||
}
|
||||
|
||||
static int restore_hw_lasx_context(struct lasx_context __user *ctx)
|
||||
{
|
||||
uint64_t __user *regs = (uint64_t *)&ctx->regs;
|
||||
uint64_t __user *fcc = &ctx->fcc;
|
||||
uint32_t __user *fcsr = &ctx->fcsr;
|
||||
|
||||
return _restore_lasx_context(regs, fcc, fcsr);
|
||||
}
|
||||
|
||||
static int fcsr_pending(unsigned int __user *fcsr)
|
||||
{
|
||||
int err, sig = 0;
|
||||
@@ -227,6 +363,162 @@ static int protected_restore_fpu_context(struct extctx_layout *extctx)
|
||||
return err ?: sig;
|
||||
}
|
||||
|
||||
static int protected_save_lsx_context(struct extctx_layout *extctx)
|
||||
{
|
||||
int err = 0;
|
||||
struct sctx_info __user *info = extctx->lsx.addr;
|
||||
struct lsx_context __user *lsx_ctx = (struct lsx_context *)get_ctx_through_ctxinfo(info);
|
||||
uint64_t __user *regs = (uint64_t *)&lsx_ctx->regs;
|
||||
uint64_t __user *fcc = &lsx_ctx->fcc;
|
||||
uint32_t __user *fcsr = &lsx_ctx->fcsr;
|
||||
|
||||
while (1) {
|
||||
lock_fpu_owner();
|
||||
if (is_lsx_enabled())
|
||||
err = save_hw_lsx_context(lsx_ctx);
|
||||
else {
|
||||
if (is_fpu_owner())
|
||||
save_fp(current);
|
||||
err = copy_lsx_to_sigcontext(lsx_ctx);
|
||||
}
|
||||
unlock_fpu_owner();
|
||||
|
||||
err |= __put_user(LSX_CTX_MAGIC, &info->magic);
|
||||
err |= __put_user(extctx->lsx.size, &info->size);
|
||||
|
||||
if (likely(!err))
|
||||
break;
|
||||
/* Touch the LSX context and try again */
|
||||
err = __put_user(0, ®s[0]) |
|
||||
__put_user(0, ®s[32*2-1]) |
|
||||
__put_user(0, fcc) |
|
||||
__put_user(0, fcsr);
|
||||
if (err)
|
||||
return err; /* really bad sigcontext */
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int protected_restore_lsx_context(struct extctx_layout *extctx)
|
||||
{
|
||||
int err = 0, sig = 0, tmp __maybe_unused;
|
||||
struct sctx_info __user *info = extctx->lsx.addr;
|
||||
struct lsx_context __user *lsx_ctx = (struct lsx_context *)get_ctx_through_ctxinfo(info);
|
||||
uint64_t __user *regs = (uint64_t *)&lsx_ctx->regs;
|
||||
uint64_t __user *fcc = &lsx_ctx->fcc;
|
||||
uint32_t __user *fcsr = &lsx_ctx->fcsr;
|
||||
|
||||
err = sig = fcsr_pending(fcsr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
while (1) {
|
||||
lock_fpu_owner();
|
||||
if (is_lsx_enabled())
|
||||
err = restore_hw_lsx_context(lsx_ctx);
|
||||
else {
|
||||
err = copy_lsx_from_sigcontext(lsx_ctx);
|
||||
if (is_fpu_owner())
|
||||
restore_fp(current);
|
||||
}
|
||||
unlock_fpu_owner();
|
||||
|
||||
if (likely(!err))
|
||||
break;
|
||||
/* Touch the LSX context and try again */
|
||||
err = __get_user(tmp, ®s[0]) |
|
||||
__get_user(tmp, ®s[32*2-1]) |
|
||||
__get_user(tmp, fcc) |
|
||||
__get_user(tmp, fcsr);
|
||||
if (err)
|
||||
break; /* really bad sigcontext */
|
||||
}
|
||||
|
||||
return err ?: sig;
|
||||
}
|
||||
|
||||
static int protected_save_lasx_context(struct extctx_layout *extctx)
|
||||
{
|
||||
int err = 0;
|
||||
struct sctx_info __user *info = extctx->lasx.addr;
|
||||
struct lasx_context __user *lasx_ctx =
|
||||
(struct lasx_context *)get_ctx_through_ctxinfo(info);
|
||||
uint64_t __user *regs = (uint64_t *)&lasx_ctx->regs;
|
||||
uint64_t __user *fcc = &lasx_ctx->fcc;
|
||||
uint32_t __user *fcsr = &lasx_ctx->fcsr;
|
||||
|
||||
while (1) {
|
||||
lock_fpu_owner();
|
||||
if (is_lasx_enabled())
|
||||
err = save_hw_lasx_context(lasx_ctx);
|
||||
else {
|
||||
if (is_lsx_enabled())
|
||||
save_lsx(current);
|
||||
else if (is_fpu_owner())
|
||||
save_fp(current);
|
||||
err = copy_lasx_to_sigcontext(lasx_ctx);
|
||||
}
|
||||
unlock_fpu_owner();
|
||||
|
||||
err |= __put_user(LASX_CTX_MAGIC, &info->magic);
|
||||
err |= __put_user(extctx->lasx.size, &info->size);
|
||||
|
||||
if (likely(!err))
|
||||
break;
|
||||
/* Touch the LASX context and try again */
|
||||
err = __put_user(0, ®s[0]) |
|
||||
__put_user(0, ®s[32*4-1]) |
|
||||
__put_user(0, fcc) |
|
||||
__put_user(0, fcsr);
|
||||
if (err)
|
||||
return err; /* really bad sigcontext */
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int protected_restore_lasx_context(struct extctx_layout *extctx)
|
||||
{
|
||||
int err = 0, sig = 0, tmp __maybe_unused;
|
||||
struct sctx_info __user *info = extctx->lasx.addr;
|
||||
struct lasx_context __user *lasx_ctx =
|
||||
(struct lasx_context *)get_ctx_through_ctxinfo(info);
|
||||
uint64_t __user *regs = (uint64_t *)&lasx_ctx->regs;
|
||||
uint64_t __user *fcc = &lasx_ctx->fcc;
|
||||
uint32_t __user *fcsr = &lasx_ctx->fcsr;
|
||||
|
||||
err = sig = fcsr_pending(fcsr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
while (1) {
|
||||
lock_fpu_owner();
|
||||
if (is_lasx_enabled())
|
||||
err = restore_hw_lasx_context(lasx_ctx);
|
||||
else {
|
||||
err = copy_lasx_from_sigcontext(lasx_ctx);
|
||||
if (is_lsx_enabled())
|
||||
restore_lsx(current);
|
||||
else if (is_fpu_owner())
|
||||
restore_fp(current);
|
||||
}
|
||||
unlock_fpu_owner();
|
||||
|
||||
if (likely(!err))
|
||||
break;
|
||||
/* Touch the LASX context and try again */
|
||||
err = __get_user(tmp, ®s[0]) |
|
||||
__get_user(tmp, ®s[32*4-1]) |
|
||||
__get_user(tmp, fcc) |
|
||||
__get_user(tmp, fcsr);
|
||||
if (err)
|
||||
break; /* really bad sigcontext */
|
||||
}
|
||||
|
||||
return err ?: sig;
|
||||
}
|
||||
|
||||
static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
|
||||
struct extctx_layout *extctx)
|
||||
{
|
||||
@@ -240,7 +532,11 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
|
||||
for (i = 1; i < 32; i++)
|
||||
err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
|
||||
|
||||
if (extctx->fpu.addr)
|
||||
if (extctx->lasx.addr)
|
||||
err |= protected_save_lasx_context(extctx);
|
||||
else if (extctx->lsx.addr)
|
||||
err |= protected_save_lsx_context(extctx);
|
||||
else if (extctx->fpu.addr)
|
||||
err |= protected_save_fpu_context(extctx);
|
||||
|
||||
/* Set the "end" magic */
|
||||
@@ -274,6 +570,20 @@ static int parse_extcontext(struct sigcontext __user *sc, struct extctx_layout *
|
||||
extctx->fpu.addr = info;
|
||||
break;
|
||||
|
||||
case LSX_CTX_MAGIC:
|
||||
if (size < (sizeof(struct sctx_info) +
|
||||
sizeof(struct lsx_context)))
|
||||
goto invalid;
|
||||
extctx->lsx.addr = info;
|
||||
break;
|
||||
|
||||
case LASX_CTX_MAGIC:
|
||||
if (size < (sizeof(struct sctx_info) +
|
||||
sizeof(struct lasx_context)))
|
||||
goto invalid;
|
||||
extctx->lasx.addr = info;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto invalid;
|
||||
}
|
||||
@@ -319,7 +629,11 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc
|
||||
for (i = 1; i < 32; i++)
|
||||
err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
|
||||
|
||||
if (extctx.fpu.addr)
|
||||
if (extctx.lasx.addr)
|
||||
err |= protected_restore_lasx_context(&extctx);
|
||||
else if (extctx.lsx.addr)
|
||||
err |= protected_restore_lsx_context(&extctx);
|
||||
else if (extctx.fpu.addr)
|
||||
err |= protected_restore_fpu_context(&extctx);
|
||||
|
||||
bad:
|
||||
@@ -375,7 +689,13 @@ static unsigned long setup_extcontext(struct extctx_layout *extctx, unsigned lon
|
||||
extctx->size += extctx->end.size;
|
||||
|
||||
if (extctx->flags & SC_USED_FP) {
|
||||
if (cpu_has_fpu)
|
||||
if (cpu_has_lasx && thread_lasx_context_live())
|
||||
new_sp = extframe_alloc(extctx, &extctx->lasx,
|
||||
sizeof(struct lasx_context), LASX_CTX_ALIGN, new_sp);
|
||||
else if (cpu_has_lsx && thread_lsx_context_live())
|
||||
new_sp = extframe_alloc(extctx, &extctx->lsx,
|
||||
sizeof(struct lsx_context), LSX_CTX_ALIGN, new_sp);
|
||||
else if (cpu_has_fpu)
|
||||
new_sp = extframe_alloc(extctx, &extctx->fpu,
|
||||
sizeof(struct fpu_context), FPU_CTX_ALIGN, new_sp);
|
||||
}
|
||||
|
||||
+12
-15
@@ -8,6 +8,7 @@
|
||||
* Copyright (C) 2000, 2001 Silicon Graphics, Inc.
|
||||
* Copyright (C) 2000, 2001, 2003 Broadcom Corporation
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/init.h>
|
||||
@@ -37,10 +38,6 @@ EXPORT_SYMBOL(__cpu_number_map);
|
||||
int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
|
||||
EXPORT_SYMBOL(__cpu_logical_map);
|
||||
|
||||
/* Number of threads (siblings) per CPU core */
|
||||
int smp_num_siblings = 1;
|
||||
EXPORT_SYMBOL(smp_num_siblings);
|
||||
|
||||
/* Representing the threads (siblings) of each logical CPU */
|
||||
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
|
||||
EXPORT_SYMBOL(cpu_sibling_map);
|
||||
@@ -118,7 +115,7 @@ static u32 ipi_read_clear(int cpu)
|
||||
action = iocsr_read32(LOONGARCH_IOCSR_IPI_STATUS);
|
||||
/* Clear the ipi register to clear the interrupt */
|
||||
iocsr_write32(action, LOONGARCH_IOCSR_IPI_CLEAR);
|
||||
smp_mb();
|
||||
wbflush();
|
||||
|
||||
return action;
|
||||
}
|
||||
@@ -210,6 +207,7 @@ static void __init fdt_smp_setup(void)
|
||||
}
|
||||
|
||||
loongson_sysconf.nr_cpus = num_processors;
|
||||
set_bit(0, &(loongson_sysconf.cores_io_master));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -228,9 +226,12 @@ void __init loongson_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
parse_acpi_topology();
|
||||
|
||||
for (i = 0; i < loongson_sysconf.nr_cpus; i++) {
|
||||
set_cpu_present(i, true);
|
||||
csr_mail_send(0, __cpu_logical_map[i], 0);
|
||||
cpu_data[i].global_id = __cpu_logical_map[i];
|
||||
}
|
||||
|
||||
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
|
||||
@@ -271,10 +272,10 @@ void loongson_init_secondary(void)
|
||||
numa_add_cpu(cpu);
|
||||
#endif
|
||||
per_cpu(cpu_state, cpu) = CPU_ONLINE;
|
||||
cpu_data[cpu].core =
|
||||
cpu_logical_map(cpu) % loongson_sysconf.cores_per_package;
|
||||
cpu_data[cpu].package =
|
||||
cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
|
||||
cpu_data[cpu].core = pptt_enabled ? cpu_data[cpu].core :
|
||||
cpu_logical_map(cpu) % loongson_sysconf.cores_per_package;
|
||||
}
|
||||
|
||||
void loongson_smp_finish(void)
|
||||
@@ -380,14 +381,10 @@ static inline void set_cpu_sibling_map(int cpu)
|
||||
|
||||
cpumask_set_cpu(cpu, &cpu_sibling_setup_map);
|
||||
|
||||
if (smp_num_siblings <= 1)
|
||||
cpumask_set_cpu(cpu, &cpu_sibling_map[cpu]);
|
||||
else {
|
||||
for_each_cpu(i, &cpu_sibling_setup_map) {
|
||||
if (cpus_are_siblings(cpu, i)) {
|
||||
cpumask_set_cpu(i, &cpu_sibling_map[cpu]);
|
||||
cpumask_set_cpu(cpu, &cpu_sibling_map[i]);
|
||||
}
|
||||
for_each_cpu(i, &cpu_sibling_setup_map) {
|
||||
if (cpus_are_siblings(cpu, i)) {
|
||||
cpumask_set_cpu(i, &cpu_sibling_map[cpu]);
|
||||
cpumask_set_cpu(cpu, &cpu_sibling_map[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/unwind.h>
|
||||
#include <asm/uprobes.h>
|
||||
|
||||
#include "access-helper.h"
|
||||
|
||||
@@ -689,7 +690,6 @@ asmlinkage void noinstr do_bp(struct pt_regs *regs)
|
||||
if (regs->csr_prmd & CSR_PRMD_PIE)
|
||||
local_irq_enable();
|
||||
|
||||
current->thread.trap_nr = read_csr_excode();
|
||||
if (__get_inst(&opcode, (u32 *)era, user))
|
||||
goto out_sigsegv;
|
||||
|
||||
@@ -711,18 +711,17 @@ asmlinkage void noinstr do_bp(struct pt_regs *regs)
|
||||
else
|
||||
break;
|
||||
case BRK_UPROBE_BP:
|
||||
if (notify_die(DIE_UPROBE, "Uprobe", regs, bcode,
|
||||
current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
|
||||
if (uprobe_breakpoint_handler(regs))
|
||||
goto out;
|
||||
else
|
||||
break;
|
||||
case BRK_UPROBE_XOLBP:
|
||||
if (notify_die(DIE_UPROBE_XOL, "Uprobe_XOL", regs, bcode,
|
||||
current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
|
||||
if (uprobe_singlestep_handler(regs))
|
||||
goto out;
|
||||
else
|
||||
break;
|
||||
default:
|
||||
current->thread.trap_nr = read_csr_excode();
|
||||
if (notify_die(DIE_TRAP, "Break", regs, bcode,
|
||||
current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
|
||||
goto out;
|
||||
@@ -852,12 +851,67 @@ static void init_restore_fp(void)
|
||||
BUG_ON(!is_fp_enabled());
|
||||
}
|
||||
|
||||
static void init_restore_lsx(void)
|
||||
{
|
||||
enable_lsx();
|
||||
|
||||
if (!thread_lsx_context_live()) {
|
||||
/* First time LSX context user */
|
||||
init_restore_fp();
|
||||
init_lsx_upper();
|
||||
set_thread_flag(TIF_LSX_CTX_LIVE);
|
||||
} else {
|
||||
if (!is_simd_owner()) {
|
||||
if (is_fpu_owner()) {
|
||||
restore_lsx_upper(current);
|
||||
} else {
|
||||
__own_fpu();
|
||||
restore_lsx(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_thread_flag(TIF_USEDSIMD);
|
||||
|
||||
BUG_ON(!is_fp_enabled());
|
||||
BUG_ON(!is_lsx_enabled());
|
||||
}
|
||||
|
||||
static void init_restore_lasx(void)
|
||||
{
|
||||
enable_lasx();
|
||||
|
||||
if (!thread_lasx_context_live()) {
|
||||
/* First time LASX context user */
|
||||
init_restore_lsx();
|
||||
init_lasx_upper();
|
||||
set_thread_flag(TIF_LASX_CTX_LIVE);
|
||||
} else {
|
||||
if (is_fpu_owner() || is_simd_owner()) {
|
||||
init_restore_lsx();
|
||||
restore_lasx_upper(current);
|
||||
} else {
|
||||
__own_fpu();
|
||||
enable_lsx();
|
||||
restore_lasx(current);
|
||||
}
|
||||
}
|
||||
|
||||
set_thread_flag(TIF_USEDSIMD);
|
||||
|
||||
BUG_ON(!is_fp_enabled());
|
||||
BUG_ON(!is_lsx_enabled());
|
||||
BUG_ON(!is_lasx_enabled());
|
||||
}
|
||||
|
||||
asmlinkage void noinstr do_fpu(struct pt_regs *regs)
|
||||
{
|
||||
irqentry_state_t state = irqentry_enter(regs);
|
||||
|
||||
local_irq_enable();
|
||||
die_if_kernel("do_fpu invoked from kernel context!", regs);
|
||||
BUG_ON(is_lsx_enabled());
|
||||
BUG_ON(is_lasx_enabled());
|
||||
|
||||
preempt_disable();
|
||||
init_restore_fp();
|
||||
@@ -872,9 +926,20 @@ asmlinkage void noinstr do_lsx(struct pt_regs *regs)
|
||||
irqentry_state_t state = irqentry_enter(regs);
|
||||
|
||||
local_irq_enable();
|
||||
force_sig(SIGILL);
|
||||
local_irq_disable();
|
||||
if (!cpu_has_lsx) {
|
||||
force_sig(SIGILL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
die_if_kernel("do_lsx invoked from kernel context!", regs);
|
||||
BUG_ON(is_lasx_enabled());
|
||||
|
||||
preempt_disable();
|
||||
init_restore_lsx();
|
||||
preempt_enable();
|
||||
|
||||
out:
|
||||
local_irq_disable();
|
||||
irqentry_exit(regs, state);
|
||||
}
|
||||
|
||||
@@ -883,9 +948,19 @@ asmlinkage void noinstr do_lasx(struct pt_regs *regs)
|
||||
irqentry_state_t state = irqentry_enter(regs);
|
||||
|
||||
local_irq_enable();
|
||||
force_sig(SIGILL);
|
||||
local_irq_disable();
|
||||
if (!cpu_has_lasx) {
|
||||
force_sig(SIGILL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
die_if_kernel("do_lasx invoked from kernel context!", regs);
|
||||
|
||||
preempt_disable();
|
||||
init_restore_lasx();
|
||||
preempt_enable();
|
||||
|
||||
out:
|
||||
local_irq_disable();
|
||||
irqentry_exit(regs, state);
|
||||
}
|
||||
|
||||
@@ -924,7 +999,7 @@ asmlinkage void cache_parity_error(void)
|
||||
/* For the moment, report the problem and hang. */
|
||||
pr_err("Cache error exception:\n");
|
||||
pr_err("csr_merrctl == %08x\n", csr_read32(LOONGARCH_CSR_MERRCTL));
|
||||
pr_err("csr_merrera == %016llx\n", csr_read64(LOONGARCH_CSR_MERRERA));
|
||||
pr_err("csr_merrera == %016lx\n", csr_read64(LOONGARCH_CSR_MERRERA));
|
||||
panic("Can't handle the cache error!");
|
||||
}
|
||||
|
||||
|
||||
@@ -485,8 +485,6 @@ static int __init debugfs_unaligned(void)
|
||||
struct dentry *d;
|
||||
|
||||
d = debugfs_create_dir("loongarch", NULL);
|
||||
if (IS_ERR_OR_NULL(d))
|
||||
return -ENOMEM;
|
||||
|
||||
debugfs_create_u32("unaligned_instructions_user",
|
||||
S_IRUGO, d, &unaligned_instructions_user);
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/uprobes.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#define UPROBE_TRAP_NR UINT_MAX
|
||||
|
||||
int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
|
||||
struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
int idx;
|
||||
union loongarch_instruction insn;
|
||||
|
||||
if (addr & 0x3)
|
||||
return -EILSEQ;
|
||||
|
||||
for (idx = ARRAY_SIZE(auprobe->insn) - 1; idx >= 0; idx--) {
|
||||
insn.word = auprobe->insn[idx];
|
||||
if (insns_not_supported(insn))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (insns_need_simulation(insn)) {
|
||||
auprobe->ixol[0] = larch_insn_gen_nop();
|
||||
auprobe->simulate = true;
|
||||
} else {
|
||||
auprobe->ixol[0] = auprobe->insn[0];
|
||||
auprobe->simulate = false;
|
||||
}
|
||||
|
||||
auprobe->ixol[1] = UPROBE_XOLBP_INSN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
{
|
||||
struct uprobe_task *utask = current->utask;
|
||||
|
||||
utask->autask.saved_trap_nr = current->thread.trap_nr;
|
||||
current->thread.trap_nr = UPROBE_TRAP_NR;
|
||||
instruction_pointer_set(regs, utask->xol_vaddr);
|
||||
user_enable_single_step(current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
{
|
||||
struct uprobe_task *utask = current->utask;
|
||||
|
||||
WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR);
|
||||
current->thread.trap_nr = utask->autask.saved_trap_nr;
|
||||
|
||||
if (auprobe->simulate)
|
||||
instruction_pointer_set(regs, auprobe->resume_era);
|
||||
else
|
||||
instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE);
|
||||
|
||||
user_disable_single_step(current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
{
|
||||
struct uprobe_task *utask = current->utask;
|
||||
|
||||
current->thread.trap_nr = utask->autask.saved_trap_nr;
|
||||
instruction_pointer_set(regs, utask->vaddr);
|
||||
user_disable_single_step(current);
|
||||
}
|
||||
|
||||
bool arch_uprobe_xol_was_trapped(struct task_struct *t)
|
||||
{
|
||||
if (t->thread.trap_nr != UPROBE_TRAP_NR)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
{
|
||||
union loongarch_instruction insn;
|
||||
|
||||
if (!auprobe->simulate)
|
||||
return false;
|
||||
|
||||
insn.word = auprobe->insn[0];
|
||||
arch_simulate_insn(insn, regs);
|
||||
auprobe->resume_era = regs->csr_era;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long ra = regs->regs[1];
|
||||
|
||||
regs->regs[1] = trampoline_vaddr;
|
||||
|
||||
return ra;
|
||||
}
|
||||
|
||||
bool arch_uretprobe_is_alive(struct return_instance *ret,
|
||||
enum rp_check ctx, struct pt_regs *regs)
|
||||
{
|
||||
if (ctx == RP_CHECK_CHAIN_CALL)
|
||||
return regs->regs[3] <= ret->stack;
|
||||
else
|
||||
return regs->regs[3] < ret->stack;
|
||||
}
|
||||
|
||||
int arch_uprobe_exception_notify(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
bool uprobe_breakpoint_handler(struct pt_regs *regs)
|
||||
{
|
||||
if (uprobe_pre_sstep_notifier(regs))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool uprobe_singlestep_handler(struct pt_regs *regs)
|
||||
{
|
||||
if (uprobe_post_sstep_notifier(regs))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
|
||||
{
|
||||
return instruction_pointer(regs);
|
||||
}
|
||||
|
||||
void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
|
||||
void *src, unsigned long len)
|
||||
{
|
||||
void *kaddr = kmap_local_page(page);
|
||||
void *dst = kaddr + (vaddr & ~PAGE_MASK);
|
||||
|
||||
memcpy(dst, src, len);
|
||||
flush_icache_range((unsigned long)dst, (unsigned long)dst + len);
|
||||
kunmap_local(kaddr);
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time_namespace.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
@@ -26,12 +27,17 @@ extern char vdso_start[], vdso_end[];
|
||||
|
||||
/* Kernel-provided data used by the VDSO. */
|
||||
static union {
|
||||
u8 page[VDSO_DATA_SIZE];
|
||||
u8 page[PAGE_SIZE];
|
||||
struct vdso_data data[CS_BASES];
|
||||
} generic_vdso_data __page_aligned_data;
|
||||
|
||||
static union {
|
||||
u8 page[LOONGARCH_VDSO_DATA_SIZE];
|
||||
struct loongarch_vdso_data vdata;
|
||||
} loongarch_vdso_data __page_aligned_data;
|
||||
|
||||
static struct page *vdso_pages[] = { NULL };
|
||||
struct vdso_data *vdso_data = loongarch_vdso_data.vdata.data;
|
||||
struct vdso_data *vdso_data = generic_vdso_data.data;
|
||||
struct vdso_pcpu_data *vdso_pdata = loongarch_vdso_data.vdata.pdata;
|
||||
|
||||
static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma)
|
||||
@@ -41,6 +47,43 @@ static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
|
||||
struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
unsigned long pfn;
|
||||
struct page *timens_page = find_timens_vvar_page(vma);
|
||||
|
||||
switch (vmf->pgoff) {
|
||||
case VVAR_GENERIC_PAGE_OFFSET:
|
||||
if (!timens_page)
|
||||
pfn = sym_to_pfn(vdso_data);
|
||||
else
|
||||
pfn = page_to_pfn(timens_page);
|
||||
break;
|
||||
#ifdef CONFIG_TIME_NS
|
||||
case VVAR_TIMENS_PAGE_OFFSET:
|
||||
/*
|
||||
* If a task belongs to a time namespace then a namespace specific
|
||||
* VVAR is mapped with the VVAR_GENERIC_PAGE_OFFSET and the real
|
||||
* VVAR page is mapped with the VVAR_TIMENS_PAGE_OFFSET offset.
|
||||
* See also the comment near timens_setup_vdso_data().
|
||||
*/
|
||||
if (!timens_page)
|
||||
return VM_FAULT_SIGBUS;
|
||||
else
|
||||
pfn = sym_to_pfn(vdso_data);
|
||||
break;
|
||||
#endif /* CONFIG_TIME_NS */
|
||||
case VVAR_LOONGARCH_PAGES_START ... VVAR_LOONGARCH_PAGES_END:
|
||||
pfn = sym_to_pfn(&loongarch_vdso_data) + vmf->pgoff - VVAR_LOONGARCH_PAGES_START;
|
||||
break;
|
||||
default:
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
||||
return vmf_insert_pfn(vma, vmf->address, pfn);
|
||||
}
|
||||
|
||||
struct loongarch_vdso_info vdso_info = {
|
||||
.vdso = vdso_start,
|
||||
.size = PAGE_SIZE,
|
||||
@@ -51,6 +94,7 @@ struct loongarch_vdso_info vdso_info = {
|
||||
},
|
||||
.data_mapping = {
|
||||
.name = "[vvar]",
|
||||
.fault = vvar_fault,
|
||||
},
|
||||
.offset_sigreturn = vdso_offset_sigreturn,
|
||||
};
|
||||
@@ -73,6 +117,37 @@ static int __init init_vdso(void)
|
||||
}
|
||||
subsys_initcall(init_vdso);
|
||||
|
||||
#ifdef CONFIG_TIME_NS
|
||||
struct vdso_data *arch_get_vdso_data(void *vvar_page)
|
||||
{
|
||||
return (struct vdso_data *)(vvar_page);
|
||||
}
|
||||
|
||||
/*
|
||||
* The vvar mapping contains data for a specific time namespace, so when a
|
||||
* task changes namespace we must unmap its vvar data for the old namespace.
|
||||
* Subsequent faults will map in data for the new namespace.
|
||||
*
|
||||
* For more details see timens_setup_vdso_data().
|
||||
*/
|
||||
int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
|
||||
{
|
||||
struct mm_struct *mm = task->mm;
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
VMA_ITERATOR(vmi, mm, 0);
|
||||
|
||||
mmap_read_lock(mm);
|
||||
for_each_vma(vmi, vma) {
|
||||
if (vma_is_special_mapping(vma, &vdso_info.data_mapping))
|
||||
zap_vma_pages(vma);
|
||||
}
|
||||
mmap_read_unlock(mm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned long vdso_base(void)
|
||||
{
|
||||
unsigned long base = STACK_TOP;
|
||||
@@ -88,7 +163,7 @@ static unsigned long vdso_base(void)
|
||||
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||
{
|
||||
int ret;
|
||||
unsigned long vvar_size, size, data_addr, vdso_addr;
|
||||
unsigned long size, data_addr, vdso_addr;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
struct loongarch_vdso_info *info = current->thread.vdso;
|
||||
@@ -100,32 +175,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||
* Determine total area size. This includes the VDSO data itself
|
||||
* and the data pages.
|
||||
*/
|
||||
vvar_size = VDSO_DATA_SIZE;
|
||||
size = vvar_size + info->size;
|
||||
size = VVAR_SIZE + info->size;
|
||||
|
||||
data_addr = get_unmapped_area(NULL, vdso_base(), size, 0, 0);
|
||||
if (IS_ERR_VALUE(data_addr)) {
|
||||
ret = data_addr;
|
||||
goto out;
|
||||
}
|
||||
vdso_addr = data_addr + VDSO_DATA_SIZE;
|
||||
|
||||
vma = _install_special_mapping(mm, data_addr, vvar_size,
|
||||
VM_READ | VM_MAYREAD,
|
||||
vma = _install_special_mapping(mm, data_addr, VVAR_SIZE,
|
||||
VM_READ | VM_MAYREAD | VM_PFNMAP,
|
||||
&info->data_mapping);
|
||||
if (IS_ERR(vma)) {
|
||||
ret = PTR_ERR(vma);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Map VDSO data page. */
|
||||
ret = remap_pfn_range(vma, data_addr,
|
||||
virt_to_phys(&loongarch_vdso_data) >> PAGE_SHIFT,
|
||||
vvar_size, PAGE_READONLY);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Map VDSO code page. */
|
||||
vdso_addr = data_addr + VVAR_SIZE;
|
||||
vma = _install_special_mapping(mm, vdso_addr, info->size,
|
||||
VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
|
||||
&info->code_mapping);
|
||||
|
||||
@@ -136,6 +136,15 @@ SECTIONS
|
||||
DWARF_DEBUG
|
||||
ELF_DETAILS
|
||||
|
||||
#ifdef CONFIG_EFI_STUB
|
||||
/* header symbols */
|
||||
_kernel_asize = _end - _text;
|
||||
_kernel_fsize = _edata - _text;
|
||||
_kernel_vsize = _end - __initdata_begin;
|
||||
_kernel_rsize = _edata - __initdata_begin;
|
||||
_kernel_offset = kernel_offset - _text;
|
||||
#endif
|
||||
|
||||
.gptab.sdata : {
|
||||
*(.gptab.data)
|
||||
*(.gptab.sdata)
|
||||
|
||||
@@ -20,9 +20,9 @@ void dump_tlb_regs(void)
|
||||
|
||||
pr_info("Index : 0x%0x\n", read_csr_tlbidx());
|
||||
pr_info("PageSize : 0x%0x\n", read_csr_pagesize());
|
||||
pr_info("EntryHi : 0x%0*llx\n", field, read_csr_entryhi());
|
||||
pr_info("EntryLo0 : 0x%0*llx\n", field, read_csr_entrylo0());
|
||||
pr_info("EntryLo1 : 0x%0*llx\n", field, read_csr_entrylo1());
|
||||
pr_info("EntryHi : 0x%0*lx\n", field, read_csr_entryhi());
|
||||
pr_info("EntryLo0 : 0x%0*lx\n", field, read_csr_entrylo0());
|
||||
pr_info("EntryLo1 : 0x%0*lx\n", field, read_csr_entrylo1());
|
||||
}
|
||||
|
||||
static void dump_tlb(int first, int last)
|
||||
|
||||
+17
-4
@@ -167,6 +167,9 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep
|
||||
int idx;
|
||||
unsigned long flags;
|
||||
|
||||
if (cpu_has_ptw)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Handle debugger faulting in for debugee.
|
||||
*/
|
||||
@@ -222,6 +225,9 @@ static void setup_ptwalker(void)
|
||||
pwctl0 = pte_i | pte_w << 5 | pmd_i << 10 | pmd_w << 15 | pud_i << 20 | pud_w << 25;
|
||||
pwctl1 = pgd_i | pgd_w << 6;
|
||||
|
||||
if (cpu_has_ptw)
|
||||
pwctl1 |= CSR_PWCTL1_PTW;
|
||||
|
||||
csr_write64(pwctl0, LOONGARCH_CSR_PWCTL0);
|
||||
csr_write64(pwctl1, LOONGARCH_CSR_PWCTL1);
|
||||
csr_write64((long)swapper_pg_dir, LOONGARCH_CSR_PGDH);
|
||||
@@ -264,10 +270,17 @@ void setup_tlb_handler(int cpu)
|
||||
if (cpu == 0) {
|
||||
memcpy((void *)tlbrentry, handle_tlb_refill, 0x80);
|
||||
local_flush_icache_range(tlbrentry, tlbrentry + 0x80);
|
||||
set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE);
|
||||
set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE);
|
||||
set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE);
|
||||
set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE);
|
||||
if (!cpu_has_ptw) {
|
||||
set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load, VECSIZE);
|
||||
set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load, VECSIZE);
|
||||
set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store, VECSIZE);
|
||||
set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify, VECSIZE);
|
||||
} else {
|
||||
set_handler(EXCCODE_TLBI * VECSIZE, handle_tlb_load_ptw, VECSIZE);
|
||||
set_handler(EXCCODE_TLBL * VECSIZE, handle_tlb_load_ptw, VECSIZE);
|
||||
set_handler(EXCCODE_TLBS * VECSIZE, handle_tlb_store_ptw, VECSIZE);
|
||||
set_handler(EXCCODE_TLBM * VECSIZE, handle_tlb_modify_ptw, VECSIZE);
|
||||
}
|
||||
set_handler(EXCCODE_TLBNR * VECSIZE, handle_tlb_protect, VECSIZE);
|
||||
set_handler(EXCCODE_TLBNX * VECSIZE, handle_tlb_protect, VECSIZE);
|
||||
set_handler(EXCCODE_TLBPE * VECSIZE, handle_tlb_protect, VECSIZE);
|
||||
|
||||
@@ -184,12 +184,19 @@ tlb_huge_update_load:
|
||||
ertn
|
||||
|
||||
nopage_tlb_load:
|
||||
dbar 0
|
||||
dbar 0x700
|
||||
csrrd ra, EXCEPTION_KS2
|
||||
la_abs t0, tlb_do_page_fault_0
|
||||
jr t0
|
||||
SYM_FUNC_END(handle_tlb_load)
|
||||
|
||||
SYM_FUNC_START(handle_tlb_load_ptw)
|
||||
csrwr t0, LOONGARCH_CSR_KS0
|
||||
csrwr t1, LOONGARCH_CSR_KS1
|
||||
la_abs t0, tlb_do_page_fault_0
|
||||
jr t0
|
||||
SYM_FUNC_END(handle_tlb_load_ptw)
|
||||
|
||||
SYM_FUNC_START(handle_tlb_store)
|
||||
csrwr t0, EXCEPTION_KS0
|
||||
csrwr t1, EXCEPTION_KS1
|
||||
@@ -333,12 +340,19 @@ tlb_huge_update_store:
|
||||
ertn
|
||||
|
||||
nopage_tlb_store:
|
||||
dbar 0
|
||||
dbar 0x700
|
||||
csrrd ra, EXCEPTION_KS2
|
||||
la_abs t0, tlb_do_page_fault_1
|
||||
jr t0
|
||||
SYM_FUNC_END(handle_tlb_store)
|
||||
|
||||
SYM_FUNC_START(handle_tlb_store_ptw)
|
||||
csrwr t0, LOONGARCH_CSR_KS0
|
||||
csrwr t1, LOONGARCH_CSR_KS1
|
||||
la_abs t0, tlb_do_page_fault_1
|
||||
jr t0
|
||||
SYM_FUNC_END(handle_tlb_store_ptw)
|
||||
|
||||
SYM_FUNC_START(handle_tlb_modify)
|
||||
csrwr t0, EXCEPTION_KS0
|
||||
csrwr t1, EXCEPTION_KS1
|
||||
@@ -480,12 +494,19 @@ tlb_huge_update_modify:
|
||||
ertn
|
||||
|
||||
nopage_tlb_modify:
|
||||
dbar 0
|
||||
dbar 0x700
|
||||
csrrd ra, EXCEPTION_KS2
|
||||
la_abs t0, tlb_do_page_fault_1
|
||||
jr t0
|
||||
SYM_FUNC_END(handle_tlb_modify)
|
||||
|
||||
SYM_FUNC_START(handle_tlb_modify_ptw)
|
||||
csrwr t0, LOONGARCH_CSR_KS0
|
||||
csrwr t1, LOONGARCH_CSR_KS1
|
||||
la_abs t0, tlb_do_page_fault_1
|
||||
jr t0
|
||||
SYM_FUNC_END(handle_tlb_modify_ptw)
|
||||
|
||||
SYM_FUNC_START(handle_tlb_refill)
|
||||
csrwr t0, LOONGARCH_CSR_TLBRSAVE
|
||||
csrrd t0, LOONGARCH_CSR_PGD
|
||||
|
||||
@@ -27,7 +27,7 @@ struct saved_registers {
|
||||
};
|
||||
static struct saved_registers saved_regs;
|
||||
|
||||
static void arch_common_suspend(void)
|
||||
void loongarch_common_suspend(void)
|
||||
{
|
||||
save_counter();
|
||||
saved_regs.pgd = csr_read64(LOONGARCH_CSR_PGDL);
|
||||
@@ -40,7 +40,7 @@ static void arch_common_suspend(void)
|
||||
loongarch_suspend_addr = loongson_sysconf.suspend_addr;
|
||||
}
|
||||
|
||||
static void arch_common_resume(void)
|
||||
void loongarch_common_resume(void)
|
||||
{
|
||||
sync_counter();
|
||||
local_flush_tlb_all();
|
||||
@@ -62,12 +62,12 @@ int loongarch_acpi_suspend(void)
|
||||
enable_gpe_wakeup();
|
||||
enable_pci_wakeup();
|
||||
|
||||
arch_common_suspend();
|
||||
loongarch_common_suspend();
|
||||
|
||||
/* processor specific suspend */
|
||||
loongarch_suspend_enter();
|
||||
|
||||
arch_common_resume();
|
||||
loongarch_common_resume();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -12,16 +12,13 @@ ccflags-vdso := \
|
||||
$(filter -E%,$(KBUILD_CFLAGS)) \
|
||||
$(filter -march=%,$(KBUILD_CFLAGS)) \
|
||||
$(filter -m%-float,$(KBUILD_CFLAGS)) \
|
||||
$(CLANG_FLAGS) \
|
||||
-D__VDSO__
|
||||
|
||||
ifeq ($(cc-name),clang)
|
||||
ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS))
|
||||
endif
|
||||
|
||||
cflags-vdso := $(ccflags-vdso) \
|
||||
-isystem $(shell $(CC) -print-file-name=include) \
|
||||
$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
|
||||
-O2 -g -fno-strict-aliasing -fno-common -fno-builtin -G0 \
|
||||
-O2 -g -fno-strict-aliasing -fno-common -fno-builtin \
|
||||
-fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
|
||||
$(call cc-option, -fno-asynchronous-unwind-tables) \
|
||||
$(call cc-option, -fno-stack-protector)
|
||||
|
||||
@@ -21,7 +21,7 @@ static __always_inline int read_cpu_id(void)
|
||||
|
||||
static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
|
||||
{
|
||||
return (struct vdso_pcpu_data *)(get_vdso_base() - VDSO_DATA_SIZE);
|
||||
return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE);
|
||||
}
|
||||
|
||||
extern
|
||||
|
||||
@@ -289,7 +289,7 @@ retry:
|
||||
mmap_read_lock(mm);
|
||||
vma = find_vma_prev(mm, address, &prev_vma);
|
||||
if (!vma || address < vma->vm_start) {
|
||||
if (!prev || !(prev->vm_flags & VM_GROWSUP))
|
||||
if (!prev_vma || !(prev_vma->vm_flags & VM_GROWSUP))
|
||||
goto bad_area;
|
||||
vma = expand_stack(mm, address);
|
||||
if (!vma)
|
||||
|
||||
@@ -210,7 +210,7 @@ config PPC
|
||||
select HAVE_ARCH_KASAN if PPC_RADIX_MMU
|
||||
select HAVE_ARCH_KASAN if PPC_BOOK3E_64
|
||||
select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
|
||||
select HAVE_ARCH_KCSAN if PPC_BOOK3S_64
|
||||
select HAVE_ARCH_KCSAN
|
||||
select HAVE_ARCH_KFENCE if ARCH_SUPPORTS_DEBUG_PAGEALLOC
|
||||
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
|
||||
select HAVE_ARCH_WITHIN_STACK_FRAMES
|
||||
@@ -235,7 +235,7 @@ config PPC
|
||||
select HAVE_FUNCTION_DESCRIPTORS if PPC64_ELF_ABI_V1
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_FUNCTION_TRACER if PPC64 || (PPC32 && CC_IS_GCC)
|
||||
select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC
|
||||
select HAVE_GENERIC_VDSO
|
||||
select HAVE_HARDLOCKUP_DETECTOR_ARCH if PPC_BOOK3S_64 && SMP
|
||||
@@ -547,8 +547,9 @@ config LD_HEAD_STUB_CATCH
|
||||
If unsure, say "N".
|
||||
|
||||
config MPROFILE_KERNEL
|
||||
depends on PPC64 && CPU_LITTLE_ENDIAN && FUNCTION_TRACER
|
||||
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -I$(srctree)/include -D__KERNEL__)
|
||||
depends on PPC64_ELF_ABI_V2 && FUNCTION_TRACER
|
||||
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -mlittle-endian) if CPU_LITTLE_ENDIAN
|
||||
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -mbig-endian) if CPU_BIG_ENDIAN
|
||||
|
||||
config HOTPLUG_CPU
|
||||
bool "Support for enabling/disabling CPUs"
|
||||
@@ -624,10 +625,12 @@ config ARCH_HAS_KEXEC_PURGATORY
|
||||
def_bool KEXEC_FILE
|
||||
|
||||
config PPC64_BIG_ENDIAN_ELF_ABI_V2
|
||||
bool "Build big-endian kernel using ELF ABI V2 (EXPERIMENTAL)"
|
||||
# Option is available to BFD, but LLD does not support ELFv1 so this is
|
||||
# always true there.
|
||||
prompt "Build big-endian kernel using ELF ABI V2" if LD_IS_BFD && EXPERT
|
||||
def_bool y
|
||||
depends on PPC64 && CPU_BIG_ENDIAN
|
||||
depends on CC_HAS_ELFV2
|
||||
depends on LD_VERSION >= 22400 || LLD_VERSION >= 150000
|
||||
help
|
||||
This builds the kernel image using the "Power Architecture 64-Bit ELF
|
||||
V2 ABI Specification", which has a reduced stack overhead and faster
|
||||
@@ -638,8 +641,6 @@ config PPC64_BIG_ENDIAN_ELF_ABI_V2
|
||||
it is less well tested by kernel and toolchain. However some distros
|
||||
build userspace this way, and it can produce a functioning kernel.
|
||||
|
||||
This requires GCC and binutils 2.24 or newer.
|
||||
|
||||
config RELOCATABLE
|
||||
bool "Build a relocatable kernel"
|
||||
depends on PPC64 || (FLATMEM && (44x || PPC_85xx))
|
||||
|
||||
+8
-15
@@ -42,18 +42,13 @@ machine-$(CONFIG_PPC64) += 64
|
||||
machine-$(CONFIG_CPU_LITTLE_ENDIAN) += le
|
||||
UTS_MACHINE := $(subst $(space),,$(machine-y))
|
||||
|
||||
# XXX This needs to be before we override LD below
|
||||
ifdef CONFIG_PPC32
|
||||
KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
|
||||
else
|
||||
ifeq ($(call ld-ifversion, -ge, 22500, y),y)
|
||||
ifeq ($(CONFIG_PPC64)$(CONFIG_LD_IS_BFD),yy)
|
||||
# Have the linker provide sfpr if possible.
|
||||
# There is a corresponding test in arch/powerpc/lib/Makefile
|
||||
KBUILD_LDFLAGS_MODULE += --save-restore-funcs
|
||||
else
|
||||
KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
KBUILD_CFLAGS += -mlittle-endian
|
||||
@@ -166,7 +161,7 @@ asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1)
|
||||
KBUILD_CPPFLAGS += -I $(srctree)/arch/$(ARCH) $(asinstr)
|
||||
KBUILD_AFLAGS += $(AFLAGS-y)
|
||||
KBUILD_CFLAGS += $(call cc-option,-msoft-float)
|
||||
KBUILD_CFLAGS += -pipe $(CFLAGS-y)
|
||||
KBUILD_CFLAGS += $(CFLAGS-y)
|
||||
CPP = $(CC) -E $(KBUILD_CFLAGS)
|
||||
|
||||
CHECKFLAGS += -m$(BITS) -D__powerpc__ -D__powerpc$(BITS)__
|
||||
@@ -398,14 +393,12 @@ endif
|
||||
endif
|
||||
|
||||
PHONY += checkbin
|
||||
# Check toolchain versions:
|
||||
# - gcc-4.6 is the minimum kernel-wide version so nothing required.
|
||||
checkbin:
|
||||
@if test "x${CONFIG_LD_IS_LLD}" != "xy" -a \
|
||||
"x$(call ld-ifversion, -le, 22400, y)" = "xy" ; then \
|
||||
echo -n '*** binutils 2.24 miscompiles weak symbols ' ; \
|
||||
echo 'in some circumstances.' ; \
|
||||
echo '*** binutils 2.23 do not define the TOC symbol ' ; \
|
||||
echo -n '*** Please use a different binutils version.' ; \
|
||||
@if test "x${CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT}" = "xy" -a \
|
||||
"x${CONFIG_LD_IS_BFD}" = "xy" -a \
|
||||
"${CONFIG_LD_VERSION}" = "23700" ; then \
|
||||
echo -n '*** binutils 2.37 drops unused section symbols, which recordmcount ' ; \
|
||||
echo 'is unable to handle.' ; \
|
||||
echo '*** Please use a different binutils version.' ; \
|
||||
false ; \
|
||||
fi
|
||||
|
||||
+34
-37
@@ -32,47 +32,59 @@ else
|
||||
BOOTAR := $(AR)
|
||||
endif
|
||||
|
||||
BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||
-fno-strict-aliasing -O2 -msoft-float -mno-altivec -mno-vsx \
|
||||
$(call cc-option,-mno-spe) $(call cc-option,-mspe=no) \
|
||||
-pipe -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
|
||||
$(LINUXINCLUDE)
|
||||
|
||||
ifdef CONFIG_PPC64_BOOT_WRAPPER
|
||||
BOOTCFLAGS += -m64
|
||||
BOOTTARGETFLAGS += -m64
|
||||
BOOTTARGETFLAGS += -mabi=elfv2
|
||||
ifdef CONFIG_PPC64_ELF_ABI_V2
|
||||
BOOTCFLAGS += $(call cc-option,-mabi=elfv2)
|
||||
BOOTTARGETFLAGS += $(call cc-option,-mabi=elfv2)
|
||||
endif
|
||||
else
|
||||
BOOTCFLAGS += -m32
|
||||
BOOTTARGETFLAGS := -m32
|
||||
endif
|
||||
|
||||
ifdef CONFIG_TARGET_CPU_BOOL
|
||||
BOOTCFLAGS += -mcpu=$(CONFIG_TARGET_CPU)
|
||||
BOOTTARGETFLAGS += -mcpu=$(CONFIG_TARGET_CPU)
|
||||
else ifdef CONFIG_PPC64_BOOT_WRAPPER
|
||||
ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
BOOTCFLAGS += -mcpu=powerpc64le
|
||||
BOOTTARGETFLAGS += -mcpu=powerpc64le
|
||||
else
|
||||
BOOTCFLAGS += -mcpu=powerpc64
|
||||
BOOTTARGETFLAGS += -mcpu=powerpc64
|
||||
endif
|
||||
endif
|
||||
|
||||
BOOTCFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include)
|
||||
$(obj)/4xx.o: BOOTTARGETFLAGS += -mcpu=405
|
||||
$(obj)/ebony.o: BOOTTARGETFLAGS += -mcpu=440
|
||||
$(obj)/cuboot-hotfoot.o: BOOTTARGETFLAGS += -mcpu=405
|
||||
$(obj)/cuboot-taishan.o: BOOTTARGETFLAGS += -mcpu=440
|
||||
$(obj)/cuboot-katmai.o: BOOTTARGETFLAGS += -mcpu=440
|
||||
$(obj)/cuboot-acadia.o: BOOTTARGETFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-iss4xx.o: BOOTTARGETFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-currituck.o: BOOTTARGETFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-akebono.o: BOOTTARGETFLAGS += -mcpu=405
|
||||
|
||||
ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
BOOTCFLAGS += -mbig-endian
|
||||
BOOTTARGETFLAGS += -mbig-endian
|
||||
else
|
||||
BOOTCFLAGS += -mlittle-endian
|
||||
BOOTTARGETFLAGS += -mlittle-endian
|
||||
endif
|
||||
|
||||
BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -nostdinc
|
||||
BOOTCPPFLAGS := -nostdinc $(LINUXINCLUDE)
|
||||
BOOTCPPFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include)
|
||||
|
||||
BOOTCFLAGS := $(BOOTTARGETFLAGS) \
|
||||
-Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||
-fno-strict-aliasing -O2 \
|
||||
-msoft-float -mno-altivec -mno-vsx \
|
||||
$(call cc-option,-mno-prefixed) \
|
||||
$(call cc-option,-mno-pcrel) \
|
||||
$(call cc-option,-mno-mma) \
|
||||
$(call cc-option,-mno-spe) $(call cc-option,-mspe=no) \
|
||||
-fomit-frame-pointer -fno-builtin -fPIC
|
||||
|
||||
BOOTAFLAGS := $(BOOTTARGETFLAGS) -D__ASSEMBLY__
|
||||
|
||||
BOOTARFLAGS := -crD
|
||||
|
||||
BOOTCFLAGS += $(call cc-option,-mno-prefixed) \
|
||||
$(call cc-option,-mno-pcrel) \
|
||||
$(call cc-option,-mno-mma)
|
||||
|
||||
ifdef CONFIG_CC_IS_CLANG
|
||||
BOOTCFLAGS += $(CLANG_FLAGS)
|
||||
BOOTAFLAGS += $(CLANG_FLAGS)
|
||||
@@ -91,16 +103,6 @@ BOOTCFLAGS += -I$(objtree)/$(obj) -I$(srctree)/$(obj)
|
||||
|
||||
DTC_FLAGS ?= -p 1024
|
||||
|
||||
$(obj)/4xx.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
|
||||
$(obj)/cuboot-hotfoot.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=440
|
||||
$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=440
|
||||
$(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-currituck.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-akebono.o: BOOTCFLAGS += -mcpu=405
|
||||
|
||||
# The pre-boot decompressors pull in a lot of kernel headers and other source
|
||||
# files. This creates a bit of a dependency headache since we need to copy
|
||||
# these files into the build dir, fix up any includes and ensure that dependent
|
||||
@@ -224,10 +226,10 @@ clean-files := $(zlib-) $(zlibheader-) $(zliblinuxheader-) \
|
||||
empty.c zImage.coff.lds zImage.ps3.lds zImage.lds
|
||||
|
||||
quiet_cmd_bootcc = BOOTCC $@
|
||||
cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
|
||||
cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCPPFLAGS) $(BOOTCFLAGS) -c -o $@ $<
|
||||
|
||||
quiet_cmd_bootas = BOOTAS $@
|
||||
cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
|
||||
cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCPPFLAGS) $(BOOTAFLAGS) -c -o $@ $<
|
||||
|
||||
quiet_cmd_bootar = BOOTAR $@
|
||||
cmd_bootar = $(BOOTAR) $(BOOTARFLAGS) $@.$$$$ $(real-prereqs); mv $@.$$$$ $@
|
||||
@@ -340,11 +342,6 @@ image-$(CONFIG_MPC834x_ITX) += cuImage.mpc8349emitx \
|
||||
image-$(CONFIG_ASP834x) += dtbImage.asp834x-redboot
|
||||
|
||||
# Board ports in arch/powerpc/platform/85xx/Kconfig
|
||||
image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads
|
||||
image-$(CONFIG_MPC8560_ADS) += cuImage.mpc8560ads
|
||||
image-$(CONFIG_MPC85xx_CDS) += cuImage.mpc8541cds \
|
||||
cuImage.mpc8548cds_32b \
|
||||
cuImage.mpc8555cds
|
||||
image-$(CONFIG_MPC85xx_MDS) += cuImage.mpc8568mds
|
||||
image-$(CONFIG_MPC85xx_DS) += cuImage.mpc8544ds \
|
||||
cuImage.mpc8572ds
|
||||
|
||||
@@ -1,355 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* MPC8540 ADS Device Tree Source
|
||||
*
|
||||
* Copyright 2006, 2008 Freescale Semiconductor Inc.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "e500v1_power_isa.dtsi"
|
||||
|
||||
/ {
|
||||
model = "MPC8540ADS";
|
||||
compatible = "MPC8540ADS", "MPC85xxADS";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
aliases {
|
||||
ethernet0 = &enet0;
|
||||
ethernet1 = &enet1;
|
||||
ethernet2 = &enet2;
|
||||
serial0 = &serial0;
|
||||
serial1 = &serial1;
|
||||
pci0 = &pci0;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,8540@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x0>;
|
||||
d-cache-line-size = <32>; // 32 bytes
|
||||
i-cache-line-size = <32>; // 32 bytes
|
||||
d-cache-size = <0x8000>; // L1, 32K
|
||||
i-cache-size = <0x8000>; // L1, 32K
|
||||
timebase-frequency = <0>; // 33 MHz, from uboot
|
||||
bus-frequency = <0>; // 166 MHz
|
||||
clock-frequency = <0>; // 825 MHz, from uboot
|
||||
next-level-cache = <&L2>;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>; // 128M at 0x0
|
||||
};
|
||||
|
||||
soc8540@e0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
ecm-law@0 {
|
||||
compatible = "fsl,ecm-law";
|
||||
reg = <0x0 0x1000>;
|
||||
fsl,num-laws = <8>;
|
||||
};
|
||||
|
||||
ecm@1000 {
|
||||
compatible = "fsl,mpc8540-ecm", "fsl,ecm";
|
||||
reg = <0x1000 0x1000>;
|
||||
interrupts = <17 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
memory-controller@2000 {
|
||||
compatible = "fsl,mpc8540-memory-controller";
|
||||
reg = <0x2000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <18 2>;
|
||||
};
|
||||
|
||||
L2: l2-cache-controller@20000 {
|
||||
compatible = "fsl,mpc8540-l2-cache-controller";
|
||||
reg = <0x20000 0x1000>;
|
||||
cache-line-size = <32>; // 32 bytes
|
||||
cache-size = <0x40000>; // L2, 256K
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
dma@21300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc8540-dma", "fsl,eloplus-dma";
|
||||
reg = <0x21300 0x4>;
|
||||
ranges = <0x0 0x21100 0x200>;
|
||||
cell-index = <0>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,mpc8540-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
cell-index = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <20 2>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,mpc8540-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
cell-index = <1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <21 2>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,mpc8540-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
cell-index = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <22 2>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,mpc8540-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
cell-index = <3>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <23 2>;
|
||||
};
|
||||
};
|
||||
|
||||
enet0: ethernet@24000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <0>;
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x24000 0x1000>;
|
||||
ranges = <0x0 0x24000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <29 2 30 2 34 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi0>;
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-mdio";
|
||||
reg = <0x520 0x20>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <5 1>;
|
||||
reg = <0x0>;
|
||||
};
|
||||
phy1: ethernet-phy@1 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <5 1>;
|
||||
reg = <0x1>;
|
||||
};
|
||||
phy3: ethernet-phy@3 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <7 1>;
|
||||
reg = <0x3>;
|
||||
};
|
||||
tbi0: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
enet1: ethernet@25000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <1>;
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x25000 0x1000>;
|
||||
ranges = <0x0 0x25000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <35 2 36 2 40 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi1>;
|
||||
phy-handle = <&phy1>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-tbi";
|
||||
reg = <0x520 0x20>;
|
||||
|
||||
tbi1: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
enet2: ethernet@26000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <2>;
|
||||
device_type = "network";
|
||||
model = "FEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x26000 0x1000>;
|
||||
ranges = <0x0 0x26000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <41 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi2>;
|
||||
phy-handle = <&phy3>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-tbi";
|
||||
reg = <0x520 0x20>;
|
||||
|
||||
tbi2: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "fsl,ns16550", "ns16550";
|
||||
reg = <0x4500 0x100>; // reg base, size
|
||||
clock-frequency = <0>; // should we fill in in uboot?
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial1: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "fsl,ns16550", "ns16550";
|
||||
reg = <0x4600 0x100>; // reg base, size
|
||||
clock-frequency = <0>; // should we fill in in uboot?
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
mpic: pic@40000 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x40000 0x40000>;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
};
|
||||
};
|
||||
|
||||
pci0: pci@e0008000 {
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x02 */
|
||||
0x1000 0x0 0x0 0x1 &mpic 0x1 0x1
|
||||
0x1000 0x0 0x0 0x2 &mpic 0x2 0x1
|
||||
0x1000 0x0 0x0 0x3 &mpic 0x3 0x1
|
||||
0x1000 0x0 0x0 0x4 &mpic 0x4 0x1
|
||||
|
||||
/* IDSEL 0x03 */
|
||||
0x1800 0x0 0x0 0x1 &mpic 0x4 0x1
|
||||
0x1800 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x1800 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x1800 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x04 */
|
||||
0x2000 0x0 0x0 0x1 &mpic 0x3 0x1
|
||||
0x2000 0x0 0x0 0x2 &mpic 0x4 0x1
|
||||
0x2000 0x0 0x0 0x3 &mpic 0x1 0x1
|
||||
0x2000 0x0 0x0 0x4 &mpic 0x2 0x1
|
||||
|
||||
/* IDSEL 0x05 */
|
||||
0x2800 0x0 0x0 0x1 &mpic 0x2 0x1
|
||||
0x2800 0x0 0x0 0x2 &mpic 0x3 0x1
|
||||
0x2800 0x0 0x0 0x3 &mpic 0x4 0x1
|
||||
0x2800 0x0 0x0 0x4 &mpic 0x1 0x1
|
||||
|
||||
/* IDSEL 0x0c */
|
||||
0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
|
||||
0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
|
||||
0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
|
||||
0x6000 0x0 0x0 0x4 &mpic 0x4 0x1
|
||||
|
||||
/* IDSEL 0x0d */
|
||||
0x6800 0x0 0x0 0x1 &mpic 0x4 0x1
|
||||
0x6800 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x6800 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x6800 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x0e */
|
||||
0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
|
||||
0x7000 0x0 0x0 0x2 &mpic 0x4 0x1
|
||||
0x7000 0x0 0x0 0x3 &mpic 0x1 0x1
|
||||
0x7000 0x0 0x0 0x4 &mpic 0x2 0x1
|
||||
|
||||
/* IDSEL 0x0f */
|
||||
0x7800 0x0 0x0 0x1 &mpic 0x2 0x1
|
||||
0x7800 0x0 0x0 0x2 &mpic 0x3 0x1
|
||||
0x7800 0x0 0x0 0x3 &mpic 0x4 0x1
|
||||
0x7800 0x0 0x0 0x4 &mpic 0x1 0x1
|
||||
|
||||
/* IDSEL 0x12 */
|
||||
0x9000 0x0 0x0 0x1 &mpic 0x1 0x1
|
||||
0x9000 0x0 0x0 0x2 &mpic 0x2 0x1
|
||||
0x9000 0x0 0x0 0x3 &mpic 0x3 0x1
|
||||
0x9000 0x0 0x0 0x4 &mpic 0x4 0x1
|
||||
|
||||
/* IDSEL 0x13 */
|
||||
0x9800 0x0 0x0 0x1 &mpic 0x4 0x1
|
||||
0x9800 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x9800 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x9800 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x14 */
|
||||
0xa000 0x0 0x0 0x1 &mpic 0x3 0x1
|
||||
0xa000 0x0 0x0 0x2 &mpic 0x4 0x1
|
||||
0xa000 0x0 0x0 0x3 &mpic 0x1 0x1
|
||||
0xa000 0x0 0x0 0x4 &mpic 0x2 0x1
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
0xa800 0x0 0x0 0x1 &mpic 0x2 0x1
|
||||
0xa800 0x0 0x0 0x2 &mpic 0x3 0x1
|
||||
0xa800 0x0 0x0 0x3 &mpic 0x4 0x1
|
||||
0xa800 0x0 0x0 0x4 &mpic 0x1 0x1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <24 2>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
|
||||
clock-frequency = <66666666>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xe0008000 0x1000>;
|
||||
compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
|
||||
device_type = "pci";
|
||||
};
|
||||
};
|
||||
@@ -1,375 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* MPC8541 CDS Device Tree Source
|
||||
*
|
||||
* Copyright 2006, 2008 Freescale Semiconductor Inc.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "e500v1_power_isa.dtsi"
|
||||
|
||||
/ {
|
||||
model = "MPC8541CDS";
|
||||
compatible = "MPC8541CDS", "MPC85xxCDS";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
aliases {
|
||||
ethernet0 = &enet0;
|
||||
ethernet1 = &enet1;
|
||||
serial0 = &serial0;
|
||||
serial1 = &serial1;
|
||||
pci0 = &pci0;
|
||||
pci1 = &pci1;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,8541@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x0>;
|
||||
d-cache-line-size = <32>; // 32 bytes
|
||||
i-cache-line-size = <32>; // 32 bytes
|
||||
d-cache-size = <0x8000>; // L1, 32K
|
||||
i-cache-size = <0x8000>; // L1, 32K
|
||||
timebase-frequency = <0>; // 33 MHz, from uboot
|
||||
bus-frequency = <0>; // 166 MHz
|
||||
clock-frequency = <0>; // 825 MHz, from uboot
|
||||
next-level-cache = <&L2>;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>; // 128M at 0x0
|
||||
};
|
||||
|
||||
soc8541@e0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
ecm-law@0 {
|
||||
compatible = "fsl,ecm-law";
|
||||
reg = <0x0 0x1000>;
|
||||
fsl,num-laws = <8>;
|
||||
};
|
||||
|
||||
ecm@1000 {
|
||||
compatible = "fsl,mpc8541-ecm", "fsl,ecm";
|
||||
reg = <0x1000 0x1000>;
|
||||
interrupts = <17 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
memory-controller@2000 {
|
||||
compatible = "fsl,mpc8541-memory-controller";
|
||||
reg = <0x2000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <18 2>;
|
||||
};
|
||||
|
||||
L2: l2-cache-controller@20000 {
|
||||
compatible = "fsl,mpc8541-l2-cache-controller";
|
||||
reg = <0x20000 0x1000>;
|
||||
cache-line-size = <32>; // 32 bytes
|
||||
cache-size = <0x40000>; // L2, 256K
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
dma@21300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc8541-dma", "fsl,eloplus-dma";
|
||||
reg = <0x21300 0x4>;
|
||||
ranges = <0x0 0x21100 0x200>;
|
||||
cell-index = <0>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,mpc8541-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
cell-index = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <20 2>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,mpc8541-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
cell-index = <1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <21 2>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,mpc8541-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
cell-index = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <22 2>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,mpc8541-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
cell-index = <3>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <23 2>;
|
||||
};
|
||||
};
|
||||
|
||||
enet0: ethernet@24000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <0>;
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x24000 0x1000>;
|
||||
ranges = <0x0 0x24000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <29 2 30 2 34 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi0>;
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-mdio";
|
||||
reg = <0x520 0x20>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <5 1>;
|
||||
reg = <0x0>;
|
||||
};
|
||||
phy1: ethernet-phy@1 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <5 1>;
|
||||
reg = <0x1>;
|
||||
};
|
||||
tbi0: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
enet1: ethernet@25000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <1>;
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x25000 0x1000>;
|
||||
ranges = <0x0 0x25000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <35 2 36 2 40 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi1>;
|
||||
phy-handle = <&phy1>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-tbi";
|
||||
reg = <0x520 0x20>;
|
||||
|
||||
tbi1: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "fsl,ns16550", "ns16550";
|
||||
reg = <0x4500 0x100>; // reg base, size
|
||||
clock-frequency = <0>; // should we fill in in uboot?
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial1: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "fsl,ns16550", "ns16550";
|
||||
reg = <0x4600 0x100>; // reg base, size
|
||||
clock-frequency = <0>; // should we fill in in uboot?
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
crypto@30000 {
|
||||
compatible = "fsl,sec2.0";
|
||||
reg = <0x30000 0x10000>;
|
||||
interrupts = <45 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
fsl,num-channels = <4>;
|
||||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0x7e>;
|
||||
fsl,descriptor-types-mask = <0x01010ebf>;
|
||||
};
|
||||
|
||||
mpic: pic@40000 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x40000 0x40000>;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
};
|
||||
|
||||
cpm@919c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc8541-cpm", "fsl,cpm2";
|
||||
reg = <0x919c0 0x30>;
|
||||
ranges;
|
||||
|
||||
muram@80000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x80000 0x10000>;
|
||||
|
||||
data@0 {
|
||||
compatible = "fsl,cpm-muram-data";
|
||||
reg = <0x0 0x2000 0x9000 0x1000>;
|
||||
};
|
||||
};
|
||||
|
||||
brg@919f0 {
|
||||
compatible = "fsl,mpc8541-brg",
|
||||
"fsl,cpm2-brg",
|
||||
"fsl,cpm-brg";
|
||||
reg = <0x919f0 0x10 0x915f0 0x10>;
|
||||
};
|
||||
|
||||
cpmpic: pic@90c00 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <46 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
reg = <0x90c00 0x80>;
|
||||
compatible = "fsl,mpc8541-cpm-pic", "fsl,cpm2-pic";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pci0: pci@e0008000 {
|
||||
interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x10 */
|
||||
0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
|
||||
0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x11 */
|
||||
0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
|
||||
0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x12 (Slot 1) */
|
||||
0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
|
||||
0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x13 (Slot 2) */
|
||||
0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
|
||||
0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
|
||||
0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
|
||||
0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
|
||||
|
||||
/* IDSEL 0x14 (Slot 3) */
|
||||
0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
|
||||
0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
|
||||
0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
|
||||
0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
|
||||
|
||||
/* IDSEL 0x15 (Slot 4) */
|
||||
0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
|
||||
0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
|
||||
0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
|
||||
0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
|
||||
|
||||
/* Bus 1 (Tundra Bridge) */
|
||||
/* IDSEL 0x12 (ISA bridge) */
|
||||
0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
|
||||
0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <24 2>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
|
||||
clock-frequency = <66666666>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xe0008000 0x1000>;
|
||||
compatible = "fsl,mpc8540-pci";
|
||||
device_type = "pci";
|
||||
|
||||
i8259@19000 {
|
||||
interrupt-controller;
|
||||
device_type = "interrupt-controller";
|
||||
reg = <0x19000 0x0 0x0 0x0 0x1>;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
compatible = "chrp,iic";
|
||||
interrupts = <1>;
|
||||
interrupt-parent = <&pci0>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pci@e0009000 {
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
|
||||
0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
|
||||
0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
|
||||
0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <25 2>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
|
||||
clock-frequency = <66666666>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xe0009000 0x1000>;
|
||||
compatible = "fsl,mpc8540-pci";
|
||||
device_type = "pci";
|
||||
};
|
||||
};
|
||||
@@ -1,302 +0,0 @@
|
||||
/*
|
||||
* MPC8548CDS Device Tree Source stub (no addresses or top-level ranges)
|
||||
*
|
||||
* Copyright 2012 Freescale Semiconductor Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Freescale Semiconductor nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation, either version 2 of that License or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
&board_lbc {
|
||||
nor@0,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x0 0x0 0x01000000>;
|
||||
bank-width = <2>;
|
||||
device-width = <2>;
|
||||
|
||||
partition@0 {
|
||||
reg = <0x0 0x0b00000>;
|
||||
label = "ramdisk-nor";
|
||||
};
|
||||
|
||||
partition@300000 {
|
||||
reg = <0x0b00000 0x0400000>;
|
||||
label = "kernel-nor";
|
||||
};
|
||||
|
||||
partition@700000 {
|
||||
reg = <0x0f00000 0x060000>;
|
||||
label = "dtb-nor";
|
||||
};
|
||||
|
||||
partition@760000 {
|
||||
reg = <0x0f60000 0x020000>;
|
||||
label = "env-nor";
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@780000 {
|
||||
reg = <0x0f80000 0x080000>;
|
||||
label = "u-boot-nor";
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
|
||||
board-control@1,0 {
|
||||
compatible = "fsl,mpc8548cds-fpga";
|
||||
reg = <0x1 0x0 0x1000>;
|
||||
};
|
||||
};
|
||||
|
||||
&board_soc {
|
||||
i2c@3000 {
|
||||
eeprom@50 {
|
||||
compatible = "atmel,24c64";
|
||||
reg = <0x50>;
|
||||
};
|
||||
|
||||
eeprom@56 {
|
||||
compatible = "atmel,24c64";
|
||||
reg = <0x56>;
|
||||
};
|
||||
|
||||
eeprom@57 {
|
||||
compatible = "atmel,24c64";
|
||||
reg = <0x57>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
eeprom@50 {
|
||||
compatible = "atmel,24c64";
|
||||
reg = <0x50>;
|
||||
};
|
||||
};
|
||||
|
||||
enet0: ethernet@24000 {
|
||||
tbi-handle = <&tbi0>;
|
||||
phy-handle = <&phy0>;
|
||||
};
|
||||
|
||||
mdio@24520 {
|
||||
phy0: ethernet-phy@0 {
|
||||
interrupts = <5 1 0 0>;
|
||||
reg = <0x0>;
|
||||
};
|
||||
phy1: ethernet-phy@1 {
|
||||
interrupts = <5 1 0 0>;
|
||||
reg = <0x1>;
|
||||
};
|
||||
phy2: ethernet-phy@2 {
|
||||
interrupts = <5 1 0 0>;
|
||||
reg = <0x2>;
|
||||
};
|
||||
phy3: ethernet-phy@3 {
|
||||
interrupts = <5 1 0 0>;
|
||||
reg = <0x3>;
|
||||
};
|
||||
tbi0: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
|
||||
enet1: ethernet@25000 {
|
||||
tbi-handle = <&tbi1>;
|
||||
phy-handle = <&phy1>;
|
||||
};
|
||||
|
||||
mdio@25520 {
|
||||
tbi1: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
|
||||
enet2: ethernet@26000 {
|
||||
tbi-handle = <&tbi2>;
|
||||
phy-handle = <&phy2>;
|
||||
};
|
||||
|
||||
mdio@26520 {
|
||||
tbi2: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
|
||||
enet3: ethernet@27000 {
|
||||
tbi-handle = <&tbi3>;
|
||||
phy-handle = <&phy3>;
|
||||
};
|
||||
|
||||
mdio@27520 {
|
||||
tbi3: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&board_pci0 {
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
/* IDSEL 0x4 (PCIX Slot 2) */
|
||||
0x2000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
|
||||
0x2000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0x2000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0x2000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
|
||||
|
||||
/* IDSEL 0x5 (PCIX Slot 3) */
|
||||
0x2800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
|
||||
0x2800 0x0 0x0 0x2 &mpic 0x2 0x1 0 0
|
||||
0x2800 0x0 0x0 0x3 &mpic 0x3 0x1 0 0
|
||||
0x2800 0x0 0x0 0x4 &mpic 0x0 0x1 0 0
|
||||
|
||||
/* IDSEL 0x6 (PCIX Slot 4) */
|
||||
0x3000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
|
||||
0x3000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
|
||||
0x3000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
|
||||
0x3000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
|
||||
|
||||
/* IDSEL 0x8 (PCIX Slot 5) */
|
||||
0x4000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
|
||||
0x4000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0x4000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0x4000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
|
||||
|
||||
/* IDSEL 0xC (Tsi310 bridge) */
|
||||
0x6000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
|
||||
0x6000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0x6000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0x6000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
|
||||
|
||||
/* IDSEL 0x14 (Slot 2) */
|
||||
0xa000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
|
||||
0xa000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0xa000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0xa000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
|
||||
|
||||
/* IDSEL 0x15 (Slot 3) */
|
||||
0xa800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
|
||||
0xa800 0x0 0x0 0x2 &mpic 0x2 0x1 0 0
|
||||
0xa800 0x0 0x0 0x3 &mpic 0x3 0x1 0 0
|
||||
0xa800 0x0 0x0 0x4 &mpic 0x0 0x1 0 0
|
||||
|
||||
/* IDSEL 0x16 (Slot 4) */
|
||||
0xb000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
|
||||
0xb000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
|
||||
0xb000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
|
||||
0xb000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
|
||||
|
||||
/* IDSEL 0x18 (Slot 5) */
|
||||
0xc000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
|
||||
0xc000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0xc000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0xc000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
|
||||
|
||||
/* IDSEL 0x1C (Tsi310 bridge PCI primary) */
|
||||
0xe000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
|
||||
0xe000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0xe000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0xe000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>;
|
||||
|
||||
pci_bridge@1c {
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x00 (PrPMC Site) */
|
||||
0000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
|
||||
0000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
|
||||
|
||||
/* IDSEL 0x04 (VIA chip) */
|
||||
0x2000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
|
||||
0x2000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0x2000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0x2000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
|
||||
|
||||
/* IDSEL 0x05 (8139) */
|
||||
0x2800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
|
||||
|
||||
/* IDSEL 0x06 (Slot 6) */
|
||||
0x3000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
|
||||
0x3000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
|
||||
0x3000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
|
||||
0x3000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
|
||||
|
||||
/* IDESL 0x07 (Slot 7) */
|
||||
0x3800 0x0 0x0 0x1 &mpic 0x3 0x1 0 0
|
||||
0x3800 0x0 0x0 0x2 &mpic 0x0 0x1 0 0
|
||||
0x3800 0x0 0x0 0x3 &mpic 0x1 0x1 0 0
|
||||
0x3800 0x0 0x0 0x4 &mpic 0x2 0x1 0 0>;
|
||||
|
||||
reg = <0xe000 0x0 0x0 0x0 0x0>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
ranges = <0x2000000 0x0 0x80000000
|
||||
0x2000000 0x0 0x80000000
|
||||
0x0 0x20000000
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x80000>;
|
||||
clock-frequency = <33333333>;
|
||||
|
||||
isa@4 {
|
||||
device_type = "isa";
|
||||
#interrupt-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
#address-cells = <2>;
|
||||
reg = <0x2000 0x0 0x0 0x0 0x0>;
|
||||
ranges = <0x1 0x0 0x1000000 0x0 0x0 0x1000>;
|
||||
interrupt-parent = <&i8259>;
|
||||
|
||||
i8259: interrupt-controller@20 {
|
||||
interrupt-controller;
|
||||
device_type = "interrupt-controller";
|
||||
reg = <0x1 0x20 0x2
|
||||
0x1 0xa0 0x2
|
||||
0x1 0x4d0 0x2>;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
compatible = "chrp,iic";
|
||||
interrupts = <0 1 0 0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
rtc@70 {
|
||||
compatible = "pnpPNP,b00";
|
||||
reg = <0x1 0x70 0x2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* MPC8548 CDS Device Tree Source (32-bit address map)
|
||||
*
|
||||
* Copyright 2006, 2008, 2011-2012 Freescale Semiconductor Inc.
|
||||
*/
|
||||
|
||||
/include/ "mpc8548si-pre.dtsi"
|
||||
|
||||
/ {
|
||||
model = "MPC8548CDS";
|
||||
compatible = "MPC8548CDS", "MPC85xxCDS";
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0 0 0x0 0x8000000>; // 128M at 0x0
|
||||
};
|
||||
|
||||
board_lbc: lbc: localbus@e0005000 {
|
||||
reg = <0 0xe0005000 0 0x1000>;
|
||||
|
||||
ranges = <0x0 0x0 0x0 0xff000000 0x01000000
|
||||
0x1 0x0 0x0 0xf8004000 0x00001000>;
|
||||
|
||||
};
|
||||
|
||||
board_soc: soc: soc8548@e0000000 {
|
||||
ranges = <0 0x0 0xe0000000 0x100000>;
|
||||
};
|
||||
|
||||
board_pci0: pci0: pci@e0008000 {
|
||||
reg = <0 0xe0008000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x10000000
|
||||
0x1000000 0x0 0x00000000 0 0xe2000000 0x0 0x800000>;
|
||||
clock-frequency = <66666666>;
|
||||
};
|
||||
|
||||
pci1: pci@e0009000 {
|
||||
reg = <0 0xe0009000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0x90000000 0 0x90000000 0x0 0x10000000
|
||||
0x1000000 0x0 0x00000000 0 0xe2800000 0x0 0x800000>;
|
||||
clock-frequency = <66666666>;
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 0 0
|
||||
0xa800 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0xa800 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0xa800 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>;
|
||||
};
|
||||
|
||||
pci2: pcie@e000a000 {
|
||||
reg = <0 0xe000a000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xe3000000 0x0 0x100000>;
|
||||
pcie@0 {
|
||||
ranges = <0x2000000 0x0 0xa0000000
|
||||
0x2000000 0x0 0xa0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
|
||||
rio: rapidio@e00c0000 {
|
||||
reg = <0x0 0xe00c0000 0x0 0x20000>;
|
||||
port1 {
|
||||
ranges = <0x0 0x0 0x0 0xc0000000 0x0 0x20000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* mpc8548cds.dtsi must be last to ensure board_pci0 overrides pci0 settings
|
||||
* for interrupt-map & interrupt-map-mask.
|
||||
*/
|
||||
|
||||
/include/ "mpc8548si-post.dtsi"
|
||||
/include/ "mpc8548cds.dtsi"
|
||||
@@ -1,82 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* MPC8548 CDS Device Tree Source (36-bit address map)
|
||||
*
|
||||
* Copyright 2012 Freescale Semiconductor Inc.
|
||||
*/
|
||||
|
||||
/include/ "mpc8548si-pre.dtsi"
|
||||
|
||||
/ {
|
||||
model = "MPC8548CDS";
|
||||
compatible = "MPC8548CDS", "MPC85xxCDS";
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0 0 0x0 0x8000000>; // 128M at 0x0
|
||||
};
|
||||
|
||||
board_lbc: lbc: localbus@fe0005000 {
|
||||
reg = <0xf 0xe0005000 0 0x1000>;
|
||||
|
||||
ranges = <0x0 0x0 0xf 0xff000000 0x01000000
|
||||
0x1 0x0 0xf 0xf8004000 0x00001000>;
|
||||
|
||||
};
|
||||
|
||||
board_soc: soc: soc8548@fe0000000 {
|
||||
ranges = <0 0xf 0xe0000000 0x100000>;
|
||||
};
|
||||
|
||||
board_pci0: pci0: pci@fe0008000 {
|
||||
reg = <0xf 0xe0008000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x10000000
|
||||
0x1000000 0x0 0x00000000 0xf 0xe2000000 0x0 0x800000>;
|
||||
clock-frequency = <66666666>;
|
||||
};
|
||||
|
||||
pci1: pci@fe0009000 {
|
||||
reg = <0xf 0xe0009000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0xe0000000 0xc 0x10000000 0x0 0x10000000
|
||||
0x1000000 0x0 0x00000000 0xf 0xe2800000 0x0 0x800000>;
|
||||
clock-frequency = <66666666>;
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 0 0
|
||||
0xa800 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
|
||||
0xa800 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
|
||||
0xa800 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>;
|
||||
};
|
||||
|
||||
pci2: pcie@fe000a000 {
|
||||
reg = <0xf 0xe000a000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0xf 0xe3000000 0x0 0x100000>;
|
||||
pcie@0 {
|
||||
ranges = <0x2000000 0x0 0xa0000000
|
||||
0x2000000 0x0 0xa0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
|
||||
rio: rapidio@fe00c0000 {
|
||||
reg = <0xf 0xe00c0000 0x0 0x20000>;
|
||||
port1 {
|
||||
ranges = <0x0 0x0 0xc 0x40000000 0x0 0x20000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* mpc8548cds.dtsi must be last to ensure board_pci0 overrides pci0 settings
|
||||
* for interrupt-map & interrupt-map-mask.
|
||||
*/
|
||||
|
||||
/include/ "mpc8548si-post.dtsi"
|
||||
/include/ "mpc8548cds.dtsi"
|
||||
@@ -1,375 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* MPC8555 CDS Device Tree Source
|
||||
*
|
||||
* Copyright 2006, 2008 Freescale Semiconductor Inc.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "e500v1_power_isa.dtsi"
|
||||
|
||||
/ {
|
||||
model = "MPC8555CDS";
|
||||
compatible = "MPC8555CDS", "MPC85xxCDS";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
aliases {
|
||||
ethernet0 = &enet0;
|
||||
ethernet1 = &enet1;
|
||||
serial0 = &serial0;
|
||||
serial1 = &serial1;
|
||||
pci0 = &pci0;
|
||||
pci1 = &pci1;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,8555@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0x0>;
|
||||
d-cache-line-size = <32>; // 32 bytes
|
||||
i-cache-line-size = <32>; // 32 bytes
|
||||
d-cache-size = <0x8000>; // L1, 32K
|
||||
i-cache-size = <0x8000>; // L1, 32K
|
||||
timebase-frequency = <0>; // 33 MHz, from uboot
|
||||
bus-frequency = <0>; // 166 MHz
|
||||
clock-frequency = <0>; // 825 MHz, from uboot
|
||||
next-level-cache = <&L2>;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>; // 128M at 0x0
|
||||
};
|
||||
|
||||
soc8555@e0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
ecm-law@0 {
|
||||
compatible = "fsl,ecm-law";
|
||||
reg = <0x0 0x1000>;
|
||||
fsl,num-laws = <8>;
|
||||
};
|
||||
|
||||
ecm@1000 {
|
||||
compatible = "fsl,mpc8555-ecm", "fsl,ecm";
|
||||
reg = <0x1000 0x1000>;
|
||||
interrupts = <17 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
memory-controller@2000 {
|
||||
compatible = "fsl,mpc8555-memory-controller";
|
||||
reg = <0x2000 0x1000>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <18 2>;
|
||||
};
|
||||
|
||||
L2: l2-cache-controller@20000 {
|
||||
compatible = "fsl,mpc8555-l2-cache-controller";
|
||||
reg = <0x20000 0x1000>;
|
||||
cache-line-size = <32>; // 32 bytes
|
||||
cache-size = <0x40000>; // L2, 256K
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <16 2>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
dma@21300 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc8555-dma", "fsl,eloplus-dma";
|
||||
reg = <0x21300 0x4>;
|
||||
ranges = <0x0 0x21100 0x200>;
|
||||
cell-index = <0>;
|
||||
dma-channel@0 {
|
||||
compatible = "fsl,mpc8555-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x0 0x80>;
|
||||
cell-index = <0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <20 2>;
|
||||
};
|
||||
dma-channel@80 {
|
||||
compatible = "fsl,mpc8555-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x80 0x80>;
|
||||
cell-index = <1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <21 2>;
|
||||
};
|
||||
dma-channel@100 {
|
||||
compatible = "fsl,mpc8555-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x100 0x80>;
|
||||
cell-index = <2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <22 2>;
|
||||
};
|
||||
dma-channel@180 {
|
||||
compatible = "fsl,mpc8555-dma-channel",
|
||||
"fsl,eloplus-dma-channel";
|
||||
reg = <0x180 0x80>;
|
||||
cell-index = <3>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <23 2>;
|
||||
};
|
||||
};
|
||||
|
||||
enet0: ethernet@24000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <0>;
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x24000 0x1000>;
|
||||
ranges = <0x0 0x24000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <29 2 30 2 34 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi0>;
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-mdio";
|
||||
reg = <0x520 0x20>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <5 1>;
|
||||
reg = <0x0>;
|
||||
};
|
||||
phy1: ethernet-phy@1 {
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <5 1>;
|
||||
reg = <0x1>;
|
||||
};
|
||||
tbi0: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
enet1: ethernet@25000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
cell-index = <1>;
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <0x25000 0x1000>;
|
||||
ranges = <0x0 0x25000 0x1000>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <35 2 36 2 40 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
tbi-handle = <&tbi1>;
|
||||
phy-handle = <&phy1>;
|
||||
|
||||
mdio@520 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,gianfar-tbi";
|
||||
reg = <0x520 0x20>;
|
||||
|
||||
tbi1: tbi-phy@11 {
|
||||
reg = <0x11>;
|
||||
device_type = "tbi-phy";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
serial0: serial@4500 {
|
||||
cell-index = <0>;
|
||||
device_type = "serial";
|
||||
compatible = "fsl,ns16550", "ns16550";
|
||||
reg = <0x4500 0x100>; // reg base, size
|
||||
clock-frequency = <0>; // should we fill in in uboot?
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
serial1: serial@4600 {
|
||||
cell-index = <1>;
|
||||
device_type = "serial";
|
||||
compatible = "fsl,ns16550", "ns16550";
|
||||
reg = <0x4600 0x100>; // reg base, size
|
||||
clock-frequency = <0>; // should we fill in in uboot?
|
||||
interrupts = <42 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
};
|
||||
|
||||
crypto@30000 {
|
||||
compatible = "fsl,sec2.0";
|
||||
reg = <0x30000 0x10000>;
|
||||
interrupts = <45 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
fsl,num-channels = <4>;
|
||||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0x7e>;
|
||||
fsl,descriptor-types-mask = <0x01010ebf>;
|
||||
};
|
||||
|
||||
mpic: pic@40000 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0x40000 0x40000>;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
};
|
||||
|
||||
cpm@919c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc8555-cpm", "fsl,cpm2";
|
||||
reg = <0x919c0 0x30>;
|
||||
ranges;
|
||||
|
||||
muram@80000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x80000 0x10000>;
|
||||
|
||||
data@0 {
|
||||
compatible = "fsl,cpm-muram-data";
|
||||
reg = <0x0 0x2000 0x9000 0x1000>;
|
||||
};
|
||||
};
|
||||
|
||||
brg@919f0 {
|
||||
compatible = "fsl,mpc8555-brg",
|
||||
"fsl,cpm2-brg",
|
||||
"fsl,cpm-brg";
|
||||
reg = <0x919f0 0x10 0x915f0 0x10>;
|
||||
};
|
||||
|
||||
cpmpic: pic@90c00 {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <46 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
reg = <0x90c00 0x80>;
|
||||
compatible = "fsl,mpc8555-cpm-pic", "fsl,cpm2-pic";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pci0: pci@e0008000 {
|
||||
interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x10 */
|
||||
0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
|
||||
0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x11 */
|
||||
0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
|
||||
0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x12 (Slot 1) */
|
||||
0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
|
||||
0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
|
||||
|
||||
/* IDSEL 0x13 (Slot 2) */
|
||||
0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
|
||||
0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
|
||||
0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
|
||||
0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
|
||||
|
||||
/* IDSEL 0x14 (Slot 3) */
|
||||
0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
|
||||
0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
|
||||
0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
|
||||
0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
|
||||
|
||||
/* IDSEL 0x15 (Slot 4) */
|
||||
0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
|
||||
0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
|
||||
0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
|
||||
0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
|
||||
|
||||
/* Bus 1 (Tundra Bridge) */
|
||||
/* IDSEL 0x12 (ISA bridge) */
|
||||
0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
|
||||
0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
|
||||
0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
|
||||
0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <24 2>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
|
||||
clock-frequency = <66666666>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xe0008000 0x1000>;
|
||||
compatible = "fsl,mpc8540-pci";
|
||||
device_type = "pci";
|
||||
|
||||
i8259@19000 {
|
||||
interrupt-controller;
|
||||
device_type = "interrupt-controller";
|
||||
reg = <0x19000 0x0 0x0 0x0 0x1>;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
compatible = "chrp,iic";
|
||||
interrupts = <1>;
|
||||
interrupt-parent = <&pci0>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pci@e0009000 {
|
||||
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
|
||||
0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
|
||||
0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
|
||||
0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
|
||||
interrupt-parent = <&mpic>;
|
||||
interrupts = <25 2>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
|
||||
clock-frequency = <66666666>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <0xe0009000 0x1000>;
|
||||
compatible = "fsl,mpc8540-pci";
|
||||
device_type = "pci";
|
||||
};
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user