mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 14:12:06 +00:00
Add partial Loongarch architecture code
This is the majority of the loongarch architecture code, including the final system call interface and all core functionality. It still misses three sets of peripheral but vital patches to add support for other subsystems, which have yet to pass review: - The drivers/firmware/efi stub for booting from a standard UEFI firmware implementation. Both the original custom boot interface and a draft implementation of the EFI stub did not make it, so it is currently impossible to boot the kernel, until the loongarch specific portions get accepted into the UEFI subsystem - The drivers/irqchip/irq-loongson-*.c drivers are shared with the the MIPS port, but currently lack support for ACPI based booting, which will get merged through the irqchip subsystem. - Similarly, the drivers/pci/controller/pci-loongson.c needs to be modified for ACPI support, which will be merged through the PCI subsystem. While the port cannot actually be used before all the above are merged, having it in 5.19 helps to establish the user space ABI for the libc ports to build on, and to help any treewide changes in the mainline kernel get applied here as well. A gcc-12 based tool chains for build testing is now included in https://mirrors.edge.kernel.org/pub/tools/crosstool/. Original description from Huacai Chen at https://lore.kernel.org/lkml/20220603072053.35005-1-chenhuacai@loongson.cn/: "LoongArch is a new RISC ISA, which is a bit like MIPS or RISC-V. LoongArch includes a reduced 32-bit version (LA32R), a standard 32-bit version (LA32S) and a 64-bit version (LA64). LoongArch use ACPI as its boot protocol LoongArch-specific interrupt controllers (similar to APIC) are already added in the next revision of ACPI Specification (current revision is 6.4). This patchset is adding basic LoongArch support in mainline kernel, we can see a complete snapshot here: https://github.com/loongson/linux/tree/loongarch-next https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git/log/?h=loongarch-next Cross-compile tool chain to build kernel: https://github.com/loongson/build-tools/releases/download/2021.12.21/loongarch64-clfs-2022-03-03-cross-tools-gcc-glibc.tar.xz A CLFS-based Linux distro: https://github.com/loongson/build-tools/releases/download/2021.12.21/loongarch64-clfs-system-2022-03-03.tar.bz2 Open-source tool chain which is under review (Binutils and Gcc are already upstream): https://github.com/loongson/binutils-gdb/tree/upstream_v3.1 https://github.com/loongson/gcc/tree/loongarch_upstream_v6.3 https://github.com/loongson/glibc/tree/loongarch_2_35_dev_v2.2 Loongson and LoongArch documentations: https://github.com/loongson/LoongArch-Documentation LoongArch-specific interrupt controllers: https://mantis.uefi.org/mantis/view.php?id=2203 https://mantis.uefi.org/mantis/view.php?id=2313" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmKZ/akACgkQmmx57+YA GNnIARAAwUsSqjU0o8jyWb3hSTNstoZa5hszrS3NoMIvMHFfIaBbz1rre+D4xnYg 5weLv/xewJRcrAKG9GvjiqLnbhXadTveTNmYA6a2C5pAKAElLgOEzt2DnljAUs3E 1Gal9kM56TnA07khpcP/2NjHWOUG5mbTy+hzVcOqJvDJsuxo35Clm2OcS9Zk/Kmk gRCQ6bgHtyktEakAXFpyPvzt0ZOJVGVLFA7v1HIqdAZRfX7BH3nBJewSALXtdiQI 5M/dasqXnAh6aBetLeaDYONQcNICpg/uv6LesowgU/AwepVObO1NUh5Or8zXV5je a79TeidaijLPBEUtV7+oa2P4n1HMfKOVsaKL6THWzLbGA6izjMOwWq/E9+iaTkra hnaJMPlHuPz0M9c+/Z/8rp1u0K38vz27wle+kn9jyoMI1/q9EFEys1HQYGowJnQf 0G6RlnKLPQqRX6iNge43E91J8L0NBr8h+d9hu6ETcSBQuaO5d2asq9FLauQ2sK1j Qxsu6SpdbuyXVjHoPl/zfbuz8BX2t62tj+twGuRSJp13hcdo0Bf6fn/yoZCnLjfq kNRKTfIJwjNB93LCp5E49XEWfOfSy6KgLoeglp6T/B+gjrl2kfddCnmKfW9JBOZI 4B5N2DEYnyYBwkgumxLMmpKzUfETBD+KqAYj+OMwD3ZfhCYMQg0= =hkwN -----END PGP SIGNATURE----- Merge tag 'loongarch-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic Pull initial Loongarch architecture code from Arnd Bergmann: "This is the majority of the loongarch architecture code, including the final system call interface and all core functionality. It still misses three sets of peripheral but vital patches to add support for other subsystems, which have yet to pass review: - The drivers/firmware/efi stub for booting from a standard UEFI firmware implementation. Both the original custom boot interface and a draft implementation of the EFI stub did not make it, so it is currently impossible to boot the kernel, until the loongarch specific portions get accepted into the UEFI subsystem - The drivers/irqchip/irq-loongson-*.c drivers are shared with the the MIPS port, but currently lack support for ACPI based booting, which will get merged through the irqchip subsystem. - Similarly, the drivers/pci/controller/pci-loongson.c needs to be modified for ACPI support, which will be merged through the PCI subsystem. While the port cannot actually be used before all the above are merged, having it in 5.19 helps to establish the user space ABI for the libc ports to build on, and to help any treewide changes in the mainline kernel get applied here as well. A gcc-12 based tool chains for build testing is now included in https://mirrors.edge.kernel.org/pub/tools/crosstool/" Original description from Huacai Chen: "LoongArch is a new RISC ISA, which is a bit like MIPS or RISC-V. LoongArch includes a reduced 32-bit version (LA32R), a standard 32-bit version (LA32S) and a 64-bit version (LA64). LoongArch use ACPI as its boot protocol LoongArch-specific interrupt controllers (similar to APIC) are already added in the next revision of ACPI Specification (current revision is 6.4). This patchset is adding basic LoongArch support in mainline kernel, we can see a complete snapshot here: https://github.com/loongson/linux/tree/loongarch-next https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git/log/?h=loongarch-next Cross-compile tool chain to build kernel: https://github.com/loongson/build-tools/releases/download/2021.12.21/loongarch64-clfs-2022-03-03-cross-tools-gcc-glibc.tar.xz A CLFS-based Linux distro: https://github.com/loongson/build-tools/releases/download/2021.12.21/loongarch64-clfs-system-2022-03-03.tar.bz2 Open-source tool chain which is under review (Binutils and Gcc are already upstream): https://github.com/loongson/binutils-gdb/tree/upstream_v3.1 https://github.com/loongson/gcc/tree/loongarch_upstream_v6.3 https://github.com/loongson/glibc/tree/loongarch_2_35_dev_v2.2 Loongson and LoongArch documentations: https://github.com/loongson/LoongArch-Documentation LoongArch-specific interrupt controllers: https://mantis.uefi.org/mantis/view.php?id=2203 https://mantis.uefi.org/mantis/view.php?id=2313" Link: https://lore.kernel.org/lkml/20220603072053.35005-1-chenhuacai@loongson.cn/ * tag 'loongarch-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic: (24 commits) MAINTAINERS: Add maintainer information for LoongArch LoongArch: Add Loongson-3 default config file LoongArch: Add Non-Uniform Memory Access (NUMA) support LoongArch: Add multi-processor (SMP) support LoongArch: Add VDSO and VSYSCALL support LoongArch: Add some library functions LoongArch: Add misc common routines LoongArch: Add ELF and module support LoongArch: Add signal handling support LoongArch: Add system call support LoongArch: Add memory management LoongArch: Add process management LoongArch: Add exception/interrupt handling LoongArch: Add boot and setup routines LoongArch: Add other common headers LoongArch: Add atomic/locking headers LoongArch: Add CPU definition headers LoongArch: Add build infrastructure LoongArch: Add writecombine support for drm LoongArch: Add ELF-related definitions ...
This commit is contained in:
commit
c6f2f3e2c8
@ -13,6 +13,7 @@ implementation.
|
||||
arm/index
|
||||
arm64/index
|
||||
ia64/index
|
||||
loongarch/index
|
||||
m68k/index
|
||||
mips/index
|
||||
nios2/index
|
||||
|
3
Documentation/loongarch/features.rst
Normal file
3
Documentation/loongarch/features.rst
Normal file
@ -0,0 +1,3 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. kernel-feat:: $srctree/Documentation/features loongarch
|
21
Documentation/loongarch/index.rst
Normal file
21
Documentation/loongarch/index.rst
Normal file
@ -0,0 +1,21 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
======================
|
||||
LoongArch Architecture
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
introduction
|
||||
irq-chip-model
|
||||
|
||||
features
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
387
Documentation/loongarch/introduction.rst
Normal file
387
Documentation/loongarch/introduction.rst
Normal file
@ -0,0 +1,387 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=========================
|
||||
Introduction to LoongArch
|
||||
=========================
|
||||
|
||||
LoongArch is a new RISC ISA, which is a bit like MIPS or RISC-V. There are
|
||||
currently 3 variants: a reduced 32-bit version (LA32R), a standard 32-bit
|
||||
version (LA32S) and a 64-bit version (LA64). There are 4 privilege levels
|
||||
(PLVs) defined in LoongArch: PLV0~PLV3, from high to low. Kernel runs at PLV0
|
||||
while applications run at PLV3. This document introduces the registers, basic
|
||||
instruction set, virtual memory and some other topics of LoongArch.
|
||||
|
||||
Registers
|
||||
=========
|
||||
|
||||
LoongArch registers include general purpose registers (GPRs), floating point
|
||||
registers (FPRs), vector registers (VRs) and control status registers (CSRs)
|
||||
used in privileged mode (PLV0).
|
||||
|
||||
GPRs
|
||||
----
|
||||
|
||||
LoongArch has 32 GPRs ( ``$r0`` ~ ``$r31`` ); each one is 32-bit wide in LA32
|
||||
and 64-bit wide in LA64. ``$r0`` is hard-wired to zero, and the other registers
|
||||
are not architecturally special. (Except ``$r1``, which is hard-wired as the
|
||||
link register of the BL instruction.)
|
||||
|
||||
The kernel uses a variant of the LoongArch register convention, as described in
|
||||
the LoongArch ELF psABI spec, in :ref:`References <loongarch-references>`:
|
||||
|
||||
================= =============== =================== ============
|
||||
Name Alias Usage Preserved
|
||||
across calls
|
||||
================= =============== =================== ============
|
||||
``$r0`` ``$zero`` Constant zero Unused
|
||||
``$r1`` ``$ra`` Return address No
|
||||
``$r2`` ``$tp`` TLS/Thread pointer Unused
|
||||
``$r3`` ``$sp`` Stack pointer Yes
|
||||
``$r4``-``$r11`` ``$a0``-``$a7`` Argument registers No
|
||||
``$r4``-``$r5`` ``$v0``-``$v1`` Return value No
|
||||
``$r12``-``$r20`` ``$t0``-``$t8`` Temp registers No
|
||||
``$r21`` ``$u0`` Percpu base address Unused
|
||||
``$r22`` ``$fp`` Frame pointer Yes
|
||||
``$r23``-``$r31`` ``$s0``-``$s8`` Static registers Yes
|
||||
================= =============== =================== ============
|
||||
|
||||
Note: The register ``$r21`` is reserved in the ELF psABI, but used by the Linux
|
||||
kernel for storing the percpu base address. It normally has no ABI name, but is
|
||||
called ``$u0`` in the kernel. You may also see ``$v0`` or ``$v1`` in some old code,
|
||||
however they are deprecated aliases of ``$a0`` and ``$a1`` respectively.
|
||||
|
||||
FPRs
|
||||
----
|
||||
|
||||
LoongArch has 32 FPRs ( ``$f0`` ~ ``$f31`` ) when FPU is present. Each one is
|
||||
64-bit wide on the LA64 cores.
|
||||
|
||||
The floating-point register convention is the same as described in the
|
||||
LoongArch ELF psABI spec:
|
||||
|
||||
================= ================== =================== ============
|
||||
Name Alias Usage Preserved
|
||||
across calls
|
||||
================= ================== =================== ============
|
||||
``$f0``-``$f7`` ``$fa0``-``$fa7`` Argument registers No
|
||||
``$f0``-``$f1`` ``$fv0``-``$fv1`` Return value No
|
||||
``$f8``-``$f23`` ``$ft0``-``$ft15`` Temp registers No
|
||||
``$f24``-``$f31`` ``$fs0``-``$fs7`` Static registers Yes
|
||||
================= ================== =================== ============
|
||||
|
||||
Note: You may see ``$fv0`` or ``$fv1`` in some old code, however they are deprecated
|
||||
aliases of ``$fa0`` and ``$fa1`` respectively.
|
||||
|
||||
VRs
|
||||
----
|
||||
|
||||
There are currently 2 vector extensions to LoongArch:
|
||||
|
||||
- LSX (Loongson SIMD eXtension) with 128-bit vectors,
|
||||
- LASX (Loongson Advanced SIMD eXtension) with 256-bit vectors.
|
||||
|
||||
LSX brings ``$v0`` ~ ``$v31`` while LASX brings ``$x0`` ~ ``$x31`` as the vector
|
||||
registers.
|
||||
|
||||
The VRs overlap with FPRs: for example, on a core implementing LSX and LASX,
|
||||
the lower 128 bits of ``$x0`` is shared with ``$v0``, and the lower 64 bits of
|
||||
``$v0`` is shared with ``$f0``; same with all other VRs.
|
||||
|
||||
CSRs
|
||||
----
|
||||
|
||||
CSRs can only be accessed from privileged mode (PLV0):
|
||||
|
||||
================= ===================================== ==============
|
||||
Address Full Name Abbrev Name
|
||||
================= ===================================== ==============
|
||||
0x0 Current Mode Information CRMD
|
||||
0x1 Pre-exception Mode Information PRMD
|
||||
0x2 Extension Unit Enable EUEN
|
||||
0x3 Miscellaneous Control MISC
|
||||
0x4 Exception Configuration ECFG
|
||||
0x5 Exception Status ESTAT
|
||||
0x6 Exception Return Address ERA
|
||||
0x7 Bad (Faulting) Virtual Address BADV
|
||||
0x8 Bad (Faulting) Instruction Word BADI
|
||||
0xC Exception Entrypoint Address EENTRY
|
||||
0x10 TLB Index TLBIDX
|
||||
0x11 TLB Entry High-order Bits TLBEHI
|
||||
0x12 TLB Entry Low-order Bits 0 TLBELO0
|
||||
0x13 TLB Entry Low-order Bits 1 TLBELO1
|
||||
0x18 Address Space Identifier ASID
|
||||
0x19 Page Global Directory Address for PGDL
|
||||
Lower-half Address Space
|
||||
0x1A Page Global Directory Address for PGDH
|
||||
Higher-half Address Space
|
||||
0x1B Page Global Directory Address PGD
|
||||
0x1C Page Walk Control for Lower- PWCL
|
||||
half Address Space
|
||||
0x1D Page Walk Control for Higher- PWCH
|
||||
half Address Space
|
||||
0x1E STLB Page Size STLBPS
|
||||
0x1F Reduced Virtual Address Configuration RVACFG
|
||||
0x20 CPU Identifier CPUID
|
||||
0x21 Privileged Resource Configuration 1 PRCFG1
|
||||
0x22 Privileged Resource Configuration 2 PRCFG2
|
||||
0x23 Privileged Resource Configuration 3 PRCFG3
|
||||
0x30+n (0≤n≤15) Saved Data register SAVEn
|
||||
0x40 Timer Identifier TID
|
||||
0x41 Timer Configuration TCFG
|
||||
0x42 Timer Value TVAL
|
||||
0x43 Compensation of Timer Count CNTC
|
||||
0x44 Timer Interrupt Clearing TICLR
|
||||
0x60 LLBit Control LLBCTL
|
||||
0x80 Implementation-specific Control 1 IMPCTL1
|
||||
0x81 Implementation-specific Control 2 IMPCTL2
|
||||
0x88 TLB Refill Exception Entrypoint TLBRENTRY
|
||||
Address
|
||||
0x89 TLB Refill Exception BAD (Faulting) TLBRBADV
|
||||
Virtual Address
|
||||
0x8A TLB Refill Exception Return Address TLBRERA
|
||||
0x8B TLB Refill Exception Saved Data TLBRSAVE
|
||||
Register
|
||||
0x8C TLB Refill Exception Entry Low-order TLBRELO0
|
||||
Bits 0
|
||||
0x8D TLB Refill Exception Entry Low-order TLBRELO1
|
||||
Bits 1
|
||||
0x8E TLB Refill Exception Entry High-order TLBEHI
|
||||
Bits
|
||||
0x8F TLB Refill Exception Pre-exception TLBRPRMD
|
||||
Mode Information
|
||||
0x90 Machine Error Control MERRCTL
|
||||
0x91 Machine Error Information 1 MERRINFO1
|
||||
0x92 Machine Error Information 2 MERRINFO2
|
||||
0x93 Machine Error Exception Entrypoint MERRENTRY
|
||||
Address
|
||||
0x94 Machine Error Exception Return MERRERA
|
||||
Address
|
||||
0x95 Machine Error Exception Saved Data MERRSAVE
|
||||
Register
|
||||
0x98 Cache TAGs CTAG
|
||||
0x180+n (0≤n≤3) Direct Mapping Configuration Window n DMWn
|
||||
0x200+2n (0≤n≤31) Performance Monitor Configuration n PMCFGn
|
||||
0x201+2n (0≤n≤31) Performance Monitor Overall Counter n PMCNTn
|
||||
0x300 Memory Load/Store WatchPoint MWPC
|
||||
Overall Control
|
||||
0x301 Memory Load/Store WatchPoint MWPS
|
||||
Overall Status
|
||||
0x310+8n (0≤n≤7) Memory Load/Store WatchPoint n MWPnCFG1
|
||||
Configuration 1
|
||||
0x311+8n (0≤n≤7) Memory Load/Store WatchPoint n MWPnCFG2
|
||||
Configuration 2
|
||||
0x312+8n (0≤n≤7) Memory Load/Store WatchPoint n MWPnCFG3
|
||||
Configuration 3
|
||||
0x313+8n (0≤n≤7) Memory Load/Store WatchPoint n MWPnCFG4
|
||||
Configuration 4
|
||||
0x380 Instruction Fetch WatchPoint FWPC
|
||||
Overall Control
|
||||
0x381 Instruction Fetch WatchPoint FWPS
|
||||
Overall Status
|
||||
0x390+8n (0≤n≤7) Instruction Fetch WatchPoint n FWPnCFG1
|
||||
Configuration 1
|
||||
0x391+8n (0≤n≤7) Instruction Fetch WatchPoint n FWPnCFG2
|
||||
Configuration 2
|
||||
0x392+8n (0≤n≤7) Instruction Fetch WatchPoint n FWPnCFG3
|
||||
Configuration 3
|
||||
0x393+8n (0≤n≤7) Instruction Fetch WatchPoint n FWPnCFG4
|
||||
Configuration 4
|
||||
0x500 Debug Register DBG
|
||||
0x501 Debug Exception Return Address DERA
|
||||
0x502 Debug Exception Saved Data Register DSAVE
|
||||
================= ===================================== ==============
|
||||
|
||||
ERA, TLBRERA, MERRERA and DERA are sometimes also known as EPC, TLBREPC, MERREPC
|
||||
and DEPC respectively.
|
||||
|
||||
Basic Instruction Set
|
||||
=====================
|
||||
|
||||
Instruction formats
|
||||
-------------------
|
||||
|
||||
LoongArch instructions are 32 bits wide, belonging to 9 basic instruction
|
||||
formats (and variants of them):
|
||||
|
||||
=========== ==========================
|
||||
Format name Composition
|
||||
=========== ==========================
|
||||
2R Opcode + Rj + Rd
|
||||
3R Opcode + Rk + Rj + Rd
|
||||
4R Opcode + Ra + Rk + Rj + Rd
|
||||
2RI8 Opcode + I8 + Rj + Rd
|
||||
2RI12 Opcode + I12 + Rj + Rd
|
||||
2RI14 Opcode + I14 + Rj + Rd
|
||||
2RI16 Opcode + I16 + Rj + Rd
|
||||
1RI21 Opcode + I21L + Rj + I21H
|
||||
I26 Opcode + I26L + I26H
|
||||
=========== ==========================
|
||||
|
||||
Rd is the destination register operand, while Rj, Rk and Ra ("a" stands for
|
||||
"additional") are the source register operands. I8/I12/I16/I21/I26 are
|
||||
immediate operands of respective width. The longer I21 and I26 are stored
|
||||
in separate higher and lower parts in the instruction word, denoted by the "L"
|
||||
and "H" suffixes.
|
||||
|
||||
List of Instructions
|
||||
--------------------
|
||||
|
||||
For brevity, only instruction names (mnemonics) are listed here; please see the
|
||||
:ref:`References <loongarch-references>` for details.
|
||||
|
||||
|
||||
1. Arithmetic Instructions::
|
||||
|
||||
ADD.W SUB.W ADDI.W ADD.D SUB.D ADDI.D
|
||||
SLT SLTU SLTI SLTUI
|
||||
AND OR NOR XOR ANDN ORN ANDI ORI XORI
|
||||
MUL.W MULH.W MULH.WU DIV.W DIV.WU MOD.W MOD.WU
|
||||
MUL.D MULH.D MULH.DU DIV.D DIV.DU MOD.D MOD.DU
|
||||
PCADDI PCADDU12I PCADDU18I
|
||||
LU12I.W LU32I.D LU52I.D ADDU16I.D
|
||||
|
||||
2. Bit-shift Instructions::
|
||||
|
||||
SLL.W SRL.W SRA.W ROTR.W SLLI.W SRLI.W SRAI.W ROTRI.W
|
||||
SLL.D SRL.D SRA.D ROTR.D SLLI.D SRLI.D SRAI.D ROTRI.D
|
||||
|
||||
3. Bit-manipulation Instructions::
|
||||
|
||||
EXT.W.B EXT.W.H CLO.W CLO.D SLZ.W CLZ.D CTO.W CTO.D CTZ.W CTZ.D
|
||||
BYTEPICK.W BYTEPICK.D BSTRINS.W BSTRINS.D BSTRPICK.W BSTRPICK.D
|
||||
REVB.2H REVB.4H REVB.2W REVB.D REVH.2W REVH.D BITREV.4B BITREV.8B BITREV.W BITREV.D
|
||||
MASKEQZ MASKNEZ
|
||||
|
||||
4. Branch Instructions::
|
||||
|
||||
BEQ BNE BLT BGE BLTU BGEU BEQZ BNEZ B BL JIRL
|
||||
|
||||
5. Load/Store Instructions::
|
||||
|
||||
LD.B LD.BU LD.H LD.HU LD.W LD.WU LD.D ST.B ST.H ST.W ST.D
|
||||
LDX.B LDX.BU LDX.H LDX.HU LDX.W LDX.WU LDX.D STX.B STX.H STX.W STX.D
|
||||
LDPTR.W LDPTR.D STPTR.W STPTR.D
|
||||
PRELD PRELDX
|
||||
|
||||
6. Atomic Operation Instructions::
|
||||
|
||||
LL.W SC.W LL.D SC.D
|
||||
AMSWAP.W AMSWAP.D AMADD.W AMADD.D AMAND.W AMAND.D AMOR.W AMOR.D AMXOR.W AMXOR.D
|
||||
AMMAX.W AMMAX.D AMMIN.W AMMIN.D
|
||||
|
||||
7. Barrier Instructions::
|
||||
|
||||
IBAR DBAR
|
||||
|
||||
8. Special Instructions::
|
||||
|
||||
SYSCALL BREAK CPUCFG NOP IDLE ERTN(ERET) DBCL(DBGCALL) RDTIMEL.W RDTIMEH.W RDTIME.D
|
||||
ASRTLE.D ASRTGT.D
|
||||
|
||||
9. Privileged Instructions::
|
||||
|
||||
CSRRD CSRWR CSRXCHG
|
||||
IOCSRRD.B IOCSRRD.H IOCSRRD.W IOCSRRD.D IOCSRWR.B IOCSRWR.H IOCSRWR.W IOCSRWR.D
|
||||
CACOP TLBP(TLBSRCH) TLBRD TLBWR TLBFILL TLBCLR TLBFLUSH INVTLB LDDIR LDPTE
|
||||
|
||||
Virtual Memory
|
||||
==============
|
||||
|
||||
LoongArch supports direct-mapped virtual memory and page-mapped virtual memory.
|
||||
|
||||
Direct-mapped virtual memory is configured by CSR.DMWn (n=0~3), it has a simple
|
||||
relationship between virtual address (VA) and physical address (PA)::
|
||||
|
||||
VA = PA + FixedOffset
|
||||
|
||||
Page-mapped virtual memory has arbitrary relationship between VA and PA, which
|
||||
is recorded in TLB and page tables. LoongArch's TLB includes a fully-associative
|
||||
MTLB (Multiple Page Size TLB) and set-associative STLB (Single Page Size TLB).
|
||||
|
||||
By default, the whole virtual address space of LA32 is configured like this:
|
||||
|
||||
============ =========================== =============================
|
||||
Name Address Range Attributes
|
||||
============ =========================== =============================
|
||||
``UVRANGE`` ``0x00000000 - 0x7FFFFFFF`` Page-mapped, Cached, PLV0~3
|
||||
``KPRANGE0`` ``0x80000000 - 0x9FFFFFFF`` Direct-mapped, Uncached, PLV0
|
||||
``KPRANGE1`` ``0xA0000000 - 0xBFFFFFFF`` Direct-mapped, Cached, PLV0
|
||||
``KVRANGE`` ``0xC0000000 - 0xFFFFFFFF`` Page-mapped, Cached, PLV0
|
||||
============ =========================== =============================
|
||||
|
||||
User mode (PLV3) can only access UVRANGE. For direct-mapped KPRANGE0 and
|
||||
KPRANGE1, PA is equal to VA with bit30~31 cleared. For example, the uncached
|
||||
direct-mapped VA of 0x00001000 is 0x80001000, and the cached direct-mapped
|
||||
VA of 0x00001000 is 0xA0001000.
|
||||
|
||||
By default, the whole virtual address space of LA64 is configured like this:
|
||||
|
||||
============ ====================== ======================================
|
||||
Name Address Range Attributes
|
||||
============ ====================== ======================================
|
||||
``XUVRANGE`` ``0x0000000000000000 - Page-mapped, Cached, PLV0~3
|
||||
0x3FFFFFFFFFFFFFFF``
|
||||
``XSPRANGE`` ``0x4000000000000000 - Direct-mapped, Cached / Uncached, PLV0
|
||||
0x7FFFFFFFFFFFFFFF``
|
||||
``XKPRANGE`` ``0x8000000000000000 - Direct-mapped, Cached / Uncached, PLV0
|
||||
0xBFFFFFFFFFFFFFFF``
|
||||
``XKVRANGE`` ``0xC000000000000000 - Page-mapped, Cached, PLV0
|
||||
0xFFFFFFFFFFFFFFFF``
|
||||
============ ====================== ======================================
|
||||
|
||||
User mode (PLV3) can only access XUVRANGE. For direct-mapped XSPRANGE and
|
||||
XKPRANGE, PA is equal to VA with bits 60~63 cleared, and the cache attribute
|
||||
is configured by bits 60~61 in VA: 0 is for strongly-ordered uncached, 1 is
|
||||
for coherent cached, and 2 is for weakly-ordered uncached.
|
||||
|
||||
Currently we only use XKPRANGE for direct mapping and XSPRANGE is reserved.
|
||||
|
||||
To put this in action: the strongly-ordered uncached direct-mapped VA (in
|
||||
XKPRANGE) of 0x00000000_00001000 is 0x80000000_00001000, the coherent cached
|
||||
direct-mapped VA (in XKPRANGE) of 0x00000000_00001000 is 0x90000000_00001000,
|
||||
and the weakly-ordered uncached direct-mapped VA (in XKPRANGE) of 0x00000000
|
||||
_00001000 is 0xA0000000_00001000.
|
||||
|
||||
Relationship of Loongson and LoongArch
|
||||
======================================
|
||||
|
||||
LoongArch is a RISC ISA which is different from any other existing ones, while
|
||||
Loongson is a family of processors. Loongson includes 3 series: Loongson-1 is
|
||||
the 32-bit processor series, Loongson-2 is the low-end 64-bit processor series,
|
||||
and Loongson-3 is the high-end 64-bit processor series. Old Loongson is based on
|
||||
MIPS, while New Loongson is based on LoongArch. Take Loongson-3 as an example:
|
||||
Loongson-3A1000/3B1500/3A2000/3A3000/3A4000 are MIPS-compatible, while Loongson-
|
||||
3A5000 (and future revisions) are all based on LoongArch.
|
||||
|
||||
.. _loongarch-references:
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
Official web site of Loongson Technology Corp. Ltd.:
|
||||
|
||||
http://www.loongson.cn/
|
||||
|
||||
Developer web site of Loongson and LoongArch (Software and Documentation):
|
||||
|
||||
http://www.loongnix.cn/
|
||||
|
||||
https://github.com/loongson/
|
||||
|
||||
https://loongson.github.io/LoongArch-Documentation/
|
||||
|
||||
Documentation of LoongArch ISA:
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-CN.pdf (in Chinese)
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-EN.pdf (in English)
|
||||
|
||||
Documentation of LoongArch ELF psABI:
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-CN.pdf (in Chinese)
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-EN.pdf (in English)
|
||||
|
||||
Linux kernel repository of Loongson and LoongArch:
|
||||
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git
|
156
Documentation/loongarch/irq-chip-model.rst
Normal file
156
Documentation/loongarch/irq-chip-model.rst
Normal file
@ -0,0 +1,156 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======================================
|
||||
IRQ chip model (hierarchy) of LoongArch
|
||||
=======================================
|
||||
|
||||
Currently, LoongArch based processors (e.g. Loongson-3A5000) can only work together
|
||||
with LS7A chipsets. The irq chips in LoongArch computers include CPUINTC (CPU Core
|
||||
Interrupt Controller), LIOINTC (Legacy I/O Interrupt Controller), EIOINTC (Extended
|
||||
I/O Interrupt Controller), HTVECINTC (Hyper-Transport Vector Interrupt Controller),
|
||||
PCH-PIC (Main Interrupt Controller in LS7A chipset), PCH-LPC (LPC Interrupt Controller
|
||||
in LS7A chipset) and PCH-MSI (MSI Interrupt Controller).
|
||||
|
||||
CPUINTC is a per-core controller (in CPU), LIOINTC/EIOINTC/HTVECINTC are per-package
|
||||
controllers (in CPU), while PCH-PIC/PCH-LPC/PCH-MSI are controllers out of CPU (i.e.,
|
||||
in chipsets). These controllers (in other words, irqchips) are linked in a hierarchy,
|
||||
and there are two models of hierarchy (legacy model and extended model).
|
||||
|
||||
Legacy IRQ model
|
||||
================
|
||||
|
||||
In this model, IPI (Inter-Processor Interrupt) and CPU Local Timer interrupt go
|
||||
to CPUINTC directly, CPU UARTS interrupts go to LIOINTC, while all other devices
|
||||
interrupts go to PCH-PIC/PCH-LPC/PCH-MSI and gathered by HTVECINTC, and then go
|
||||
to LIOINTC, and then CPUINTC::
|
||||
|
||||
+-----+ +---------+ +-------+
|
||||
| IPI | --> | CPUINTC | <-- | Timer |
|
||||
+-----+ +---------+ +-------+
|
||||
^
|
||||
|
|
||||
+---------+ +-------+
|
||||
| LIOINTC | <-- | UARTs |
|
||||
+---------+ +-------+
|
||||
^
|
||||
|
|
||||
+-----------+
|
||||
| HTVECINTC |
|
||||
+-----------+
|
||||
^ ^
|
||||
| |
|
||||
+---------+ +---------+
|
||||
| PCH-PIC | | PCH-MSI |
|
||||
+---------+ +---------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
+---------+ +---------+ +---------+
|
||||
| PCH-LPC | | Devices | | Devices |
|
||||
+---------+ +---------+ +---------+
|
||||
^
|
||||
|
|
||||
+---------+
|
||||
| Devices |
|
||||
+---------+
|
||||
|
||||
Extended IRQ model
|
||||
==================
|
||||
|
||||
In this model, IPI (Inter-Processor Interrupt) and CPU Local Timer interrupt go
|
||||
to CPUINTC directly, CPU UARTS interrupts go to LIOINTC, while all other devices
|
||||
interrupts go to PCH-PIC/PCH-LPC/PCH-MSI and gathered by EIOINTC, and then go to
|
||||
to CPUINTC directly::
|
||||
|
||||
+-----+ +---------+ +-------+
|
||||
| IPI | --> | CPUINTC | <-- | Timer |
|
||||
+-----+ +---------+ +-------+
|
||||
^ ^
|
||||
| |
|
||||
+---------+ +---------+ +-------+
|
||||
| EIOINTC | | LIOINTC | <-- | UARTs |
|
||||
+---------+ +---------+ +-------+
|
||||
^ ^
|
||||
| |
|
||||
+---------+ +---------+
|
||||
| PCH-PIC | | PCH-MSI |
|
||||
+---------+ +---------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
+---------+ +---------+ +---------+
|
||||
| PCH-LPC | | Devices | | Devices |
|
||||
+---------+ +---------+ +---------+
|
||||
^
|
||||
|
|
||||
+---------+
|
||||
| Devices |
|
||||
+---------+
|
||||
|
||||
ACPI-related definitions
|
||||
========================
|
||||
|
||||
CPUINTC::
|
||||
|
||||
ACPI_MADT_TYPE_CORE_PIC;
|
||||
struct acpi_madt_core_pic;
|
||||
enum acpi_madt_core_pic_version;
|
||||
|
||||
LIOINTC::
|
||||
|
||||
ACPI_MADT_TYPE_LIO_PIC;
|
||||
struct acpi_madt_lio_pic;
|
||||
enum acpi_madt_lio_pic_version;
|
||||
|
||||
EIOINTC::
|
||||
|
||||
ACPI_MADT_TYPE_EIO_PIC;
|
||||
struct acpi_madt_eio_pic;
|
||||
enum acpi_madt_eio_pic_version;
|
||||
|
||||
HTVECINTC::
|
||||
|
||||
ACPI_MADT_TYPE_HT_PIC;
|
||||
struct acpi_madt_ht_pic;
|
||||
enum acpi_madt_ht_pic_version;
|
||||
|
||||
PCH-PIC::
|
||||
|
||||
ACPI_MADT_TYPE_BIO_PIC;
|
||||
struct acpi_madt_bio_pic;
|
||||
enum acpi_madt_bio_pic_version;
|
||||
|
||||
PCH-MSI::
|
||||
|
||||
ACPI_MADT_TYPE_MSI_PIC;
|
||||
struct acpi_madt_msi_pic;
|
||||
enum acpi_madt_msi_pic_version;
|
||||
|
||||
PCH-LPC::
|
||||
|
||||
ACPI_MADT_TYPE_LPC_PIC;
|
||||
struct acpi_madt_lpc_pic;
|
||||
enum acpi_madt_lpc_pic_version;
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
Documentation of Loongson-3A5000:
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-3A5000-usermanual-1.02-CN.pdf (in Chinese)
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-3A5000-usermanual-1.02-EN.pdf (in English)
|
||||
|
||||
Documentation of Loongson's LS7A chipset:
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-CN.pdf (in Chinese)
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-EN.pdf (in English)
|
||||
|
||||
Note: CPUINTC is CSR.ECFG/CSR.ESTAT and its interrupt controller described
|
||||
in Section 7.4 of "LoongArch Reference Manual, Vol 1"; LIOINTC is "Legacy I/O
|
||||
Interrupts" described in Section 11.1 of "Loongson 3A5000 Processor Reference
|
||||
Manual"; EIOINTC is "Extended I/O Interrupts" described in Section 11.2 of
|
||||
"Loongson 3A5000 Processor Reference Manual"; HTVECINTC is "HyperTransport
|
||||
Interrupts" described in Section 14.3 of "Loongson 3A5000 Processor Reference
|
||||
Manual"; PCH-PIC/PCH-MSI is "Interrupt Controller" described in Section 5 of
|
||||
"Loongson 7A1000 Bridge User Manual"; PCH-LPC is "LPC Interrupts" described in
|
||||
Section 24.3 of "Loongson 7A1000 Bridge User Manual".
|
@ -171,6 +171,7 @@ TODOList:
|
||||
riscv/index
|
||||
openrisc/index
|
||||
parisc/index
|
||||
loongarch/index
|
||||
|
||||
TODOList:
|
||||
|
||||
|
8
Documentation/translations/zh_CN/loongarch/features.rst
Normal file
8
Documentation/translations/zh_CN/loongarch/features.rst
Normal file
@ -0,0 +1,8 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/loongarch/features.rst
|
||||
:Translator: Huacai Chen <chenhuacai@loongson.cn>
|
||||
|
||||
.. kernel-feat:: $srctree/Documentation/features loongarch
|
26
Documentation/translations/zh_CN/loongarch/index.rst
Normal file
26
Documentation/translations/zh_CN/loongarch/index.rst
Normal file
@ -0,0 +1,26 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/loongarch/index.rst
|
||||
:Translator: Huacai Chen <chenhuacai@loongson.cn>
|
||||
|
||||
=================
|
||||
LoongArch体系结构
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
introduction
|
||||
irq-chip-model
|
||||
|
||||
features
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
351
Documentation/translations/zh_CN/loongarch/introduction.rst
Normal file
351
Documentation/translations/zh_CN/loongarch/introduction.rst
Normal file
@ -0,0 +1,351 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/loongarch/introduction.rst
|
||||
:Translator: Huacai Chen <chenhuacai@loongson.cn>
|
||||
|
||||
=============
|
||||
LoongArch介绍
|
||||
=============
|
||||
|
||||
LoongArch是一种新的RISC ISA,在一定程度上类似于MIPS和RISC-V。LoongArch指令集
|
||||
包括一个精简32位版(LA32R)、一个标准32位版(LA32S)、一个64位版(LA64)。
|
||||
LoongArch定义了四个特权级(PLV0~PLV3),其中PLV0是最高特权级,用于内核;而PLV3
|
||||
是最低特权级,用于应用程序。本文档介绍了LoongArch的寄存器、基础指令集、虚拟内
|
||||
存以及其他一些主题。
|
||||
|
||||
寄存器
|
||||
======
|
||||
|
||||
LoongArch的寄存器包括通用寄存器(GPRs)、浮点寄存器(FPRs)、向量寄存器(VRs)
|
||||
和用于特权模式(PLV0)的控制状态寄存器(CSRs)。
|
||||
|
||||
通用寄存器
|
||||
----------
|
||||
|
||||
LoongArch包括32个通用寄存器( ``$r0`` ~ ``$r31`` ),LA32中每个寄存器为32位宽,
|
||||
LA64中每个寄存器为64位宽。 ``$r0`` 的内容总是固定为0,而其他寄存器在体系结构层面
|
||||
没有特殊功能。( ``$r1`` 算是一个例外,在BL指令中固定用作链接返回寄存器。)
|
||||
|
||||
内核使用了一套LoongArch寄存器约定,定义在LoongArch ELF psABI规范中,详细描述参见
|
||||
:ref:`参考文献 <loongarch-references-zh_CN>`:
|
||||
|
||||
================= =============== =================== ==========
|
||||
寄存器名 别名 用途 跨调用保持
|
||||
================= =============== =================== ==========
|
||||
``$r0`` ``$zero`` 常量0 不使用
|
||||
``$r1`` ``$ra`` 返回地址 否
|
||||
``$r2`` ``$tp`` TLS/线程信息指针 不使用
|
||||
``$r3`` ``$sp`` 栈指针 是
|
||||
``$r4``-``$r11`` ``$a0``-``$a7`` 参数寄存器 否
|
||||
``$r4``-``$r5`` ``$v0``-``$v1`` 返回值 否
|
||||
``$r12``-``$r20`` ``$t0``-``$t8`` 临时寄存器 否
|
||||
``$r21`` ``$u0`` 每CPU变量基地址 不使用
|
||||
``$r22`` ``$fp`` 帧指针 是
|
||||
``$r23``-``$r31`` ``$s0``-``$s8`` 静态寄存器 是
|
||||
================= =============== =================== ==========
|
||||
|
||||
注意:``$r21``寄存器在ELF psABI中保留未使用,但是在Linux内核用于保存每CPU
|
||||
变量基地址。该寄存器没有ABI命名,不过在内核中称为``$u0``。在一些遗留代码
|
||||
中有时可能见到``$v0``和``$v1``,它们是``$a0``和``$a1``的别名,属于已经废弃
|
||||
的用法。
|
||||
|
||||
浮点寄存器
|
||||
----------
|
||||
|
||||
当系统中存在FPU时,LoongArch有32个浮点寄存器( ``$f0`` ~ ``$f31`` )。在LA64
|
||||
的CPU核上,每个寄存器均为64位宽。
|
||||
|
||||
浮点寄存器的使用约定与LoongArch ELF psABI规范的描述相同:
|
||||
|
||||
================= ================== =================== ==========
|
||||
寄存器名 别名 用途 跨调用保持
|
||||
================= ================== =================== ==========
|
||||
``$f0``-``$f7`` ``$fa0``-``$fa7`` 参数寄存器 否
|
||||
``$f0``-``$f1`` ``$fv0``-``$fv1`` 返回值 否
|
||||
``$f8``-``$f23`` ``$ft0``-``$ft15`` 临时寄存器 否
|
||||
``$f24``-``$f31`` ``$fs0``-``$fs7`` 静态寄存器 是
|
||||
================= ================== =================== ==========
|
||||
|
||||
注意:在一些遗留代码中有时可能见到 ``$v0`` 和 ``$v1`` ,它们是 ``$a0``
|
||||
和 ``$a1`` 的别名,属于已经废弃的用法。
|
||||
|
||||
|
||||
向量寄存器
|
||||
----------
|
||||
|
||||
LoongArch现有两种向量扩展:
|
||||
|
||||
- 128位向量扩展LSX(全称Loongson SIMD eXtention),
|
||||
- 256位向量扩展LASX(全称Loongson Advanced SIMD eXtention)。
|
||||
|
||||
LSX使用 ``$v0`` ~ ``$v31`` 向量寄存器,而LASX则使用 ``$x0`` ~ ``$x31`` 。
|
||||
|
||||
浮点寄存器和向量寄存器是复用的,比如:在一个实现了LSX和LASX的核上, ``$x0`` 的
|
||||
低128位与 ``$v0`` 共用, ``$v0`` 的低64位与 ``$f0`` 共用,其他寄存器依此类推。
|
||||
|
||||
控制状态寄存器
|
||||
--------------
|
||||
|
||||
控制状态寄存器只能在特权模式(PLV0)下访问:
|
||||
|
||||
================= ==================================== ==========
|
||||
地址 全称描述 简称
|
||||
================= ==================================== ==========
|
||||
0x0 当前模式信息 CRMD
|
||||
0x1 异常前模式信息 PRMD
|
||||
0x2 扩展部件使能 EUEN
|
||||
0x3 杂项控制 MISC
|
||||
0x4 异常配置 ECFG
|
||||
0x5 异常状态 ESTAT
|
||||
0x6 异常返回地址 ERA
|
||||
0x7 出错(Faulting)虚拟地址 BADV
|
||||
0x8 出错(Faulting)指令字 BADI
|
||||
0xC 异常入口地址 EENTRY
|
||||
0x10 TLB索引 TLBIDX
|
||||
0x11 TLB表项高位 TLBEHI
|
||||
0x12 TLB表项低位0 TLBELO0
|
||||
0x13 TLB表项低位1 TLBELO1
|
||||
0x18 地址空间标识符 ASID
|
||||
0x19 低半地址空间页全局目录基址 PGDL
|
||||
0x1A 高半地址空间页全局目录基址 PGDH
|
||||
0x1B 页全局目录基址 PGD
|
||||
0x1C 页表遍历控制低半部分 PWCL
|
||||
0x1D 页表遍历控制高半部分 PWCH
|
||||
0x1E STLB页大小 STLBPS
|
||||
0x1F 缩减虚地址配置 RVACFG
|
||||
0x20 CPU编号 CPUID
|
||||
0x21 特权资源配置信息1 PRCFG1
|
||||
0x22 特权资源配置信息2 PRCFG2
|
||||
0x23 特权资源配置信息3 PRCFG3
|
||||
0x30+n (0≤n≤15) 数据保存寄存器 SAVEn
|
||||
0x40 定时器编号 TID
|
||||
0x41 定时器配置 TCFG
|
||||
0x42 定时器值 TVAL
|
||||
0x43 计时器补偿 CNTC
|
||||
0x44 定时器中断清除 TICLR
|
||||
0x60 LLBit相关控制 LLBCTL
|
||||
0x80 实现相关控制1 IMPCTL1
|
||||
0x81 实现相关控制2 IMPCTL2
|
||||
0x88 TLB重填异常入口地址 TLBRENTRY
|
||||
0x89 TLB重填异常出错(Faulting)虚地址 TLBRBADV
|
||||
0x8A TLB重填异常返回地址 TLBRERA
|
||||
0x8B TLB重填异常数据保存 TLBRSAVE
|
||||
0x8C TLB重填异常表项低位0 TLBRELO0
|
||||
0x8D TLB重填异常表项低位1 TLBRELO1
|
||||
0x8E TLB重填异常表项高位 TLBEHI
|
||||
0x8F TLB重填异常前模式信息 TLBRPRMD
|
||||
0x90 机器错误控制 MERRCTL
|
||||
0x91 机器错误信息1 MERRINFO1
|
||||
0x92 机器错误信息2 MERRINFO2
|
||||
0x93 机器错误异常入口地址 MERRENTRY
|
||||
0x94 机器错误异常返回地址 MERRERA
|
||||
0x95 机器错误异常数据保存 MERRSAVE
|
||||
0x98 高速缓存标签 CTAG
|
||||
0x180+n (0≤n≤3) 直接映射配置窗口n DMWn
|
||||
0x200+2n (0≤n≤31) 性能监测配置n PMCFGn
|
||||
0x201+2n (0≤n≤31) 性能监测计数器n PMCNTn
|
||||
0x300 内存读写监视点整体控制 MWPC
|
||||
0x301 内存读写监视点整体状态 MWPS
|
||||
0x310+8n (0≤n≤7) 内存读写监视点n配置1 MWPnCFG1
|
||||
0x311+8n (0≤n≤7) 内存读写监视点n配置2 MWPnCFG2
|
||||
0x312+8n (0≤n≤7) 内存读写监视点n配置3 MWPnCFG3
|
||||
0x313+8n (0≤n≤7) 内存读写监视点n配置4 MWPnCFG4
|
||||
0x380 取指监视点整体控制 FWPC
|
||||
0x381 取指监视点整体状态 FWPS
|
||||
0x390+8n (0≤n≤7) 取指监视点n配置1 FWPnCFG1
|
||||
0x391+8n (0≤n≤7) 取指监视点n配置2 FWPnCFG2
|
||||
0x392+8n (0≤n≤7) 取指监视点n配置3 FWPnCFG3
|
||||
0x393+8n (0≤n≤7) 取指监视点n配置4 FWPnCFG4
|
||||
0x500 调试寄存器 DBG
|
||||
0x501 调试异常返回地址 DERA
|
||||
0x502 调试数据保存 DSAVE
|
||||
================= ==================================== ==========
|
||||
|
||||
ERA,TLBRERA,MERRERA和DERA有时也分别称为EPC,TLBREPC,MERREPC和DEPC。
|
||||
|
||||
基础指令集
|
||||
==========
|
||||
|
||||
指令格式
|
||||
--------
|
||||
|
||||
LoongArch的指令字长为32位,一共有9种基本指令格式(以及一些变体):
|
||||
|
||||
=========== ==========================
|
||||
格式名称 指令构成
|
||||
=========== ==========================
|
||||
2R Opcode + Rj + Rd
|
||||
3R Opcode + Rk + Rj + Rd
|
||||
4R Opcode + Ra + Rk + Rj + Rd
|
||||
2RI8 Opcode + I8 + Rj + Rd
|
||||
2RI12 Opcode + I12 + Rj + Rd
|
||||
2RI14 Opcode + I14 + Rj + Rd
|
||||
2RI16 Opcode + I16 + Rj + Rd
|
||||
1RI21 Opcode + I21L + Rj + I21H
|
||||
I26 Opcode + I26L + I26H
|
||||
=========== ==========================
|
||||
|
||||
Opcode是指令操作码,Rj和Rk是源操作数(寄存器),Rd是目标操作数(寄存器),Ra是
|
||||
4R-type格式特有的附加操作数(寄存器)。I8/I12/I16/I21/I26分别是8位/12位/16位/
|
||||
21位/26位的立即数。其中较长的21位和26位立即数在指令字中被分割为高位部分与低位
|
||||
部分,所以你们在这里的格式描述中能够看到I21L/I21H和I26L/I26H这样带后缀的表述。
|
||||
|
||||
指令列表
|
||||
--------
|
||||
|
||||
为了简便起见,我们在此只罗列一下指令名称(助记符),需要详细信息请阅读
|
||||
:ref:`参考文献 <loongarch-references-zh_CN>` 中的文档。
|
||||
|
||||
1. 算术运算指令::
|
||||
|
||||
ADD.W SUB.W ADDI.W ADD.D SUB.D ADDI.D
|
||||
SLT SLTU SLTI SLTUI
|
||||
AND OR NOR XOR ANDN ORN ANDI ORI XORI
|
||||
MUL.W MULH.W MULH.WU DIV.W DIV.WU MOD.W MOD.WU
|
||||
MUL.D MULH.D MULH.DU DIV.D DIV.DU MOD.D MOD.DU
|
||||
PCADDI PCADDU12I PCADDU18I
|
||||
LU12I.W LU32I.D LU52I.D ADDU16I.D
|
||||
|
||||
2. 移位运算指令::
|
||||
|
||||
SLL.W SRL.W SRA.W ROTR.W SLLI.W SRLI.W SRAI.W ROTRI.W
|
||||
SLL.D SRL.D SRA.D ROTR.D SLLI.D SRLI.D SRAI.D ROTRI.D
|
||||
|
||||
3. 位域操作指令::
|
||||
|
||||
EXT.W.B EXT.W.H CLO.W CLO.D SLZ.W CLZ.D CTO.W CTO.D CTZ.W CTZ.D
|
||||
BYTEPICK.W BYTEPICK.D BSTRINS.W BSTRINS.D BSTRPICK.W BSTRPICK.D
|
||||
REVB.2H REVB.4H REVB.2W REVB.D REVH.2W REVH.D BITREV.4B BITREV.8B BITREV.W BITREV.D
|
||||
MASKEQZ MASKNEZ
|
||||
|
||||
4. 分支转移指令::
|
||||
|
||||
BEQ BNE BLT BGE BLTU BGEU BEQZ BNEZ B BL JIRL
|
||||
|
||||
5. 访存读写指令::
|
||||
|
||||
LD.B LD.BU LD.H LD.HU LD.W LD.WU LD.D ST.B ST.H ST.W ST.D
|
||||
LDX.B LDX.BU LDX.H LDX.HU LDX.W LDX.WU LDX.D STX.B STX.H STX.W STX.D
|
||||
LDPTR.W LDPTR.D STPTR.W STPTR.D
|
||||
PRELD PRELDX
|
||||
|
||||
6. 原子操作指令::
|
||||
|
||||
LL.W SC.W LL.D SC.D
|
||||
AMSWAP.W AMSWAP.D AMADD.W AMADD.D AMAND.W AMAND.D AMOR.W AMOR.D AMXOR.W AMXOR.D
|
||||
AMMAX.W AMMAX.D AMMIN.W AMMIN.D
|
||||
|
||||
7. 栅障指令::
|
||||
|
||||
IBAR DBAR
|
||||
|
||||
8. 特殊指令::
|
||||
|
||||
SYSCALL BREAK CPUCFG NOP IDLE ERTN(ERET) DBCL(DBGCALL) RDTIMEL.W RDTIMEH.W RDTIME.D
|
||||
ASRTLE.D ASRTGT.D
|
||||
|
||||
9. 特权指令::
|
||||
|
||||
CSRRD CSRWR CSRXCHG
|
||||
IOCSRRD.B IOCSRRD.H IOCSRRD.W IOCSRRD.D IOCSRWR.B IOCSRWR.H IOCSRWR.W IOCSRWR.D
|
||||
CACOP TLBP(TLBSRCH) TLBRD TLBWR TLBFILL TLBCLR TLBFLUSH INVTLB LDDIR LDPTE
|
||||
|
||||
虚拟内存
|
||||
========
|
||||
|
||||
LoongArch可以使用直接映射虚拟内存和分页映射虚拟内存。
|
||||
|
||||
直接映射虚拟内存通过CSR.DMWn(n=0~3)来进行配置,虚拟地址(VA)和物理地址(PA)
|
||||
之间有简单的映射关系::
|
||||
|
||||
VA = PA + 固定偏移
|
||||
|
||||
分页映射的虚拟地址(VA)和物理地址(PA)有任意的映射关系,这种关系记录在TLB和页
|
||||
表中。LoongArch的TLB包括一个全相联的MTLB(Multiple Page Size TLB,多样页大小TLB)
|
||||
和一个组相联的STLB(Single Page Size TLB,单一页大小TLB)。
|
||||
|
||||
缺省状态下,LA32的整个虚拟地址空间配置如下:
|
||||
|
||||
============ =========================== ===========================
|
||||
区段名 地址范围 属性
|
||||
============ =========================== ===========================
|
||||
``UVRANGE`` ``0x00000000 - 0x7FFFFFFF`` 分页映射, 可缓存, PLV0~3
|
||||
``KPRANGE0`` ``0x80000000 - 0x9FFFFFFF`` 直接映射, 非缓存, PLV0
|
||||
``KPRANGE1`` ``0xA0000000 - 0xBFFFFFFF`` 直接映射, 可缓存, PLV0
|
||||
``KVRANGE`` ``0xC0000000 - 0xFFFFFFFF`` 分页映射, 可缓存, PLV0
|
||||
============ =========================== ===========================
|
||||
|
||||
用户态(PLV3)只能访问UVRANGE,对于直接映射的KPRANGE0和KPRANGE1,将虚拟地址的第
|
||||
30~31位清零就等于物理地址。例如:物理地址0x00001000对应的非缓存直接映射虚拟地址
|
||||
是0x80001000,而其可缓存直接映射虚拟地址是0xA0001000。
|
||||
|
||||
缺省状态下,LA64的整个虚拟地址空间配置如下:
|
||||
|
||||
============ ====================== ==================================
|
||||
区段名 地址范围 属性
|
||||
============ ====================== ==================================
|
||||
``XUVRANGE`` ``0x0000000000000000 - 分页映射, 可缓存, PLV0~3
|
||||
0x3FFFFFFFFFFFFFFF``
|
||||
``XSPRANGE`` ``0x4000000000000000 - 直接映射, 可缓存 / 非缓存, PLV0
|
||||
0x7FFFFFFFFFFFFFFF``
|
||||
``XKPRANGE`` ``0x8000000000000000 - 直接映射, 可缓存 / 非缓存, PLV0
|
||||
0xBFFFFFFFFFFFFFFF``
|
||||
``XKVRANGE`` ``0xC000000000000000 - 分页映射, 可缓存, PLV0
|
||||
0xFFFFFFFFFFFFFFFF``
|
||||
============ ====================== ==================================
|
||||
|
||||
用户态(PLV3)只能访问XUVRANGE,对于直接映射的XSPRANGE和XKPRANGE,将虚拟地址的第
|
||||
60~63位清零就等于物理地址,而其缓存属性是通过虚拟地址的第60~61位配置的(0表示强序
|
||||
非缓存,1表示一致可缓存,2表示弱序非缓存)。
|
||||
|
||||
目前,我们仅用XKPRANGE来进行直接映射,XSPRANGE保留给以后用。
|
||||
|
||||
此处给出一个直接映射的例子:物理地址0x00000000_00001000的强序非缓存直接映射虚拟地址
|
||||
(在XKPRANGE中)是0x80000000_00001000,其一致可缓存直接映射虚拟地址(在XKPRANGE中)
|
||||
是0x90000000_00001000,而其弱序非缓存直接映射虚拟地址(在XKPRANGE中)是0xA0000000_
|
||||
00001000。
|
||||
|
||||
Loongson与LoongArch的关系
|
||||
=========================
|
||||
|
||||
LoongArch是一种RISC指令集架构(ISA),不同于现存的任何一种ISA,而Loongson(即龙
|
||||
芯)是一个处理器家族。龙芯包括三个系列:Loongson-1(龙芯1号)是32位处理器系列,
|
||||
Loongson-2(龙芯2号)是低端64位处理器系列,而Loongson-3(龙芯3号)是高端64位处理
|
||||
器系列。旧的龙芯处理器基于MIPS架构,而新的龙芯处理器基于LoongArch架构。以龙芯3号
|
||||
为例:龙芯3A1000/3B1500/3A2000/3A3000/3A4000都是兼容MIPS的,而龙芯3A5000(以及将
|
||||
来的型号)都是基于LoongArch的。
|
||||
|
||||
.. _loongarch-references-zh_CN:
|
||||
|
||||
参考文献
|
||||
========
|
||||
|
||||
Loongson官方网站(龙芯中科技术股份有限公司):
|
||||
|
||||
http://www.loongson.cn/
|
||||
|
||||
Loongson与LoongArch的开发者网站(软件与文档资源):
|
||||
|
||||
http://www.loongnix.cn/
|
||||
|
||||
https://github.com/loongson/
|
||||
|
||||
https://loongson.github.io/LoongArch-Documentation/
|
||||
|
||||
LoongArch指令集架构的文档:
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-CN.pdf (中文版)
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-EN.pdf (英文版)
|
||||
|
||||
LoongArch的ELF psABI文档:
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-CN.pdf (中文版)
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-EN.pdf (英文版)
|
||||
|
||||
Loongson与LoongArch的Linux内核源码仓库:
|
||||
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git
|
155
Documentation/translations/zh_CN/loongarch/irq-chip-model.rst
Normal file
155
Documentation/translations/zh_CN/loongarch/irq-chip-model.rst
Normal file
@ -0,0 +1,155 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/loongarch/irq-chip-model.rst
|
||||
:Translator: Huacai Chen <chenhuacai@loongson.cn>
|
||||
|
||||
==================================
|
||||
LoongArch的IRQ芯片模型(层级关系)
|
||||
==================================
|
||||
|
||||
目前,基于LoongArch的处理器(如龙芯3A5000)只能与LS7A芯片组配合工作。LoongArch计算机
|
||||
中的中断控制器(即IRQ芯片)包括CPUINTC(CPU Core Interrupt Controller)、LIOINTC(
|
||||
Legacy I/O Interrupt Controller)、EIOINTC(Extended I/O Interrupt Controller)、
|
||||
HTVECINTC(Hyper-Transport Vector Interrupt Controller)、PCH-PIC(LS7A芯片组的主中
|
||||
断控制器)、PCH-LPC(LS7A芯片组的LPC中断控制器)和PCH-MSI(MSI中断控制器)。
|
||||
|
||||
CPUINTC是一种CPU内部的每个核本地的中断控制器,LIOINTC/EIOINTC/HTVECINTC是CPU内部的
|
||||
全局中断控制器(每个芯片一个,所有核共享),而PCH-PIC/PCH-LPC/PCH-MSI是CPU外部的中
|
||||
断控制器(在配套芯片组里面)。这些中断控制器(或者说IRQ芯片)以一种层次树的组织形式
|
||||
级联在一起,一共有两种层级关系模型(传统IRQ模型和扩展IRQ模型)。
|
||||
|
||||
传统IRQ模型
|
||||
===========
|
||||
|
||||
在这种模型里面,IPI(Inter-Processor Interrupt)和CPU本地时钟中断直接发送到CPUINTC,
|
||||
CPU串口(UARTs)中断发送到LIOINTC,而其他所有设备的中断则分别发送到所连接的PCH-PIC/
|
||||
PCH-LPC/PCH-MSI,然后被HTVECINTC统一收集,再发送到LIOINTC,最后到达CPUINTC::
|
||||
|
||||
+-----+ +---------+ +-------+
|
||||
| IPI | --> | CPUINTC | <-- | Timer |
|
||||
+-----+ +---------+ +-------+
|
||||
^
|
||||
|
|
||||
+---------+ +-------+
|
||||
| LIOINTC | <-- | UARTs |
|
||||
+---------+ +-------+
|
||||
^
|
||||
|
|
||||
+-----------+
|
||||
| HTVECINTC |
|
||||
+-----------+
|
||||
^ ^
|
||||
| |
|
||||
+---------+ +---------+
|
||||
| PCH-PIC | | PCH-MSI |
|
||||
+---------+ +---------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
+---------+ +---------+ +---------+
|
||||
| PCH-LPC | | Devices | | Devices |
|
||||
+---------+ +---------+ +---------+
|
||||
^
|
||||
|
|
||||
+---------+
|
||||
| Devices |
|
||||
+---------+
|
||||
|
||||
扩展IRQ模型
|
||||
===========
|
||||
|
||||
在这种模型里面,IPI(Inter-Processor Interrupt)和CPU本地时钟中断直接发送到CPUINTC,
|
||||
CPU串口(UARTs)中断发送到LIOINTC,而其他所有设备的中断则分别发送到所连接的PCH-PIC/
|
||||
PCH-LPC/PCH-MSI,然后被EIOINTC统一收集,再直接到达CPUINTC::
|
||||
|
||||
+-----+ +---------+ +-------+
|
||||
| IPI | --> | CPUINTC | <-- | Timer |
|
||||
+-----+ +---------+ +-------+
|
||||
^ ^
|
||||
| |
|
||||
+---------+ +---------+ +-------+
|
||||
| EIOINTC | | LIOINTC | <-- | UARTs |
|
||||
+---------+ +---------+ +-------+
|
||||
^ ^
|
||||
| |
|
||||
+---------+ +---------+
|
||||
| PCH-PIC | | PCH-MSI |
|
||||
+---------+ +---------+
|
||||
^ ^ ^
|
||||
| | |
|
||||
+---------+ +---------+ +---------+
|
||||
| PCH-LPC | | Devices | | Devices |
|
||||
+---------+ +---------+ +---------+
|
||||
^
|
||||
|
|
||||
+---------+
|
||||
| Devices |
|
||||
+---------+
|
||||
|
||||
ACPI相关的定义
|
||||
==============
|
||||
|
||||
CPUINTC::
|
||||
|
||||
ACPI_MADT_TYPE_CORE_PIC;
|
||||
struct acpi_madt_core_pic;
|
||||
enum acpi_madt_core_pic_version;
|
||||
|
||||
LIOINTC::
|
||||
|
||||
ACPI_MADT_TYPE_LIO_PIC;
|
||||
struct acpi_madt_lio_pic;
|
||||
enum acpi_madt_lio_pic_version;
|
||||
|
||||
EIOINTC::
|
||||
|
||||
ACPI_MADT_TYPE_EIO_PIC;
|
||||
struct acpi_madt_eio_pic;
|
||||
enum acpi_madt_eio_pic_version;
|
||||
|
||||
HTVECINTC::
|
||||
|
||||
ACPI_MADT_TYPE_HT_PIC;
|
||||
struct acpi_madt_ht_pic;
|
||||
enum acpi_madt_ht_pic_version;
|
||||
|
||||
PCH-PIC::
|
||||
|
||||
ACPI_MADT_TYPE_BIO_PIC;
|
||||
struct acpi_madt_bio_pic;
|
||||
enum acpi_madt_bio_pic_version;
|
||||
|
||||
PCH-MSI::
|
||||
|
||||
ACPI_MADT_TYPE_MSI_PIC;
|
||||
struct acpi_madt_msi_pic;
|
||||
enum acpi_madt_msi_pic_version;
|
||||
|
||||
PCH-LPC::
|
||||
|
||||
ACPI_MADT_TYPE_LPC_PIC;
|
||||
struct acpi_madt_lpc_pic;
|
||||
enum acpi_madt_lpc_pic_version;
|
||||
|
||||
参考文献
|
||||
========
|
||||
|
||||
龙芯3A5000的文档:
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-3A5000-usermanual-1.02-CN.pdf (中文版)
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-3A5000-usermanual-1.02-EN.pdf (英文版)
|
||||
|
||||
龙芯LS7A芯片组的文档:
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-CN.pdf (中文版)
|
||||
|
||||
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/Loongson-7A1000-usermanual-2.00-EN.pdf (英文版)
|
||||
|
||||
注:CPUINTC即《龙芯架构参考手册卷一》第7.4节所描述的CSR.ECFG/CSR.ESTAT寄存器及其中断
|
||||
控制逻辑;LIOINTC即《龙芯3A5000处理器使用手册》第11.1节所描述的“传统I/O中断”;EIOINTC
|
||||
即《龙芯3A5000处理器使用手册》第11.2节所描述的“扩展I/O中断”;HTVECINTC即《龙芯3A5000
|
||||
处理器使用手册》第14.3节所描述的“HyperTransport中断”;PCH-PIC/PCH-MSI即《龙芯7A1000桥
|
||||
片用户手册》第5章所描述的“中断控制器”;PCH-LPC即《龙芯7A1000桥片用户手册》第24.3节所
|
||||
描述的“LPC中断”。
|
10
MAINTAINERS
10
MAINTAINERS
@ -11565,6 +11565,16 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml
|
||||
F: drivers/gpu/drm/bridge/lontium-lt8912b.c
|
||||
|
||||
LOONGARCH
|
||||
M: Huacai Chen <chenhuacai@kernel.org>
|
||||
R: WANG Xuerui <kernel@xen0n.name>
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git
|
||||
F: arch/loongarch/
|
||||
F: drivers/*/*loongarch*
|
||||
F: Documentation/loongarch/
|
||||
F: Documentation/translations/zh_CN/loongarch/
|
||||
|
||||
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
|
||||
M: Sathya Prakash <sathya.prakash@broadcom.com>
|
||||
M: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
|
||||
|
6
arch/loongarch/Kbuild
Normal file
6
arch/loongarch/Kbuild
Normal file
@ -0,0 +1,6 @@
|
||||
obj-y += kernel/
|
||||
obj-y += mm/
|
||||
obj-y += vdso/
|
||||
|
||||
# for cleaning
|
||||
subdir- += boot
|
438
arch/loongarch/Kconfig
Normal file
438
arch/loongarch/Kconfig
Normal file
@ -0,0 +1,438 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
config LOONGARCH
|
||||
bool
|
||||
default y
|
||||
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
|
||||
select ARCH_BINFMT_ELF_STATE
|
||||
select ARCH_ENABLE_MEMORY_HOTPLUG
|
||||
select ARCH_ENABLE_MEMORY_HOTREMOVE
|
||||
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
|
||||
select ARCH_HAS_PHYS_TO_DMA
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_INLINE_READ_LOCK if !PREEMPTION
|
||||
select ARCH_INLINE_READ_LOCK_BH if !PREEMPTION
|
||||
select ARCH_INLINE_READ_LOCK_IRQ if !PREEMPTION
|
||||
select ARCH_INLINE_READ_LOCK_IRQSAVE if !PREEMPTION
|
||||
select ARCH_INLINE_READ_UNLOCK if !PREEMPTION
|
||||
select ARCH_INLINE_READ_UNLOCK_BH if !PREEMPTION
|
||||
select ARCH_INLINE_READ_UNLOCK_IRQ if !PREEMPTION
|
||||
select ARCH_INLINE_READ_UNLOCK_IRQRESTORE if !PREEMPTION
|
||||
select ARCH_INLINE_WRITE_LOCK if !PREEMPTION
|
||||
select ARCH_INLINE_WRITE_LOCK_BH if !PREEMPTION
|
||||
select ARCH_INLINE_WRITE_LOCK_IRQ if !PREEMPTION
|
||||
select ARCH_INLINE_WRITE_LOCK_IRQSAVE if !PREEMPTION
|
||||
select ARCH_INLINE_WRITE_UNLOCK if !PREEMPTION
|
||||
select ARCH_INLINE_WRITE_UNLOCK_BH if !PREEMPTION
|
||||
select ARCH_INLINE_WRITE_UNLOCK_IRQ if !PREEMPTION
|
||||
select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_TRYLOCK if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_TRYLOCK_BH if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_LOCK if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_LOCK_BH if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_LOCK_IRQ if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_LOCK_IRQSAVE if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_UNLOCK if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPTION
|
||||
select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
select ARCH_SPARSEMEM_ENABLE
|
||||
select ARCH_SUPPORTS_ACPI
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW
|
||||
select ARCH_SUPPORTS_HUGETLBFS
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select ARCH_USE_BUILTIN_BSWAP
|
||||
select ARCH_USE_CMPXCHG_LOCKREF
|
||||
select ARCH_USE_QUEUED_RWLOCKS
|
||||
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
|
||||
select ARCH_WANTS_NO_INSTR
|
||||
select BUILDTIME_TABLE_SORT
|
||||
select COMMON_CLK
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_CMOS_UPDATE
|
||||
select GENERIC_CPU_AUTOPROBE
|
||||
select GENERIC_ENTRY
|
||||
select GENERIC_FIND_FIRST_BIT
|
||||
select GENERIC_GETTIMEOFDAY
|
||||
select GENERIC_IRQ_MULTI_HANDLER
|
||||
select GENERIC_IRQ_PROBE
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_LIB_ASHLDI3
|
||||
select GENERIC_LIB_ASHRDI3
|
||||
select GENERIC_LIB_CMPDI2
|
||||
select GENERIC_LIB_LSHRDI3
|
||||
select GENERIC_LIB_UCMPDI2
|
||||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GPIOLIB
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_COMPILER_H
|
||||
select HAVE_ARCH_MMAP_RND_BITS if MMU
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select HAVE_ASM_MODVERSIONS
|
||||
select HAVE_CONTEXT_TRACKING
|
||||
select HAVE_COPY_THREAD_TLS
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
select HAVE_DMA_CONTIGUOUS
|
||||
select HAVE_EXIT_THREAD
|
||||
select HAVE_FAST_GUP
|
||||
select HAVE_GENERIC_VDSO
|
||||
select HAVE_IOREMAP_PROT
|
||||
select HAVE_IRQ_EXIT_ON_IRQ_STACK
|
||||
select HAVE_IRQ_TIME_ACCOUNTING
|
||||
select HAVE_MEMBLOCK
|
||||
select HAVE_MEMBLOCK_NODE_MAP
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select HAVE_NMI
|
||||
select HAVE_PERF_EVENTS
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_RSEQ
|
||||
select HAVE_SETUP_PER_CPU_AREA if NUMA
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select HAVE_TIF_NOHZ
|
||||
select HAVE_VIRT_CPU_ACCOUNTING_GEN if !SMP
|
||||
select IRQ_FORCED_THREADING
|
||||
select IRQ_LOONGARCH_CPU
|
||||
select MODULES_USE_ELF_RELA if MODULES
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
select NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
select OF
|
||||
select OF_EARLY_FLATTREE
|
||||
select PERF_USE_VMALLOC
|
||||
select RTC_LIB
|
||||
select SPARSE_IRQ
|
||||
select SYSCTL_EXCEPTION_TRACE
|
||||
select SWIOTLB
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
select ZONE_DMA32
|
||||
|
||||
config 32BIT
|
||||
bool
|
||||
|
||||
config 64BIT
|
||||
def_bool y
|
||||
|
||||
config CPU_HAS_FPU
|
||||
bool
|
||||
default y
|
||||
|
||||
config CPU_HAS_PREFETCH
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_CALIBRATE_DELAY
|
||||
def_bool y
|
||||
|
||||
config GENERIC_CSUM
|
||||
def_bool y
|
||||
|
||||
config GENERIC_HWEIGHT
|
||||
def_bool y
|
||||
|
||||
config L1_CACHE_SHIFT
|
||||
int
|
||||
default "6"
|
||||
|
||||
config LOCKDEP_SUPPORT
|
||||
bool
|
||||
default y
|
||||
|
||||
# MACH_LOONGSON32 and MACH_LOONGSON64 are delibrately carried over from the
|
||||
# MIPS Loongson code, to preserve Loongson-specific code paths in drivers that
|
||||
# are shared between architectures, and specifically expecting the symbols.
|
||||
config MACH_LOONGSON32
|
||||
def_bool 32BIT
|
||||
|
||||
config MACH_LOONGSON64
|
||||
def_bool 64BIT
|
||||
|
||||
config PAGE_SIZE_4KB
|
||||
bool
|
||||
|
||||
config PAGE_SIZE_16KB
|
||||
bool
|
||||
|
||||
config PAGE_SIZE_64KB
|
||||
bool
|
||||
|
||||
config PGTABLE_2LEVEL
|
||||
bool
|
||||
|
||||
config PGTABLE_3LEVEL
|
||||
bool
|
||||
|
||||
config PGTABLE_4LEVEL
|
||||
bool
|
||||
|
||||
config PGTABLE_LEVELS
|
||||
int
|
||||
default 2 if PGTABLE_2LEVEL
|
||||
default 3 if PGTABLE_3LEVEL
|
||||
default 4 if PGTABLE_4LEVEL
|
||||
|
||||
config SCHED_OMIT_FRAME_POINTER
|
||||
bool
|
||||
default y
|
||||
|
||||
menu "Kernel type and options"
|
||||
|
||||
source "kernel/Kconfig.hz"
|
||||
|
||||
choice
|
||||
prompt "Page Table Layout"
|
||||
default 16KB_2LEVEL if 32BIT
|
||||
default 16KB_3LEVEL if 64BIT
|
||||
help
|
||||
Allows choosing the page table layout, which is a combination
|
||||
of page size and page table levels. The size of virtual memory
|
||||
address space are determined by the page table layout.
|
||||
|
||||
config 4KB_3LEVEL
|
||||
bool "4KB with 3 levels"
|
||||
select PAGE_SIZE_4KB
|
||||
select PGTABLE_3LEVEL
|
||||
help
|
||||
This option selects 4KB page size with 3 level page tables, which
|
||||
support a maximum of 39 bits of application virtual memory.
|
||||
|
||||
config 4KB_4LEVEL
|
||||
bool "4KB with 4 levels"
|
||||
select PAGE_SIZE_4KB
|
||||
select PGTABLE_4LEVEL
|
||||
help
|
||||
This option selects 4KB page size with 4 level page tables, which
|
||||
support a maximum of 48 bits of application virtual memory.
|
||||
|
||||
config 16KB_2LEVEL
|
||||
bool "16KB with 2 levels"
|
||||
select PAGE_SIZE_16KB
|
||||
select PGTABLE_2LEVEL
|
||||
help
|
||||
This option selects 16KB page size with 2 level page tables, which
|
||||
support a maximum of 36 bits of application virtual memory.
|
||||
|
||||
config 16KB_3LEVEL
|
||||
bool "16KB with 3 levels"
|
||||
select PAGE_SIZE_16KB
|
||||
select PGTABLE_3LEVEL
|
||||
help
|
||||
This option selects 16KB page size with 3 level page tables, which
|
||||
support a maximum of 47 bits of application virtual memory.
|
||||
|
||||
config 64KB_2LEVEL
|
||||
bool "64KB with 2 levels"
|
||||
select PAGE_SIZE_64KB
|
||||
select PGTABLE_2LEVEL
|
||||
help
|
||||
This option selects 64KB page size with 2 level page tables, which
|
||||
support a maximum of 42 bits of application virtual memory.
|
||||
|
||||
config 64KB_3LEVEL
|
||||
bool "64KB with 3 levels"
|
||||
select PAGE_SIZE_64KB
|
||||
select PGTABLE_3LEVEL
|
||||
help
|
||||
This option selects 64KB page size with 3 level page tables, which
|
||||
support a maximum of 55 bits of application virtual memory.
|
||||
|
||||
endchoice
|
||||
|
||||
config CMDLINE
|
||||
string "Built-in kernel command line"
|
||||
help
|
||||
For most platforms, the arguments for the kernel's command line
|
||||
are provided at run-time, during boot. However, there are cases
|
||||
where either no arguments are being provided or the provided
|
||||
arguments are insufficient or even invalid.
|
||||
|
||||
When that occurs, it is possible to define a built-in command
|
||||
line here and choose how the kernel should use it later on.
|
||||
|
||||
choice
|
||||
prompt "Kernel command line type"
|
||||
default CMDLINE_BOOTLOADER
|
||||
help
|
||||
Choose how the kernel will handle the provided built-in command
|
||||
line.
|
||||
|
||||
config CMDLINE_BOOTLOADER
|
||||
bool "Use bootloader kernel arguments if available"
|
||||
help
|
||||
Prefer the command-line passed by the boot loader if available.
|
||||
Use the built-in command line as fallback in case we get nothing
|
||||
during boot. This is the default behaviour.
|
||||
|
||||
config CMDLINE_EXTEND
|
||||
bool "Use built-in to extend bootloader kernel arguments"
|
||||
help
|
||||
The command-line arguments provided during boot will be
|
||||
appended to the built-in command line. This is useful in
|
||||
cases where the provided arguments are insufficient and
|
||||
you don't want to or cannot modify them.
|
||||
|
||||
config CMDLINE_FORCE
|
||||
bool "Always use the built-in kernel command string"
|
||||
help
|
||||
Always use the built-in command line, even if we get one during
|
||||
boot. This is useful in case you need to override the provided
|
||||
command line on systems where you don't have or want control
|
||||
over it.
|
||||
|
||||
endchoice
|
||||
|
||||
config DMI
|
||||
bool "Enable DMI scanning"
|
||||
select DMI_SCAN_MACHINE_NON_EFI_FALLBACK
|
||||
default y
|
||||
help
|
||||
This enables SMBIOS/DMI feature for systems, and scanning of
|
||||
DMI to identify machine quirks.
|
||||
|
||||
config EFI
|
||||
bool "EFI runtime service support"
|
||||
select UCS2_STRING
|
||||
select EFI_PARAMS_FROM_FDT
|
||||
select EFI_RUNTIME_WRAPPERS
|
||||
help
|
||||
This enables the kernel to use EFI runtime services that are
|
||||
available (such as the EFI variable services).
|
||||
|
||||
config SMP
|
||||
bool "Multi-Processing support"
|
||||
help
|
||||
This enables support for systems with more than one CPU. If you have
|
||||
a system with only one CPU, say N. If you have a system with more
|
||||
than one CPU, say Y.
|
||||
|
||||
If you say N here, the kernel will run on uni- and multiprocessor
|
||||
machines, but will use only one CPU of a multiprocessor machine. If
|
||||
you say Y here, the kernel will run on many, but not all,
|
||||
uniprocessor machines. On a uniprocessor machine, the kernel
|
||||
will run faster if you say N here.
|
||||
|
||||
See also the SMP-HOWTO available at <http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
If you don't know what to do here, say N.
|
||||
|
||||
config HOTPLUG_CPU
|
||||
bool "Support for hot-pluggable CPUs"
|
||||
depends on SMP
|
||||
select GENERIC_IRQ_MIGRATION
|
||||
help
|
||||
Say Y here to allow turning CPUs off and on. CPUs can be
|
||||
controlled through /sys/devices/system/cpu.
|
||||
(Note: power management support will enable this option
|
||||
automatically on SMP systems. )
|
||||
Say N if you want to disable CPU hotplug.
|
||||
|
||||
config NR_CPUS
|
||||
int "Maximum number of CPUs (2-256)"
|
||||
range 2 256
|
||||
depends on SMP
|
||||
default "64"
|
||||
help
|
||||
This allows you to specify the maximum number of CPUs which this
|
||||
kernel will support.
|
||||
|
||||
config NUMA
|
||||
bool "NUMA Support"
|
||||
select ACPI_NUMA if ACPI
|
||||
help
|
||||
Say Y to compile the kernel with NUMA (Non-Uniform Memory Access)
|
||||
support. This option improves performance on systems with more
|
||||
than one NUMA node; on single node systems it is generally better
|
||||
to leave it disabled.
|
||||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
default "6"
|
||||
depends on NUMA
|
||||
|
||||
config FORCE_MAX_ZONEORDER
|
||||
int "Maximum zone order"
|
||||
range 14 64 if PAGE_SIZE_64KB
|
||||
default "14" if PAGE_SIZE_64KB
|
||||
range 12 64 if PAGE_SIZE_16KB
|
||||
default "12" if PAGE_SIZE_16KB
|
||||
range 11 64
|
||||
default "11"
|
||||
help
|
||||
The kernel memory allocator divides physically contiguous memory
|
||||
blocks into "zones", where each zone is a power of two number of
|
||||
pages. This option selects the largest power of two that the kernel
|
||||
keeps in the memory allocator. If you need to allocate very large
|
||||
blocks of physically contiguous memory, then you may need to
|
||||
increase this value.
|
||||
|
||||
This config option is actually maximum order plus one. For example,
|
||||
a value of 11 means that the largest free memory block is 2^10 pages.
|
||||
|
||||
The page size is not necessarily 4KB. Keep this in mind
|
||||
when choosing a value for this option.
|
||||
|
||||
config SECCOMP
|
||||
bool "Enable seccomp to safely compute untrusted bytecode"
|
||||
depends on PROC_FS
|
||||
default y
|
||||
help
|
||||
This kernel feature is useful for number crunching applications
|
||||
that may need to compute untrusted bytecode during their
|
||||
execution. By using pipes or other transports made available to
|
||||
the process as file descriptors supporting the read/write
|
||||
syscalls, it's possible to isolate those applications in
|
||||
their own address space using seccomp. Once seccomp is
|
||||
enabled via /proc/<pid>/seccomp, it cannot be disabled
|
||||
and the task is only allowed to execute a few safe syscalls
|
||||
defined by each seccomp mode.
|
||||
|
||||
If unsure, say Y. Only embedded should say N here.
|
||||
|
||||
endmenu
|
||||
|
||||
config ARCH_SELECT_MEMORY_MODEL
|
||||
def_bool y
|
||||
|
||||
config ARCH_FLATMEM_ENABLE
|
||||
def_bool y
|
||||
depends on !NUMA
|
||||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
def_bool y
|
||||
help
|
||||
Say Y to support efficient handling of sparse physical memory,
|
||||
for architectures which are either NUMA (Non-Uniform Memory Access)
|
||||
or have huge holes in the physical address space for other reasons.
|
||||
See <file:Documentation/vm/numa.rst> for more.
|
||||
|
||||
config ARCH_ENABLE_THP_MIGRATION
|
||||
def_bool y
|
||||
depends on TRANSPARENT_HUGEPAGE
|
||||
|
||||
config ARCH_MEMORY_PROBE
|
||||
def_bool y
|
||||
depends on MEMORY_HOTPLUG
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default y
|
||||
|
||||
config ARCH_MMAP_RND_BITS_MIN
|
||||
default 12
|
||||
|
||||
config ARCH_MMAP_RND_BITS_MAX
|
||||
default 18
|
||||
|
||||
menu "Power management options"
|
||||
|
||||
source "drivers/acpi/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
source "drivers/firmware/Kconfig"
|
0
arch/loongarch/Kconfig.debug
Normal file
0
arch/loongarch/Kconfig.debug
Normal file
100
arch/loongarch/Makefile
Normal file
100
arch/loongarch/Makefile
Normal file
@ -0,0 +1,100 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Author: Huacai Chen <chenhuacai@loongson.cn>
|
||||
# Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
|
||||
boot := arch/loongarch/boot
|
||||
|
||||
KBUILD_DEFCONFIG := loongson3_defconfig
|
||||
|
||||
KBUILD_IMAGE = $(boot)/vmlinux
|
||||
|
||||
#
|
||||
# Select the object file format to substitute into the linker script.
|
||||
#
|
||||
64bit-tool-archpref = loongarch64
|
||||
32bit-bfd = elf32-loongarch
|
||||
64bit-bfd = elf64-loongarch
|
||||
32bit-emul = elf32loongarch
|
||||
64bit-emul = elf64loongarch
|
||||
|
||||
ifdef CONFIG_64BIT
|
||||
tool-archpref = $(64bit-tool-archpref)
|
||||
UTS_MACHINE := loongarch64
|
||||
endif
|
||||
|
||||
ifneq ($(SUBARCH),$(ARCH))
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE := $(call cc-cross-prefix, $(tool-archpref)-linux- $(tool-archpref)-linux-gnu- $(tool-archpref)-unknown-linux-gnu-)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_64BIT
|
||||
ld-emul = $(64bit-emul)
|
||||
cflags-y += -mabi=lp64s
|
||||
endif
|
||||
|
||||
cflags-y += -G0 -pipe -msoft-float
|
||||
LDFLAGS_vmlinux += -G0 -static -n -nostdlib
|
||||
KBUILD_AFLAGS_KERNEL += -Wa,-mla-global-with-pcrel
|
||||
KBUILD_CFLAGS_KERNEL += -Wa,-mla-global-with-pcrel
|
||||
KBUILD_AFLAGS_MODULE += -Wa,-mla-global-with-abs
|
||||
KBUILD_CFLAGS_MODULE += -fplt -Wa,-mla-global-with-abs,-mla-local-with-abs
|
||||
|
||||
cflags-y += -ffreestanding
|
||||
cflags-y += $(call cc-option, -mno-check-zero-division)
|
||||
|
||||
load-y = 0x9000000000200000
|
||||
bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y)
|
||||
|
||||
KBUILD_AFLAGS += $(cflags-y)
|
||||
KBUILD_CFLAGS += $(cflags-y)
|
||||
KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y)
|
||||
|
||||
# This is required to get dwarf unwinding tables into .debug_frame
|
||||
# instead of .eh_frame so we don't discard them.
|
||||
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
|
||||
|
||||
# Don't emit unaligned accesses.
|
||||
# Not all LoongArch cores support unaligned access, and as kernel we can't
|
||||
# rely on others to provide emulation for these accesses.
|
||||
KBUILD_CFLAGS += $(call cc-option,-mstrict-align)
|
||||
|
||||
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 | \
|
||||
egrep -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
|
||||
sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
|
||||
endif
|
||||
|
||||
head-y := arch/loongarch/kernel/head.o
|
||||
|
||||
libs-y += arch/loongarch/lib/
|
||||
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
prepare: vdso_prepare
|
||||
vdso_prepare: prepare0
|
||||
$(Q)$(MAKE) $(build)=arch/loongarch/vdso include/generated/vdso-offsets.h
|
||||
endif
|
||||
|
||||
PHONY += vdso_install
|
||||
vdso_install:
|
||||
$(Q)$(MAKE) $(build)=arch/loongarch/vdso $@
|
||||
|
||||
all: $(KBUILD_IMAGE)
|
||||
|
||||
$(KBUILD_IMAGE): vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $@
|
||||
|
||||
install:
|
||||
$(Q)install -D -m 755 $(KBUILD_IMAGE) $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
|
||||
$(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
|
||||
$(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
|
||||
|
||||
define archhelp
|
||||
echo ' install - install kernel into $(INSTALL_PATH)'
|
||||
echo
|
||||
endef
|
2
arch/loongarch/boot/.gitignore
vendored
Normal file
2
arch/loongarch/boot/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
vmlinux*
|
16
arch/loongarch/boot/Makefile
Normal file
16
arch/loongarch/boot/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# arch/loongarch/boot/Makefile
|
||||
#
|
||||
# Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
#
|
||||
|
||||
drop-sections := .comment .note .options .note.gnu.build-id
|
||||
strip-flags := $(addprefix --remove-section=,$(drop-sections)) -S
|
||||
OBJCOPYFLAGS_vmlinux.efi := -O binary $(strip-flags)
|
||||
|
||||
targets := vmlinux
|
||||
quiet_cmd_strip = STRIP $@
|
||||
cmd_strip = $(STRIP) -s -o $@ $<
|
||||
|
||||
$(obj)/vmlinux: vmlinux FORCE
|
||||
$(call if_changed,strip)
|
4
arch/loongarch/boot/dts/Makefile
Normal file
4
arch/loongarch/boot/dts/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
dtstree := $(srctree)/$(src)
|
||||
|
||||
dtb-y := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
|
771
arch/loongarch/configs/loongson3_defconfig
Normal file
771
arch/loongarch/configs/loongson3_defconfig
Normal file
@ -0,0 +1,771 @@
|
||||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_BSD_PROCESS_ACCT=y
|
||||
CONFIG_BSD_PROCESS_ACCT_V3=y
|
||||
CONFIG_TASKSTATS=y
|
||||
CONFIG_TASK_DELAY_ACCT=y
|
||||
CONFIG_TASK_XACCT=y
|
||||
CONFIG_TASK_IO_ACCOUNTING=y
|
||||
CONFIG_LOG_BUF_SHIFT=18
|
||||
CONFIG_NUMA_BALANCING=y
|
||||
CONFIG_MEMCG=y
|
||||
CONFIG_BLK_CGROUP=y
|
||||
CONFIG_CFS_BANDWIDTH=y
|
||||
CONFIG_RT_GROUP_SCHED=y
|
||||
CONFIG_CGROUP_PIDS=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_HUGETLB=y
|
||||
CONFIG_CPUSETS=y
|
||||
CONFIG_CGROUP_DEVICE=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_CGROUP_PERF=y
|
||||
CONFIG_CGROUP_BPF=y
|
||||
CONFIG_NAMESPACES=y
|
||||
CONFIG_USER_NS=y
|
||||
CONFIG_CHECKPOINT_RESTORE=y
|
||||
CONFIG_SCHED_AUTOGROUP=y
|
||||
CONFIG_SYSFS_DEPRECATED=y
|
||||
CONFIG_RELAY=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_EXPERT=y
|
||||
CONFIG_USERFAULTFD=y
|
||||
CONFIG_PERF_EVENTS=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_LOONGARCH=y
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_MACH_LOONGSON64=y
|
||||
CONFIG_DMI=y
|
||||
CONFIG_EFI=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_NR_CPUS=64
|
||||
CONFIG_NUMA=y
|
||||
CONFIG_PAGE_SIZE_16KB=y
|
||||
CONFIG_HZ_250=y
|
||||
CONFIG_ACPI=y
|
||||
CONFIG_ACPI_SPCR_TABLE=y
|
||||
CONFIG_ACPI_HOTPLUG_CPU=y
|
||||
CONFIG_ACPI_TAD=y
|
||||
CONFIG_ACPI_DOCK=y
|
||||
CONFIG_ACPI_IPMI=m
|
||||
CONFIG_ACPI_PCI_SLOT=y
|
||||
CONFIG_ACPI_HOTPLUG_MEMORY=y
|
||||
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
|
||||
CONFIG_EFI_CAPSULE_LOADER=m
|
||||
CONFIG_EFI_TEST=m
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_FORCE_LOAD=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_MODULE_FORCE_UNLOAD=y
|
||||
CONFIG_MODVERSIONS=y
|
||||
CONFIG_BLK_DEV_THROTTLING=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_IOSCHED_BFQ=y
|
||||
CONFIG_BFQ_GROUP_IOSCHED=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_ZSWAP=y
|
||||
CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y
|
||||
CONFIG_ZPOOL=y
|
||||
CONFIG_ZBUD=y
|
||||
CONFIG_Z3FOLD=y
|
||||
CONFIG_ZSMALLOC=m
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_XFRM_USER=y
|
||||
CONFIG_NET_KEY=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_MULTIPLE_TABLES=y
|
||||
CONFIG_IP_ROUTE_MULTIPATH=y
|
||||
CONFIG_IP_ROUTE_VERBOSE=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_IP_PNP_RARP=y
|
||||
CONFIG_NET_IPIP=m
|
||||
CONFIG_IP_MROUTE=y
|
||||
CONFIG_INET_ESP=m
|
||||
CONFIG_INET_UDP_DIAG=y
|
||||
CONFIG_TCP_CONG_ADVANCED=y
|
||||
CONFIG_TCP_CONG_BBR=m
|
||||
CONFIG_IPV6_ROUTER_PREF=y
|
||||
CONFIG_IPV6_ROUTE_INFO=y
|
||||
CONFIG_IPV6_MROUTE=y
|
||||
CONFIG_NETWORK_PHY_TIMESTAMPING=y
|
||||
CONFIG_NETFILTER=y
|
||||
CONFIG_BRIDGE_NETFILTER=m
|
||||
CONFIG_NETFILTER_NETLINK_LOG=m
|
||||
CONFIG_NF_CONNTRACK=m
|
||||
CONFIG_NF_LOG_NETDEV=m
|
||||
CONFIG_NF_CONNTRACK_AMANDA=m
|
||||
CONFIG_NF_CONNTRACK_FTP=m
|
||||
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
|
||||
CONFIG_NF_CONNTRACK_TFTP=m
|
||||
CONFIG_NF_CT_NETLINK=m
|
||||
CONFIG_NF_TABLES=m
|
||||
CONFIG_NFT_COUNTER=m
|
||||
CONFIG_NFT_CONNLIMIT=m
|
||||
CONFIG_NFT_LOG=m
|
||||
CONFIG_NFT_LIMIT=m
|
||||
CONFIG_NFT_MASQ=m
|
||||
CONFIG_NFT_REDIR=m
|
||||
CONFIG_NFT_NAT=m
|
||||
CONFIG_NFT_TUNNEL=m
|
||||
CONFIG_NFT_OBJREF=m
|
||||
CONFIG_NFT_QUEUE=m
|
||||
CONFIG_NFT_QUOTA=m
|
||||
CONFIG_NFT_REJECT=m
|
||||
CONFIG_NFT_COMPAT=m
|
||||
CONFIG_NFT_HASH=m
|
||||
CONFIG_NFT_SOCKET=m
|
||||
CONFIG_NFT_OSF=m
|
||||
CONFIG_NFT_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_SET=m
|
||||
CONFIG_NETFILTER_XT_TARGET_AUDIT=m
|
||||
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
|
||||
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_CT=m
|
||||
CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_HMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
|
||||
CONFIG_NETFILTER_XT_TARGET_LED=m
|
||||
CONFIG_NETFILTER_XT_TARGET_LOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
|
||||
CONFIG_NETFILTER_XT_MATCH_BPF=m
|
||||
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
|
||||
CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
|
||||
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
|
||||
CONFIG_NETFILTER_XT_MATCH_CPU=m
|
||||
CONFIG_NETFILTER_XT_MATCH_DCCP=m
|
||||
CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
|
||||
CONFIG_NETFILTER_XT_MATCH_DSCP=m
|
||||
CONFIG_NETFILTER_XT_MATCH_ESP=m
|
||||
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_HELPER=m
|
||||
CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
|
||||
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
|
||||
CONFIG_NETFILTER_XT_MATCH_IPVS=m
|
||||
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
|
||||
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MAC=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MARK=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_NFACCT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_OSF=m
|
||||
CONFIG_NETFILTER_XT_MATCH_OWNER=m
|
||||
CONFIG_NETFILTER_XT_MATCH_POLICY=m
|
||||
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
|
||||
CONFIG_NETFILTER_XT_MATCH_QUOTA=m
|
||||
CONFIG_NETFILTER_XT_MATCH_RATEEST=m
|
||||
CONFIG_NETFILTER_XT_MATCH_REALM=m
|
||||
CONFIG_NETFILTER_XT_MATCH_SOCKET=m
|
||||
CONFIG_NETFILTER_XT_MATCH_STATE=m
|
||||
CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
|
||||
CONFIG_NETFILTER_XT_MATCH_STRING=m
|
||||
CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_MATCH_TIME=m
|
||||
CONFIG_NETFILTER_XT_MATCH_U32=m
|
||||
CONFIG_IP_SET=m
|
||||
CONFIG_IP_VS=m
|
||||
CONFIG_IP_VS_IPV6=y
|
||||
CONFIG_IP_VS_PROTO_TCP=y
|
||||
CONFIG_IP_VS_PROTO_UDP=y
|
||||
CONFIG_IP_VS_RR=m
|
||||
CONFIG_IP_VS_NFCT=y
|
||||
CONFIG_NF_TABLES_IPV4=y
|
||||
CONFIG_NFT_DUP_IPV4=m
|
||||
CONFIG_NFT_FIB_IPV4=m
|
||||
CONFIG_NF_TABLES_ARP=y
|
||||
CONFIG_NF_LOG_ARP=m
|
||||
CONFIG_IP_NF_IPTABLES=m
|
||||
CONFIG_IP_NF_MATCH_AH=m
|
||||
CONFIG_IP_NF_MATCH_ECN=m
|
||||
CONFIG_IP_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP_NF_MATCH_TTL=m
|
||||
CONFIG_IP_NF_FILTER=m
|
||||
CONFIG_IP_NF_TARGET_REJECT=m
|
||||
CONFIG_IP_NF_TARGET_SYNPROXY=m
|
||||
CONFIG_IP_NF_NAT=m
|
||||
CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
CONFIG_IP_NF_SECURITY=m
|
||||
CONFIG_IP_NF_ARPTABLES=m
|
||||
CONFIG_IP_NF_ARPFILTER=m
|
||||
CONFIG_IP_NF_ARP_MANGLE=m
|
||||
CONFIG_NF_TABLES_IPV6=y
|
||||
CONFIG_IP6_NF_IPTABLES=y
|
||||
CONFIG_IP6_NF_MATCH_AH=m
|
||||
CONFIG_IP6_NF_MATCH_EUI64=m
|
||||
CONFIG_IP6_NF_MATCH_FRAG=m
|
||||
CONFIG_IP6_NF_MATCH_OPTS=m
|
||||
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
|
||||
CONFIG_IP6_NF_MATCH_MH=m
|
||||
CONFIG_IP6_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP6_NF_MATCH_RT=m
|
||||
CONFIG_IP6_NF_MATCH_SRH=m
|
||||
CONFIG_IP6_NF_FILTER=y
|
||||
CONFIG_IP6_NF_TARGET_REJECT=m
|
||||
CONFIG_IP6_NF_TARGET_SYNPROXY=m
|
||||
CONFIG_IP6_NF_MANGLE=m
|
||||
CONFIG_IP6_NF_RAW=m
|
||||
CONFIG_IP6_NF_SECURITY=m
|
||||
CONFIG_IP6_NF_NAT=m
|
||||
CONFIG_IP6_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP6_NF_TARGET_NPT=m
|
||||
CONFIG_NF_TABLES_BRIDGE=m
|
||||
CONFIG_BRIDGE_NF_EBTABLES=m
|
||||
CONFIG_BRIDGE_EBT_BROUTE=m
|
||||
CONFIG_BRIDGE_EBT_T_FILTER=m
|
||||
CONFIG_BRIDGE_EBT_T_NAT=m
|
||||
CONFIG_BRIDGE_EBT_ARP=m
|
||||
CONFIG_BRIDGE_EBT_IP=m
|
||||
CONFIG_BRIDGE_EBT_IP6=m
|
||||
CONFIG_BPFILTER=y
|
||||
CONFIG_IP_SCTP=m
|
||||
CONFIG_RDS=y
|
||||
CONFIG_L2TP=m
|
||||
CONFIG_BRIDGE=m
|
||||
CONFIG_VLAN_8021Q=m
|
||||
CONFIG_VLAN_8021Q_GVRP=y
|
||||
CONFIG_VLAN_8021Q_MVRP=y
|
||||
CONFIG_NET_SCHED=y
|
||||
CONFIG_NET_SCH_HTB=m
|
||||
CONFIG_NET_SCH_PRIO=m
|
||||
CONFIG_NET_SCH_SFQ=m
|
||||
CONFIG_NET_SCH_TBF=m
|
||||
CONFIG_NET_SCH_NETEM=m
|
||||
CONFIG_NET_SCH_INGRESS=m
|
||||
CONFIG_NET_CLS_BASIC=m
|
||||
CONFIG_NET_CLS_FW=m
|
||||
CONFIG_NET_CLS_U32=m
|
||||
CONFIG_NET_CLS_CGROUP=m
|
||||
CONFIG_NET_CLS_BPF=m
|
||||
CONFIG_NET_CLS_ACT=y
|
||||
CONFIG_NET_ACT_POLICE=m
|
||||
CONFIG_NET_ACT_GACT=m
|
||||
CONFIG_NET_ACT_MIRRED=m
|
||||
CONFIG_NET_ACT_IPT=m
|
||||
CONFIG_NET_ACT_NAT=m
|
||||
CONFIG_NET_ACT_BPF=m
|
||||
CONFIG_OPENVSWITCH=m
|
||||
CONFIG_NETLINK_DIAG=y
|
||||
CONFIG_CGROUP_NET_PRIO=y
|
||||
CONFIG_BT=m
|
||||
CONFIG_BT_HCIBTUSB=m
|
||||
# CONFIG_BT_HCIBTUSB_BCM is not set
|
||||
CONFIG_CFG80211=m
|
||||
CONFIG_CFG80211_WEXT=y
|
||||
CONFIG_MAC80211=m
|
||||
CONFIG_RFKILL=m
|
||||
CONFIG_RFKILL_INPUT=y
|
||||
CONFIG_NET_9P=y
|
||||
CONFIG_CEPH_LIB=m
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_HOTPLUG_PCI_PCIE=y
|
||||
CONFIG_PCIEAER=y
|
||||
# CONFIG_PCIEASPM is not set
|
||||
CONFIG_PCI_IOV=y
|
||||
CONFIG_HOTPLUG_PCI=y
|
||||
CONFIG_HOTPLUG_PCI_SHPC=y
|
||||
CONFIG_PCCARD=m
|
||||
CONFIG_YENTA=m
|
||||
CONFIG_RAPIDIO=y
|
||||
CONFIG_RAPIDIO_TSI721=y
|
||||
CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS=y
|
||||
CONFIG_RAPIDIO_ENUM_BASIC=m
|
||||
CONFIG_RAPIDIO_CHMAN=m
|
||||
CONFIG_RAPIDIO_MPORT_CDEV=m
|
||||
CONFIG_UEVENT_HELPER=y
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
CONFIG_MTD=m
|
||||
CONFIG_MTD_BLOCK=m
|
||||
CONFIG_MTD_CFI=m
|
||||
CONFIG_MTD_JEDECPROBE=m
|
||||
CONFIG_MTD_CFI_INTELEXT=m
|
||||
CONFIG_MTD_CFI_AMDSTD=m
|
||||
CONFIG_MTD_CFI_STAA=m
|
||||
CONFIG_MTD_RAM=m
|
||||
CONFIG_MTD_ROM=m
|
||||
CONFIG_PARPORT=y
|
||||
CONFIG_PARPORT_PC=y
|
||||
CONFIG_PARPORT_SERIAL=y
|
||||
CONFIG_PARPORT_PC_FIFO=y
|
||||
CONFIG_ZRAM=m
|
||||
CONFIG_ZRAM_DEF_COMP_ZSTD=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_CRYPTOLOOP=y
|
||||
CONFIG_BLK_DEV_NBD=m
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=8192
|
||||
CONFIG_BLK_DEV_RBD=m
|
||||
CONFIG_BLK_DEV_NVME=y
|
||||
CONFIG_EEPROM_AT24=m
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_DEV_SR=y
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
CONFIG_CHR_DEV_SCH=m
|
||||
CONFIG_SCSI_CONSTANTS=y
|
||||
CONFIG_SCSI_LOGGING=y
|
||||
CONFIG_SCSI_SPI_ATTRS=m
|
||||
CONFIG_SCSI_FC_ATTRS=m
|
||||
CONFIG_SCSI_SAS_ATA=y
|
||||
CONFIG_ISCSI_TCP=m
|
||||
CONFIG_SCSI_MVSAS=y
|
||||
# CONFIG_SCSI_MVSAS_DEBUG is not set
|
||||
CONFIG_SCSI_MVSAS_TASKLET=y
|
||||
CONFIG_SCSI_MVUMI=y
|
||||
CONFIG_MEGARAID_NEWGEN=y
|
||||
CONFIG_MEGARAID_MM=y
|
||||
CONFIG_MEGARAID_MAILBOX=y
|
||||
CONFIG_MEGARAID_LEGACY=y
|
||||
CONFIG_MEGARAID_SAS=y
|
||||
CONFIG_SCSI_MPT2SAS=y
|
||||
CONFIG_LIBFC=m
|
||||
CONFIG_LIBFCOE=m
|
||||
CONFIG_FCOE=m
|
||||
CONFIG_SCSI_QLOGIC_1280=m
|
||||
CONFIG_SCSI_QLA_FC=m
|
||||
CONFIG_TCM_QLA2XXX=m
|
||||
CONFIG_SCSI_QLA_ISCSI=m
|
||||
CONFIG_SCSI_LPFC=m
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
CONFIG_SATA_AHCI_PLATFORM=y
|
||||
CONFIG_PATA_ATIIXP=y
|
||||
CONFIG_PATA_PCMCIA=m
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_MD=m
|
||||
CONFIG_MD_LINEAR=m
|
||||
CONFIG_MD_RAID0=m
|
||||
CONFIG_MD_RAID1=m
|
||||
CONFIG_MD_RAID10=m
|
||||
CONFIG_MD_RAID456=m
|
||||
CONFIG_MD_MULTIPATH=m
|
||||
CONFIG_BCACHE=m
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
CONFIG_DM_CRYPT=m
|
||||
CONFIG_DM_SNAPSHOT=m
|
||||
CONFIG_DM_THIN_PROVISIONING=m
|
||||
CONFIG_DM_CACHE=m
|
||||
CONFIG_DM_WRITECACHE=m
|
||||
CONFIG_DM_MIRROR=m
|
||||
CONFIG_DM_RAID=m
|
||||
CONFIG_DM_ZERO=m
|
||||
CONFIG_DM_MULTIPATH=m
|
||||
CONFIG_DM_MULTIPATH_QL=m
|
||||
CONFIG_DM_MULTIPATH_ST=m
|
||||
CONFIG_TARGET_CORE=m
|
||||
CONFIG_TCM_IBLOCK=m
|
||||
CONFIG_TCM_FILEIO=m
|
||||
CONFIG_TCM_PSCSI=m
|
||||
CONFIG_TCM_USER2=m
|
||||
CONFIG_LOOPBACK_TARGET=m
|
||||
CONFIG_ISCSI_TARGET=m
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_BONDING=m
|
||||
CONFIG_DUMMY=y
|
||||
CONFIG_WIREGUARD=m
|
||||
CONFIG_MACVLAN=m
|
||||
CONFIG_MACVTAP=m
|
||||
CONFIG_IPVLAN=m
|
||||
CONFIG_VXLAN=y
|
||||
CONFIG_RIONET=m
|
||||
CONFIG_TUN=m
|
||||
CONFIG_VETH=m
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
# CONFIG_NET_VENDOR_ADAPTEC is not set
|
||||
# CONFIG_NET_VENDOR_AGERE is not set
|
||||
# CONFIG_NET_VENDOR_ALACRITECH is not set
|
||||
# CONFIG_NET_VENDOR_ALTEON is not set
|
||||
# CONFIG_NET_VENDOR_AMAZON is not set
|
||||
# CONFIG_NET_VENDOR_AMD is not set
|
||||
# CONFIG_NET_VENDOR_AQUANTIA is not set
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||
CONFIG_BNX2=y
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_CAVIUM is not set
|
||||
CONFIG_CHELSIO_T1=m
|
||||
CONFIG_CHELSIO_T1_1G=y
|
||||
CONFIG_CHELSIO_T3=m
|
||||
CONFIG_CHELSIO_T4=m
|
||||
# CONFIG_NET_VENDOR_CIRRUS is not set
|
||||
# CONFIG_NET_VENDOR_CISCO is not set
|
||||
# CONFIG_NET_VENDOR_DEC is not set
|
||||
# CONFIG_NET_VENDOR_DLINK is not set
|
||||
# CONFIG_NET_VENDOR_EMULEX is not set
|
||||
# CONFIG_NET_VENDOR_EZCHIP is not set
|
||||
# CONFIG_NET_VENDOR_I825XX is not set
|
||||
CONFIG_E1000=y
|
||||
CONFIG_E1000E=y
|
||||
CONFIG_IGB=y
|
||||
CONFIG_IXGB=y
|
||||
CONFIG_IXGBE=y
|
||||
# CONFIG_NET_VENDOR_MARVELL is not set
|
||||
# CONFIG_NET_VENDOR_MELLANOX is not set
|
||||
# CONFIG_NET_VENDOR_MICREL is not set
|
||||
# CONFIG_NET_VENDOR_MYRI is not set
|
||||
# CONFIG_NET_VENDOR_NATSEMI is not set
|
||||
# CONFIG_NET_VENDOR_NETRONOME is not set
|
||||
# CONFIG_NET_VENDOR_NVIDIA is not set
|
||||
# CONFIG_NET_VENDOR_OKI is not set
|
||||
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||
# CONFIG_NET_VENDOR_QUALCOMM is not set
|
||||
# CONFIG_NET_VENDOR_RDC is not set
|
||||
CONFIG_8139CP=m
|
||||
CONFIG_8139TOO=m
|
||||
CONFIG_R8169=y
|
||||
# CONFIG_NET_VENDOR_RENESAS is not set
|
||||
# CONFIG_NET_VENDOR_ROCKER is not set
|
||||
# CONFIG_NET_VENDOR_SAMSUNG is not set
|
||||
# CONFIG_NET_VENDOR_SEEQ is not set
|
||||
# CONFIG_NET_VENDOR_SOLARFLARE is not set
|
||||
# CONFIG_NET_VENDOR_SILAN is not set
|
||||
# CONFIG_NET_VENDOR_SIS is not set
|
||||
# CONFIG_NET_VENDOR_SMSC is not set
|
||||
CONFIG_STMMAC_ETH=y
|
||||
# CONFIG_NET_VENDOR_SUN is not set
|
||||
# CONFIG_NET_VENDOR_TEHUTI is not set
|
||||
# CONFIG_NET_VENDOR_TI is not set
|
||||
# CONFIG_NET_VENDOR_VIA is not set
|
||||
# CONFIG_NET_VENDOR_WIZNET is not set
|
||||
# CONFIG_NET_VENDOR_XILINX is not set
|
||||
CONFIG_PPP=m
|
||||
CONFIG_PPP_BSDCOMP=m
|
||||
CONFIG_PPP_DEFLATE=m
|
||||
CONFIG_PPP_FILTER=y
|
||||
CONFIG_PPP_MPPE=m
|
||||
CONFIG_PPP_MULTILINK=y
|
||||
CONFIG_PPPOE=m
|
||||
CONFIG_PPPOL2TP=m
|
||||
CONFIG_PPP_ASYNC=m
|
||||
CONFIG_PPP_SYNC_TTY=m
|
||||
CONFIG_USB_RTL8150=m
|
||||
CONFIG_USB_RTL8152=m
|
||||
# CONFIG_USB_NET_AX8817X is not set
|
||||
# CONFIG_USB_NET_AX88179_178A is not set
|
||||
CONFIG_USB_NET_CDC_EEM=m
|
||||
CONFIG_USB_NET_HUAWEI_CDC_NCM=m
|
||||
CONFIG_USB_NET_CDC_MBIM=m
|
||||
# CONFIG_USB_NET_NET1080 is not set
|
||||
# CONFIG_USB_BELKIN is not set
|
||||
# CONFIG_USB_ARMLINUX is not set
|
||||
# CONFIG_USB_NET_ZAURUS is not set
|
||||
CONFIG_ATH9K=m
|
||||
CONFIG_ATH9K_HTC=m
|
||||
CONFIG_IWLWIFI=m
|
||||
CONFIG_IWLDVM=m
|
||||
CONFIG_IWLMVM=m
|
||||
CONFIG_IWLWIFI_BCAST_FILTERING=y
|
||||
CONFIG_HOSTAP=m
|
||||
CONFIG_MT7601U=m
|
||||
CONFIG_RT2X00=m
|
||||
CONFIG_RT2800USB=m
|
||||
CONFIG_RTL8192CE=m
|
||||
CONFIG_RTL8192SE=m
|
||||
CONFIG_RTL8192DE=m
|
||||
CONFIG_RTL8723AE=m
|
||||
CONFIG_RTL8723BE=m
|
||||
CONFIG_RTL8188EE=m
|
||||
CONFIG_RTL8192EE=m
|
||||
CONFIG_RTL8821AE=m
|
||||
CONFIG_RTL8192CU=m
|
||||
# CONFIG_RTLWIFI_DEBUG is not set
|
||||
CONFIG_RTL8XXXU=m
|
||||
CONFIG_ZD1211RW=m
|
||||
CONFIG_USB_NET_RNDIS_WLAN=m
|
||||
CONFIG_INPUT_MOUSEDEV=y
|
||||
CONFIG_INPUT_MOUSEDEV_PSAUX=y
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
CONFIG_KEYBOARD_XTKBD=m
|
||||
CONFIG_MOUSE_PS2_ELANTECH=y
|
||||
CONFIG_MOUSE_PS2_SENTELIC=y
|
||||
CONFIG_MOUSE_SERIAL=m
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_UINPUT=m
|
||||
CONFIG_SERIO_SERPORT=m
|
||||
CONFIG_SERIO_RAW=m
|
||||
CONFIG_LEGACY_PTY_COUNT=16
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=16
|
||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=16
|
||||
CONFIG_SERIAL_8250_EXTENDED=y
|
||||
CONFIG_SERIAL_8250_MANY_PORTS=y
|
||||
CONFIG_SERIAL_8250_SHARE_IRQ=y
|
||||
CONFIG_SERIAL_8250_RSA=y
|
||||
CONFIG_SERIAL_NONSTANDARD=y
|
||||
CONFIG_PRINTER=m
|
||||
CONFIG_IPMI_HANDLER=m
|
||||
CONFIG_IPMI_DEVICE_INTERFACE=m
|
||||
CONFIG_IPMI_SI=m
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_PIIX4=y
|
||||
CONFIG_I2C_GPIO=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_GPIO_LOONGSON=y
|
||||
CONFIG_SENSORS_LM75=m
|
||||
CONFIG_SENSORS_LM93=m
|
||||
CONFIG_SENSORS_W83795=m
|
||||
CONFIG_SENSORS_W83627HF=m
|
||||
CONFIG_RC_CORE=m
|
||||
CONFIG_LIRC=y
|
||||
CONFIG_RC_DECODERS=y
|
||||
CONFIG_IR_NEC_DECODER=m
|
||||
CONFIG_IR_RC5_DECODER=m
|
||||
CONFIG_IR_RC6_DECODER=m
|
||||
CONFIG_IR_JVC_DECODER=m
|
||||
CONFIG_IR_SONY_DECODER=m
|
||||
CONFIG_IR_SANYO_DECODER=m
|
||||
CONFIG_IR_SHARP_DECODER=m
|
||||
CONFIG_IR_MCE_KBD_DECODER=m
|
||||
CONFIG_IR_XMP_DECODER=m
|
||||
CONFIG_IR_IMON_DECODER=m
|
||||
CONFIG_MEDIA_SUPPORT=m
|
||||
CONFIG_MEDIA_USB_SUPPORT=y
|
||||
CONFIG_USB_VIDEO_CLASS=m
|
||||
CONFIG_MEDIA_PCI_SUPPORT=y
|
||||
CONFIG_VIDEO_BT848=m
|
||||
CONFIG_DVB_BT8XX=m
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_RADEON=m
|
||||
CONFIG_DRM_RADEON_USERPTR=y
|
||||
CONFIG_DRM_AMDGPU=m
|
||||
CONFIG_DRM_AMDGPU_SI=y
|
||||
CONFIG_DRM_AMDGPU_CIK=y
|
||||
CONFIG_DRM_AMDGPU_USERPTR=y
|
||||
CONFIG_DRM_AST=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_EFI=y
|
||||
CONFIG_FB_RADEON=y
|
||||
CONFIG_LCD_PLATFORM=m
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
|
||||
CONFIG_LOGO=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_SND_SEQUENCER=m
|
||||
CONFIG_SND_SEQ_DUMMY=m
|
||||
# CONFIG_SND_ISA is not set
|
||||
CONFIG_SND_BT87X=m
|
||||
CONFIG_SND_BT87X_OVERCLOCK=y
|
||||
CONFIG_SND_HDA_INTEL=y
|
||||
CONFIG_SND_HDA_HWDEP=y
|
||||
CONFIG_SND_HDA_INPUT_BEEP=y
|
||||
CONFIG_SND_HDA_PATCH_LOADER=y
|
||||
CONFIG_SND_HDA_CODEC_REALTEK=y
|
||||
CONFIG_SND_HDA_CODEC_SIGMATEL=y
|
||||
CONFIG_SND_HDA_CODEC_HDMI=y
|
||||
CONFIG_SND_HDA_CODEC_CONEXANT=y
|
||||
CONFIG_SND_USB_AUDIO=m
|
||||
CONFIG_HIDRAW=y
|
||||
CONFIG_UHID=m
|
||||
CONFIG_HID_A4TECH=m
|
||||
CONFIG_HID_CHERRY=m
|
||||
CONFIG_HID_LOGITECH=m
|
||||
CONFIG_HID_LOGITECH_DJ=m
|
||||
CONFIG_LOGITECH_FF=y
|
||||
CONFIG_LOGIRUMBLEPAD2_FF=y
|
||||
CONFIG_LOGIG940_FF=y
|
||||
CONFIG_HID_MICROSOFT=m
|
||||
CONFIG_HID_MULTITOUCH=m
|
||||
CONFIG_HID_SUNPLUS=m
|
||||
CONFIG_USB_HIDDEV=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_OTG=y
|
||||
CONFIG_USB_MON=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_ROOT_HUB_TT=y
|
||||
CONFIG_USB_EHCI_HCD_PLATFORM=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD_PLATFORM=y
|
||||
CONFIG_USB_UHCI_HCD=m
|
||||
CONFIG_USB_ACM=m
|
||||
CONFIG_USB_PRINTER=m
|
||||
CONFIG_USB_STORAGE=m
|
||||
CONFIG_USB_STORAGE_REALTEK=m
|
||||
CONFIG_USB_UAS=m
|
||||
CONFIG_USB_DWC2=y
|
||||
CONFIG_USB_DWC2_HOST=y
|
||||
CONFIG_USB_SERIAL=m
|
||||
CONFIG_USB_SERIAL_CH341=m
|
||||
CONFIG_USB_SERIAL_CP210X=m
|
||||
CONFIG_USB_SERIAL_FTDI_SIO=m
|
||||
CONFIG_USB_SERIAL_PL2303=m
|
||||
CONFIG_USB_SERIAL_OPTION=m
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_INFINIBAND=m
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_EFI=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_UIO=m
|
||||
CONFIG_UIO_PDRV_GENIRQ=m
|
||||
CONFIG_UIO_DMEM_GENIRQ=m
|
||||
CONFIG_UIO_PCI_GENERIC=m
|
||||
# CONFIG_VIRTIO_MENU is not set
|
||||
CONFIG_COMEDI=m
|
||||
CONFIG_COMEDI_PCI_DRIVERS=m
|
||||
CONFIG_COMEDI_8255_PCI=m
|
||||
CONFIG_COMEDI_ADL_PCI6208=m
|
||||
CONFIG_COMEDI_ADL_PCI7X3X=m
|
||||
CONFIG_COMEDI_ADL_PCI8164=m
|
||||
CONFIG_COMEDI_ADL_PCI9111=m
|
||||
CONFIG_COMEDI_ADL_PCI9118=m
|
||||
CONFIG_COMEDI_ADV_PCI1710=m
|
||||
CONFIG_COMEDI_ADV_PCI1720=m
|
||||
CONFIG_COMEDI_ADV_PCI1723=m
|
||||
CONFIG_COMEDI_ADV_PCI1724=m
|
||||
CONFIG_COMEDI_ADV_PCI1760=m
|
||||
CONFIG_COMEDI_ADV_PCI_DIO=m
|
||||
CONFIG_COMEDI_NI_LABPC_PCI=m
|
||||
CONFIG_COMEDI_NI_PCIDIO=m
|
||||
CONFIG_COMEDI_NI_PCIMIO=m
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_R8188EU=m
|
||||
# CONFIG_88EU_AP_MODE is not set
|
||||
CONFIG_PM_DEVFREQ=y
|
||||
CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
|
||||
CONFIG_DEVFREQ_GOV_PERFORMANCE=y
|
||||
CONFIG_DEVFREQ_GOV_POWERSAVE=y
|
||||
CONFIG_DEVFREQ_GOV_USERSPACE=y
|
||||
CONFIG_PWM=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
CONFIG_EXT2_FS_POSIX_ACL=y
|
||||
CONFIG_EXT2_FS_SECURITY=y
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_POSIX_ACL=y
|
||||
CONFIG_EXT3_FS_SECURITY=y
|
||||
CONFIG_XFS_FS=y
|
||||
CONFIG_XFS_QUOTA=y
|
||||
CONFIG_XFS_POSIX_ACL=y
|
||||
CONFIG_BTRFS_FS=y
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
|
||||
CONFIG_QUOTA=y
|
||||
# CONFIG_PRINT_QUOTA_WARNING is not set
|
||||
CONFIG_QFMT_V1=m
|
||||
CONFIG_QFMT_V2=m
|
||||
CONFIG_AUTOFS4_FS=y
|
||||
CONFIG_FUSE_FS=m
|
||||
CONFIG_OVERLAY_FS=y
|
||||
CONFIG_OVERLAY_FS_INDEX=y
|
||||
CONFIG_OVERLAY_FS_XINO_AUTO=y
|
||||
CONFIG_OVERLAY_FS_METACOPY=y
|
||||
CONFIG_FSCACHE=y
|
||||
CONFIG_ISO9660_FS=y
|
||||
CONFIG_JOLIET=y
|
||||
CONFIG_ZISOFS=y
|
||||
CONFIG_UDF_FS=y
|
||||
CONFIG_MSDOS_FS=m
|
||||
CONFIG_VFAT_FS=m
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=936
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="gb2312"
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_TMPFS_POSIX_ACL=y
|
||||
CONFIG_HUGETLBFS=y
|
||||
CONFIG_CONFIGFS_FS=y
|
||||
CONFIG_HFS_FS=m
|
||||
CONFIG_HFSPLUS_FS=m
|
||||
CONFIG_CRAMFS=m
|
||||
CONFIG_SQUASHFS=y
|
||||
CONFIG_SQUASHFS_XATTR=y
|
||||
CONFIG_SQUASHFS_LZ4=y
|
||||
CONFIG_SQUASHFS_LZO=y
|
||||
CONFIG_SQUASHFS_XZ=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_NFS_V4_1=y
|
||||
CONFIG_NFS_V4_2=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
CONFIG_NFSD_V4=y
|
||||
CONFIG_NFSD_BLOCKLAYOUT=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
CONFIG_9P_FS=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_CODEPAGE_936=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_KEY_DH_OPERATIONS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
|
||||
CONFIG_SECURITY_SELINUX_DISABLE=y
|
||||
CONFIG_SECURITY_APPARMOR=y
|
||||
CONFIG_SECURITY_YAMA=y
|
||||
CONFIG_DEFAULT_SECURITY_DAC=y
|
||||
CONFIG_CRYPTO_USER=m
|
||||
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
||||
CONFIG_CRYPTO_PCRYPT=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_CHACHA20POLY1305=m
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPTO_VMAC=m
|
||||
CONFIG_CRYPTO_TGR192=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_ANUBIS=m
|
||||
CONFIG_CRYPTO_BLOWFISH=m
|
||||
CONFIG_CRYPTO_CAST5=m
|
||||
CONFIG_CRYPTO_CAST6=m
|
||||
CONFIG_CRYPTO_KHAZAD=m
|
||||
CONFIG_CRYPTO_SALSA20=m
|
||||
CONFIG_CRYPTO_SEED=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
CONFIG_CRYPTO_TEA=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
CONFIG_CRYPTO_DEFLATE=m
|
||||
CONFIG_CRYPTO_LZO=m
|
||||
CONFIG_CRYPTO_842=m
|
||||
CONFIG_CRYPTO_LZ4=m
|
||||
CONFIG_CRYPTO_LZ4HC=m
|
||||
CONFIG_CRYPTO_USER_API_HASH=m
|
||||
CONFIG_CRYPTO_USER_API_SKCIPHER=m
|
||||
CONFIG_CRYPTO_USER_API_RNG=m
|
||||
CONFIG_CRYPTO_USER_API_AEAD=m
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_STRIP_ASM_SYMS=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_SCHEDSTATS=y
|
||||
# CONFIG_DEBUG_PREEMPT is not set
|
||||
# CONFIG_FTRACE is not set
|
30
arch/loongarch/include/asm/Kbuild
Normal file
30
arch/loongarch/include/asm/Kbuild
Normal file
@ -0,0 +1,30 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
generic-y += dma-contiguous.h
|
||||
generic-y += export.h
|
||||
generic-y += parport.h
|
||||
generic-y += early_ioremap.h
|
||||
generic-y += qrwlock.h
|
||||
generic-y += qrwlock_types.h
|
||||
generic-y += spinlock.h
|
||||
generic-y += spinlock_types.h
|
||||
generic-y += rwsem.h
|
||||
generic-y += segment.h
|
||||
generic-y += user.h
|
||||
generic-y += stat.h
|
||||
generic-y += fcntl.h
|
||||
generic-y += ioctl.h
|
||||
generic-y += ioctls.h
|
||||
generic-y += mman.h
|
||||
generic-y += msgbuf.h
|
||||
generic-y += sembuf.h
|
||||
generic-y += shmbuf.h
|
||||
generic-y += statfs.h
|
||||
generic-y += socket.h
|
||||
generic-y += sockios.h
|
||||
generic-y += termios.h
|
||||
generic-y += termbits.h
|
||||
generic-y += poll.h
|
||||
generic-y += param.h
|
||||
generic-y += posix_types.h
|
||||
generic-y += resource.h
|
||||
generic-y += kvm_para.h
|
18
arch/loongarch/include/asm/acenv.h
Normal file
18
arch/loongarch/include/asm/acenv.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* LoongArch specific ACPICA environments and implementation
|
||||
*
|
||||
* Author: Jianmin Lv <lvjianmin@loongson.cn>
|
||||
* Huacai Chen <chenhuacai@loongson.cn>
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _ASM_LOONGARCH_ACENV_H
|
||||
#define _ASM_LOONGARCH_ACENV_H
|
||||
|
||||
/*
|
||||
* This header is required by ACPI core, but we have nothing to fill in
|
||||
* right now. Will be updated later when needed.
|
||||
*/
|
||||
|
||||
#endif /* _ASM_LOONGARCH_ACENV_H */
|
38
arch/loongarch/include/asm/acpi.h
Normal file
38
arch/loongarch/include/asm/acpi.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Author: Jianmin Lv <lvjianmin@loongson.cn>
|
||||
* Huacai Chen <chenhuacai@loongson.cn>
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _ASM_LOONGARCH_ACPI_H
|
||||
#define _ASM_LOONGARCH_ACPI_H
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
extern int acpi_strict;
|
||||
extern int acpi_disabled;
|
||||
extern int acpi_pci_disabled;
|
||||
extern int acpi_noirq;
|
||||
|
||||
#define acpi_os_ioremap acpi_os_ioremap
|
||||
void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
|
||||
|
||||
static inline void disable_acpi(void)
|
||||
{
|
||||
acpi_disabled = 1;
|
||||
acpi_pci_disabled = 1;
|
||||
acpi_noirq = 1;
|
||||
}
|
||||
|
||||
static inline bool acpi_has_cpu_in_madt(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
extern struct list_head acpi_wakeup_device_list;
|
||||
|
||||
#endif /* !CONFIG_ACPI */
|
||||
|
||||
#define ACPI_TABLE_UPGRADE_MAX_PHYS ARCH_LOW_ADDRESS_LIMIT
|
||||
|
||||
#endif /* _ASM_LOONGARCH_ACPI_H */
|
112
arch/loongarch/include/asm/addrspace.h
Normal file
112
arch/loongarch/include/asm/addrspace.h
Normal file
@ -0,0 +1,112 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*
|
||||
* Derived from MIPS:
|
||||
* Copyright (C) 1996, 99 Ralf Baechle
|
||||
* Copyright (C) 2000, 2002 Maciej W. Rozycki
|
||||
* Copyright (C) 1990, 1999 by Silicon Graphics, Inc.
|
||||
*/
|
||||
#ifndef _ASM_ADDRSPACE_H
|
||||
#define _ASM_ADDRSPACE_H
|
||||
|
||||
#include <linux/const.h>
|
||||
|
||||
#include <asm/loongarch.h>
|
||||
|
||||
/*
|
||||
* This gives the physical RAM offset.
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef PHYS_OFFSET
|
||||
#define PHYS_OFFSET _AC(0, UL)
|
||||
#endif
|
||||
extern unsigned long vm_map_base;
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#ifndef IO_BASE
|
||||
#define IO_BASE CSR_DMW0_BASE
|
||||
#endif
|
||||
|
||||
#ifndef CACHE_BASE
|
||||
#define CACHE_BASE CSR_DMW1_BASE
|
||||
#endif
|
||||
|
||||
#ifndef UNCACHE_BASE
|
||||
#define UNCACHE_BASE CSR_DMW0_BASE
|
||||
#endif
|
||||
|
||||
#define DMW_PABITS 48
|
||||
#define TO_PHYS_MASK ((1ULL << DMW_PABITS) - 1)
|
||||
|
||||
/*
|
||||
* Memory above this physical address will be considered highmem.
|
||||
*/
|
||||
#ifndef HIGHMEM_START
|
||||
#define HIGHMEM_START (_AC(1, UL) << _AC(DMW_PABITS, UL))
|
||||
#endif
|
||||
|
||||
#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
|
||||
#define TO_CACHE(x) (CACHE_BASE | ((x) & TO_PHYS_MASK))
|
||||
#define TO_UNCACHE(x) (UNCACHE_BASE | ((x) & TO_PHYS_MASK))
|
||||
|
||||
/*
|
||||
* This handles the memory map.
|
||||
*/
|
||||
#ifndef PAGE_OFFSET
|
||||
#define PAGE_OFFSET (CACHE_BASE + PHYS_OFFSET)
|
||||
#endif
|
||||
|
||||
#ifndef FIXADDR_TOP
|
||||
#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000)
|
||||
#endif
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define _ATYPE_
|
||||
#define _ATYPE32_
|
||||
#define _ATYPE64_
|
||||
#define _CONST64_(x) x
|
||||
#else
|
||||
#define _ATYPE_ __PTRDIFF_TYPE__
|
||||
#define _ATYPE32_ int
|
||||
#define _ATYPE64_ __s64
|
||||
#ifdef CONFIG_64BIT
|
||||
#define _CONST64_(x) x ## L
|
||||
#else
|
||||
#define _CONST64_(x) x ## LL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 32/64-bit LoongArch address spaces
|
||||
*/
|
||||
#ifdef __ASSEMBLY__
|
||||
#define _ACAST32_
|
||||
#define _ACAST64_
|
||||
#else
|
||||
#define _ACAST32_ (_ATYPE_)(_ATYPE32_) /* widen if necessary */
|
||||
#define _ACAST64_ (_ATYPE64_) /* do _not_ narrow */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
|
||||
#define UVRANGE 0x00000000
|
||||
#define KPRANGE0 0x80000000
|
||||
#define KPRANGE1 0xa0000000
|
||||
#define KVRANGE 0xc0000000
|
||||
|
||||
#else
|
||||
|
||||
#define XUVRANGE _CONST64_(0x0000000000000000)
|
||||
#define XSPRANGE _CONST64_(0x4000000000000000)
|
||||
#define XKPRANGE _CONST64_(0x8000000000000000)
|
||||
#define XKVRANGE _CONST64_(0xc000000000000000)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns the physical address of a KPRANGEx / XKPRANGE address
|
||||
*/
|
||||
#define PHYSADDR(a) ((_ACAST64_(a)) & TO_PHYS_MASK)
|
||||
|
||||
#endif /* _ASM_ADDRSPACE_H */
|
5
arch/loongarch/include/asm/asm-offsets.h
Normal file
5
arch/loongarch/include/asm/asm-offsets.h
Normal file
@ -0,0 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#include <generated/asm-offsets.h>
|
7
arch/loongarch/include/asm/asm-prototypes.h
Normal file
7
arch/loongarch/include/asm/asm-prototypes.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm-generic/asm-prototypes.h>
|
191
arch/loongarch/include/asm/asm.h
Normal file
191
arch/loongarch/include/asm/asm.h
Normal file
@ -0,0 +1,191 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Some useful macros for LoongArch assembler code
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*
|
||||
* Derived from MIPS:
|
||||
* Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle
|
||||
* Copyright (C) 1999 by Silicon Graphics, Inc.
|
||||
* Copyright (C) 2001 MIPS Technologies, Inc.
|
||||
* Copyright (C) 2002 Maciej W. Rozycki
|
||||
*/
|
||||
#ifndef __ASM_ASM_H
|
||||
#define __ASM_ASM_H
|
||||
|
||||
/* LoongArch pref instruction. */
|
||||
#ifdef CONFIG_CPU_HAS_PREFETCH
|
||||
|
||||
#define PREF(hint, addr, offs) \
|
||||
preld hint, addr, offs; \
|
||||
|
||||
#define PREFX(hint, addr, index) \
|
||||
preldx hint, addr, index; \
|
||||
|
||||
#else /* !CONFIG_CPU_HAS_PREFETCH */
|
||||
|
||||
#define PREF(hint, addr, offs)
|
||||
#define PREFX(hint, addr, index)
|
||||
|
||||
#endif /* !CONFIG_CPU_HAS_PREFETCH */
|
||||
|
||||
/*
|
||||
* Stack alignment
|
||||
*/
|
||||
#define STACK_ALIGN ~(0xf)
|
||||
|
||||
/*
|
||||
* Macros to handle different pointer/register sizes for 32/64-bit code
|
||||
*/
|
||||
|
||||
/*
|
||||
* Size of a register
|
||||
*/
|
||||
#ifndef __loongarch64
|
||||
#define SZREG 4
|
||||
#else
|
||||
#define SZREG 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use the following macros in assemblercode to load/store registers,
|
||||
* pointers etc.
|
||||
*/
|
||||
#if (SZREG == 4)
|
||||
#define REG_L ld.w
|
||||
#define REG_S st.w
|
||||
#define REG_ADD add.w
|
||||
#define REG_SUB sub.w
|
||||
#else /* SZREG == 8 */
|
||||
#define REG_L ld.d
|
||||
#define REG_S st.d
|
||||
#define REG_ADD add.d
|
||||
#define REG_SUB sub.d
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How to add/sub/load/store/shift C int variables.
|
||||
*/
|
||||
#if (__SIZEOF_INT__ == 4)
|
||||
#define INT_ADD add.w
|
||||
#define INT_ADDI addi.w
|
||||
#define INT_SUB sub.w
|
||||
#define INT_L ld.w
|
||||
#define INT_S st.w
|
||||
#define INT_SLL slli.w
|
||||
#define INT_SLLV sll.w
|
||||
#define INT_SRL srli.w
|
||||
#define INT_SRLV srl.w
|
||||
#define INT_SRA srai.w
|
||||
#define INT_SRAV sra.w
|
||||
#endif
|
||||
|
||||
#if (__SIZEOF_INT__ == 8)
|
||||
#define INT_ADD add.d
|
||||
#define INT_ADDI addi.d
|
||||
#define INT_SUB sub.d
|
||||
#define INT_L ld.d
|
||||
#define INT_S st.d
|
||||
#define INT_SLL slli.d
|
||||
#define INT_SLLV sll.d
|
||||
#define INT_SRL srli.d
|
||||
#define INT_SRLV srl.d
|
||||
#define INT_SRA srai.d
|
||||
#define INT_SRAV sra.d
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How to add/sub/load/store/shift C long variables.
|
||||
*/
|
||||
#if (__SIZEOF_LONG__ == 4)
|
||||
#define LONG_ADD add.w
|
||||
#define LONG_ADDI addi.w
|
||||
#define LONG_SUB sub.w
|
||||
#define LONG_L ld.w
|
||||
#define LONG_S st.w
|
||||
#define LONG_SLL slli.w
|
||||
#define LONG_SLLV sll.w
|
||||
#define LONG_SRL srli.w
|
||||
#define LONG_SRLV srl.w
|
||||
#define LONG_SRA srai.w
|
||||
#define LONG_SRAV sra.w
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define LONG .word
|
||||
#endif
|
||||
#define LONGSIZE 4
|
||||
#define LONGMASK 3
|
||||
#define LONGLOG 2
|
||||
#endif
|
||||
|
||||
#if (__SIZEOF_LONG__ == 8)
|
||||
#define LONG_ADD add.d
|
||||
#define LONG_ADDI addi.d
|
||||
#define LONG_SUB sub.d
|
||||
#define LONG_L ld.d
|
||||
#define LONG_S st.d
|
||||
#define LONG_SLL slli.d
|
||||
#define LONG_SLLV sll.d
|
||||
#define LONG_SRL srli.d
|
||||
#define LONG_SRLV srl.d
|
||||
#define LONG_SRA srai.d
|
||||
#define LONG_SRAV sra.d
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define LONG .dword
|
||||
#endif
|
||||
#define LONGSIZE 8
|
||||
#define LONGMASK 7
|
||||
#define LONGLOG 3
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How to add/sub/load/store/shift pointers.
|
||||
*/
|
||||
#if (__SIZEOF_POINTER__ == 4)
|
||||
#define PTR_ADD add.w
|
||||
#define PTR_ADDI addi.w
|
||||
#define PTR_SUB sub.w
|
||||
#define PTR_L ld.w
|
||||
#define PTR_S st.w
|
||||
#define PTR_LI li.w
|
||||
#define PTR_SLL slli.w
|
||||
#define PTR_SLLV sll.w
|
||||
#define PTR_SRL srli.w
|
||||
#define PTR_SRLV srl.w
|
||||
#define PTR_SRA srai.w
|
||||
#define PTR_SRAV sra.w
|
||||
|
||||
#define PTR_SCALESHIFT 2
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define PTR .word
|
||||
#endif
|
||||
#define PTRSIZE 4
|
||||
#define PTRLOG 2
|
||||
#endif
|
||||
|
||||
#if (__SIZEOF_POINTER__ == 8)
|
||||
#define PTR_ADD add.d
|
||||
#define PTR_ADDI addi.d
|
||||
#define PTR_SUB sub.d
|
||||
#define PTR_L ld.d
|
||||
#define PTR_S st.d
|
||||
#define PTR_LI li.d
|
||||
#define PTR_SLL slli.d
|
||||
#define PTR_SLLV sll.d
|
||||
#define PTR_SRL srli.d
|
||||
#define PTR_SRLV srl.d
|
||||
#define PTR_SRA srai.d
|
||||
#define PTR_SRAV sra.d
|
||||
|
||||
#define PTR_SCALESHIFT 3
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define PTR .dword
|
||||
#endif
|
||||
#define PTRSIZE 8
|
||||
#define PTRLOG 3
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_ASM_H */
|
289
arch/loongarch/include/asm/asmmacro.h
Normal file
289
arch/loongarch/include/asm/asmmacro.h
Normal file
@ -0,0 +1,289 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_ASMMACRO_H
|
||||
#define _ASM_ASMMACRO_H
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/fpregdef.h>
|
||||
#include <asm/loongarch.h>
|
||||
|
||||
.macro parse_v var val
|
||||
\var = \val
|
||||
.endm
|
||||
|
||||
.macro parse_r var r
|
||||
\var = -1
|
||||
.ifc \r, $r0
|
||||
\var = 0
|
||||
.endif
|
||||
.ifc \r, $r1
|
||||
\var = 1
|
||||
.endif
|
||||
.ifc \r, $r2
|
||||
\var = 2
|
||||
.endif
|
||||
.ifc \r, $r3
|
||||
\var = 3
|
||||
.endif
|
||||
.ifc \r, $r4
|
||||
\var = 4
|
||||
.endif
|
||||
.ifc \r, $r5
|
||||
\var = 5
|
||||
.endif
|
||||
.ifc \r, $r6
|
||||
\var = 6
|
||||
.endif
|
||||
.ifc \r, $r7
|
||||
\var = 7
|
||||
.endif
|
||||
.ifc \r, $r8
|
||||
\var = 8
|
||||
.endif
|
||||
.ifc \r, $r9
|
||||
\var = 9
|
||||
.endif
|
||||
.ifc \r, $r10
|
||||
\var = 10
|
||||
.endif
|
||||
.ifc \r, $r11
|
||||
\var = 11
|
||||
.endif
|
||||
.ifc \r, $r12
|
||||
\var = 12
|
||||
.endif
|
||||
.ifc \r, $r13
|
||||
\var = 13
|
||||
.endif
|
||||
.ifc \r, $r14
|
||||
\var = 14
|
||||
.endif
|
||||
.ifc \r, $r15
|
||||
\var = 15
|
||||
.endif
|
||||
.ifc \r, $r16
|
||||
\var = 16
|
||||
.endif
|
||||
.ifc \r, $r17
|
||||
\var = 17
|
||||
.endif
|
||||
.ifc \r, $r18
|
||||
\var = 18
|
||||
.endif
|
||||
.ifc \r, $r19
|
||||
\var = 19
|
||||
.endif
|
||||
.ifc \r, $r20
|
||||
\var = 20
|
||||
.endif
|
||||
.ifc \r, $r21
|
||||
\var = 21
|
||||
.endif
|
||||
.ifc \r, $r22
|
||||
\var = 22
|
||||
.endif
|
||||
.ifc \r, $r23
|
||||
\var = 23
|
||||
.endif
|
||||
.ifc \r, $r24
|
||||
\var = 24
|
||||
.endif
|
||||
.ifc \r, $r25
|
||||
\var = 25
|
||||
.endif
|
||||
.ifc \r, $r26
|
||||
\var = 26
|
||||
.endif
|
||||
.ifc \r, $r27
|
||||
\var = 27
|
||||
.endif
|
||||
.ifc \r, $r28
|
||||
\var = 28
|
||||
.endif
|
||||
.ifc \r, $r29
|
||||
\var = 29
|
||||
.endif
|
||||
.ifc \r, $r30
|
||||
\var = 30
|
||||
.endif
|
||||
.ifc \r, $r31
|
||||
\var = 31
|
||||
.endif
|
||||
.iflt \var
|
||||
.error "Unable to parse register name \r"
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro cpu_save_nonscratch thread
|
||||
stptr.d s0, \thread, THREAD_REG23
|
||||
stptr.d s1, \thread, THREAD_REG24
|
||||
stptr.d s2, \thread, THREAD_REG25
|
||||
stptr.d s3, \thread, THREAD_REG26
|
||||
stptr.d s4, \thread, THREAD_REG27
|
||||
stptr.d s5, \thread, THREAD_REG28
|
||||
stptr.d s6, \thread, THREAD_REG29
|
||||
stptr.d s7, \thread, THREAD_REG30
|
||||
stptr.d s8, \thread, THREAD_REG31
|
||||
stptr.d sp, \thread, THREAD_REG03
|
||||
stptr.d fp, \thread, THREAD_REG22
|
||||
.endm
|
||||
|
||||
.macro cpu_restore_nonscratch thread
|
||||
ldptr.d s0, \thread, THREAD_REG23
|
||||
ldptr.d s1, \thread, THREAD_REG24
|
||||
ldptr.d s2, \thread, THREAD_REG25
|
||||
ldptr.d s3, \thread, THREAD_REG26
|
||||
ldptr.d s4, \thread, THREAD_REG27
|
||||
ldptr.d s5, \thread, THREAD_REG28
|
||||
ldptr.d s6, \thread, THREAD_REG29
|
||||
ldptr.d s7, \thread, THREAD_REG30
|
||||
ldptr.d s8, \thread, THREAD_REG31
|
||||
ldptr.d ra, \thread, THREAD_REG01
|
||||
ldptr.d sp, \thread, THREAD_REG03
|
||||
ldptr.d fp, \thread, THREAD_REG22
|
||||
.endm
|
||||
|
||||
.macro fpu_save_csr thread tmp
|
||||
movfcsr2gr \tmp, fcsr0
|
||||
stptr.w \tmp, \thread, THREAD_FCSR
|
||||
.endm
|
||||
|
||||
.macro fpu_restore_csr thread tmp
|
||||
ldptr.w \tmp, \thread, THREAD_FCSR
|
||||
movgr2fcsr fcsr0, \tmp
|
||||
.endm
|
||||
|
||||
.macro fpu_save_cc thread tmp0 tmp1
|
||||
movcf2gr \tmp0, $fcc0
|
||||
move \tmp1, \tmp0
|
||||
movcf2gr \tmp0, $fcc1
|
||||
bstrins.d \tmp1, \tmp0, 15, 8
|
||||
movcf2gr \tmp0, $fcc2
|
||||
bstrins.d \tmp1, \tmp0, 23, 16
|
||||
movcf2gr \tmp0, $fcc3
|
||||
bstrins.d \tmp1, \tmp0, 31, 24
|
||||
movcf2gr \tmp0, $fcc4
|
||||
bstrins.d \tmp1, \tmp0, 39, 32
|
||||
movcf2gr \tmp0, $fcc5
|
||||
bstrins.d \tmp1, \tmp0, 47, 40
|
||||
movcf2gr \tmp0, $fcc6
|
||||
bstrins.d \tmp1, \tmp0, 55, 48
|
||||
movcf2gr \tmp0, $fcc7
|
||||
bstrins.d \tmp1, \tmp0, 63, 56
|
||||
stptr.d \tmp1, \thread, THREAD_FCC
|
||||
.endm
|
||||
|
||||
.macro fpu_restore_cc thread tmp0 tmp1
|
||||
ldptr.d \tmp0, \thread, THREAD_FCC
|
||||
bstrpick.d \tmp1, \tmp0, 7, 0
|
||||
movgr2cf $fcc0, \tmp1
|
||||
bstrpick.d \tmp1, \tmp0, 15, 8
|
||||
movgr2cf $fcc1, \tmp1
|
||||
bstrpick.d \tmp1, \tmp0, 23, 16
|
||||
movgr2cf $fcc2, \tmp1
|
||||
bstrpick.d \tmp1, \tmp0, 31, 24
|
||||
movgr2cf $fcc3, \tmp1
|
||||
bstrpick.d \tmp1, \tmp0, 39, 32
|
||||
movgr2cf $fcc4, \tmp1
|
||||
bstrpick.d \tmp1, \tmp0, 47, 40
|
||||
movgr2cf $fcc5, \tmp1
|
||||
bstrpick.d \tmp1, \tmp0, 55, 48
|
||||
movgr2cf $fcc6, \tmp1
|
||||
bstrpick.d \tmp1, \tmp0, 63, 56
|
||||
movgr2cf $fcc7, \tmp1
|
||||
.endm
|
||||
|
||||
.macro fpu_save_double thread tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \tmp, \tmp, \thread
|
||||
fst.d $f0, \tmp, THREAD_FPR0 - THREAD_FPR0
|
||||
fst.d $f1, \tmp, THREAD_FPR1 - THREAD_FPR0
|
||||
fst.d $f2, \tmp, THREAD_FPR2 - THREAD_FPR0
|
||||
fst.d $f3, \tmp, THREAD_FPR3 - THREAD_FPR0
|
||||
fst.d $f4, \tmp, THREAD_FPR4 - THREAD_FPR0
|
||||
fst.d $f5, \tmp, THREAD_FPR5 - THREAD_FPR0
|
||||
fst.d $f6, \tmp, THREAD_FPR6 - THREAD_FPR0
|
||||
fst.d $f7, \tmp, THREAD_FPR7 - THREAD_FPR0
|
||||
fst.d $f8, \tmp, THREAD_FPR8 - THREAD_FPR0
|
||||
fst.d $f9, \tmp, THREAD_FPR9 - THREAD_FPR0
|
||||
fst.d $f10, \tmp, THREAD_FPR10 - THREAD_FPR0
|
||||
fst.d $f11, \tmp, THREAD_FPR11 - THREAD_FPR0
|
||||
fst.d $f12, \tmp, THREAD_FPR12 - THREAD_FPR0
|
||||
fst.d $f13, \tmp, THREAD_FPR13 - THREAD_FPR0
|
||||
fst.d $f14, \tmp, THREAD_FPR14 - THREAD_FPR0
|
||||
fst.d $f15, \tmp, THREAD_FPR15 - THREAD_FPR0
|
||||
fst.d $f16, \tmp, THREAD_FPR16 - THREAD_FPR0
|
||||
fst.d $f17, \tmp, THREAD_FPR17 - THREAD_FPR0
|
||||
fst.d $f18, \tmp, THREAD_FPR18 - THREAD_FPR0
|
||||
fst.d $f19, \tmp, THREAD_FPR19 - THREAD_FPR0
|
||||
fst.d $f20, \tmp, THREAD_FPR20 - THREAD_FPR0
|
||||
fst.d $f21, \tmp, THREAD_FPR21 - THREAD_FPR0
|
||||
fst.d $f22, \tmp, THREAD_FPR22 - THREAD_FPR0
|
||||
fst.d $f23, \tmp, THREAD_FPR23 - THREAD_FPR0
|
||||
fst.d $f24, \tmp, THREAD_FPR24 - THREAD_FPR0
|
||||
fst.d $f25, \tmp, THREAD_FPR25 - THREAD_FPR0
|
||||
fst.d $f26, \tmp, THREAD_FPR26 - THREAD_FPR0
|
||||
fst.d $f27, \tmp, THREAD_FPR27 - THREAD_FPR0
|
||||
fst.d $f28, \tmp, THREAD_FPR28 - THREAD_FPR0
|
||||
fst.d $f29, \tmp, THREAD_FPR29 - THREAD_FPR0
|
||||
fst.d $f30, \tmp, THREAD_FPR30 - THREAD_FPR0
|
||||
fst.d $f31, \tmp, THREAD_FPR31 - THREAD_FPR0
|
||||
.endm
|
||||
|
||||
.macro fpu_restore_double thread tmp
|
||||
li.w \tmp, THREAD_FPR0
|
||||
PTR_ADD \tmp, \tmp, \thread
|
||||
fld.d $f0, \tmp, THREAD_FPR0 - THREAD_FPR0
|
||||
fld.d $f1, \tmp, THREAD_FPR1 - THREAD_FPR0
|
||||
fld.d $f2, \tmp, THREAD_FPR2 - THREAD_FPR0
|
||||
fld.d $f3, \tmp, THREAD_FPR3 - THREAD_FPR0
|
||||
fld.d $f4, \tmp, THREAD_FPR4 - THREAD_FPR0
|
||||
fld.d $f5, \tmp, THREAD_FPR5 - THREAD_FPR0
|
||||
fld.d $f6, \tmp, THREAD_FPR6 - THREAD_FPR0
|
||||
fld.d $f7, \tmp, THREAD_FPR7 - THREAD_FPR0
|
||||
fld.d $f8, \tmp, THREAD_FPR8 - THREAD_FPR0
|
||||
fld.d $f9, \tmp, THREAD_FPR9 - THREAD_FPR0
|
||||
fld.d $f10, \tmp, THREAD_FPR10 - THREAD_FPR0
|
||||
fld.d $f11, \tmp, THREAD_FPR11 - THREAD_FPR0
|
||||
fld.d $f12, \tmp, THREAD_FPR12 - THREAD_FPR0
|
||||
fld.d $f13, \tmp, THREAD_FPR13 - THREAD_FPR0
|
||||
fld.d $f14, \tmp, THREAD_FPR14 - THREAD_FPR0
|
||||
fld.d $f15, \tmp, THREAD_FPR15 - THREAD_FPR0
|
||||
fld.d $f16, \tmp, THREAD_FPR16 - THREAD_FPR0
|
||||
fld.d $f17, \tmp, THREAD_FPR17 - THREAD_FPR0
|
||||
fld.d $f18, \tmp, THREAD_FPR18 - THREAD_FPR0
|
||||
fld.d $f19, \tmp, THREAD_FPR19 - THREAD_FPR0
|
||||
fld.d $f20, \tmp, THREAD_FPR20 - THREAD_FPR0
|
||||
fld.d $f21, \tmp, THREAD_FPR21 - THREAD_FPR0
|
||||
fld.d $f22, \tmp, THREAD_FPR22 - THREAD_FPR0
|
||||
fld.d $f23, \tmp, THREAD_FPR23 - THREAD_FPR0
|
||||
fld.d $f24, \tmp, THREAD_FPR24 - THREAD_FPR0
|
||||
fld.d $f25, \tmp, THREAD_FPR25 - THREAD_FPR0
|
||||
fld.d $f26, \tmp, THREAD_FPR26 - THREAD_FPR0
|
||||
fld.d $f27, \tmp, THREAD_FPR27 - THREAD_FPR0
|
||||
fld.d $f28, \tmp, THREAD_FPR28 - THREAD_FPR0
|
||||
fld.d $f29, \tmp, THREAD_FPR29 - THREAD_FPR0
|
||||
fld.d $f30, \tmp, THREAD_FPR30 - THREAD_FPR0
|
||||
fld.d $f31, \tmp, THREAD_FPR31 - THREAD_FPR0
|
||||
.endm
|
||||
|
||||
.macro not dst src
|
||||
nor \dst, \src, zero
|
||||
.endm
|
||||
|
||||
.macro bgt r0 r1 label
|
||||
blt \r1, \r0, \label
|
||||
.endm
|
||||
|
||||
.macro bltz r0 label
|
||||
blt \r0, zero, \label
|
||||
.endm
|
||||
|
||||
.macro bgez r0 label
|
||||
bge \r0, zero, \label
|
||||
.endm
|
||||
|
||||
#endif /* _ASM_ASMMACRO_H */
|
362
arch/loongarch/include/asm/atomic.h
Normal file
362
arch/loongarch/include/asm/atomic.h
Normal file
@ -0,0 +1,362 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Atomic operations.
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_ATOMIC_H
|
||||
#define _ASM_ATOMIC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/cmpxchg.h>
|
||||
#include <asm/compiler.h>
|
||||
|
||||
#if __SIZEOF_LONG__ == 4
|
||||
#define __LL "ll.w "
|
||||
#define __SC "sc.w "
|
||||
#define __AMADD "amadd.w "
|
||||
#define __AMAND_DB "amand_db.w "
|
||||
#define __AMOR_DB "amor_db.w "
|
||||
#define __AMXOR_DB "amxor_db.w "
|
||||
#elif __SIZEOF_LONG__ == 8
|
||||
#define __LL "ll.d "
|
||||
#define __SC "sc.d "
|
||||
#define __AMADD "amadd.d "
|
||||
#define __AMAND_DB "amand_db.d "
|
||||
#define __AMOR_DB "amor_db.d "
|
||||
#define __AMXOR_DB "amxor_db.d "
|
||||
#endif
|
||||
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
/*
|
||||
* arch_atomic_read - read atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically reads the value of @v.
|
||||
*/
|
||||
#define arch_atomic_read(v) READ_ONCE((v)->counter)
|
||||
|
||||
/*
|
||||
* arch_atomic_set - set atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i.
|
||||
*/
|
||||
#define arch_atomic_set(v, i) WRITE_ONCE((v)->counter, (i))
|
||||
|
||||
#define ATOMIC_OP(op, I, asm_op) \
|
||||
static inline void arch_atomic_##op(int i, atomic_t *v) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"am"#asm_op"_db.w" " $zero, %1, %0 \n" \
|
||||
: "+ZB" (v->counter) \
|
||||
: "r" (I) \
|
||||
: "memory"); \
|
||||
}
|
||||
|
||||
#define ATOMIC_OP_RETURN(op, I, asm_op, c_op) \
|
||||
static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \
|
||||
{ \
|
||||
int result; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
"am"#asm_op"_db.w" " %1, %2, %0 \n" \
|
||||
: "+ZB" (v->counter), "=&r" (result) \
|
||||
: "r" (I) \
|
||||
: "memory"); \
|
||||
\
|
||||
return result c_op I; \
|
||||
}
|
||||
|
||||
#define ATOMIC_FETCH_OP(op, I, asm_op) \
|
||||
static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \
|
||||
{ \
|
||||
int result; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
"am"#asm_op"_db.w" " %1, %2, %0 \n" \
|
||||
: "+ZB" (v->counter), "=&r" (result) \
|
||||
: "r" (I) \
|
||||
: "memory"); \
|
||||
\
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ATOMIC_OPS(op, I, asm_op, c_op) \
|
||||
ATOMIC_OP(op, I, asm_op) \
|
||||
ATOMIC_OP_RETURN(op, I, asm_op, c_op) \
|
||||
ATOMIC_FETCH_OP(op, I, asm_op)
|
||||
|
||||
ATOMIC_OPS(add, i, add, +)
|
||||
ATOMIC_OPS(sub, -i, add, +)
|
||||
|
||||
#define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed
|
||||
#define arch_atomic_sub_return_relaxed arch_atomic_sub_return_relaxed
|
||||
#define arch_atomic_fetch_add_relaxed arch_atomic_fetch_add_relaxed
|
||||
#define arch_atomic_fetch_sub_relaxed arch_atomic_fetch_sub_relaxed
|
||||
|
||||
#undef ATOMIC_OPS
|
||||
|
||||
#define ATOMIC_OPS(op, I, asm_op) \
|
||||
ATOMIC_OP(op, I, asm_op) \
|
||||
ATOMIC_FETCH_OP(op, I, asm_op)
|
||||
|
||||
ATOMIC_OPS(and, i, and)
|
||||
ATOMIC_OPS(or, i, or)
|
||||
ATOMIC_OPS(xor, i, xor)
|
||||
|
||||
#define arch_atomic_fetch_and_relaxed arch_atomic_fetch_and_relaxed
|
||||
#define arch_atomic_fetch_or_relaxed arch_atomic_fetch_or_relaxed
|
||||
#define arch_atomic_fetch_xor_relaxed arch_atomic_fetch_xor_relaxed
|
||||
|
||||
#undef ATOMIC_OPS
|
||||
#undef ATOMIC_FETCH_OP
|
||||
#undef ATOMIC_OP_RETURN
|
||||
#undef ATOMIC_OP
|
||||
|
||||
static inline int arch_atomic_fetch_add_unless(atomic_t *v, int a, int u)
|
||||
{
|
||||
int prev, rc;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"0: ll.w %[p], %[c]\n"
|
||||
" beq %[p], %[u], 1f\n"
|
||||
" add.w %[rc], %[p], %[a]\n"
|
||||
" sc.w %[rc], %[c]\n"
|
||||
" beqz %[rc], 0b\n"
|
||||
" b 2f\n"
|
||||
"1:\n"
|
||||
__WEAK_LLSC_MB
|
||||
"2:\n"
|
||||
: [p]"=&r" (prev), [rc]"=&r" (rc),
|
||||
[c]"=ZB" (v->counter)
|
||||
: [a]"r" (a), [u]"r" (u)
|
||||
: "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
#define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless
|
||||
|
||||
/*
|
||||
* arch_atomic_sub_if_positive - conditionally subtract integer from atomic variable
|
||||
* @i: integer value to subtract
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically test @v and subtract @i if @v is greater or equal than @i.
|
||||
* The function returns the old value of @v minus @i.
|
||||
*/
|
||||
static inline int arch_atomic_sub_if_positive(int i, atomic_t *v)
|
||||
{
|
||||
int result;
|
||||
int temp;
|
||||
|
||||
if (__builtin_constant_p(i)) {
|
||||
__asm__ __volatile__(
|
||||
"1: ll.w %1, %2 # atomic_sub_if_positive\n"
|
||||
" addi.w %0, %1, %3 \n"
|
||||
" or %1, %0, $zero \n"
|
||||
" blt %0, $zero, 2f \n"
|
||||
" sc.w %1, %2 \n"
|
||||
" beq $zero, %1, 1b \n"
|
||||
"2: \n"
|
||||
__WEAK_LLSC_MB
|
||||
: "=&r" (result), "=&r" (temp),
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||
: "I" (-i));
|
||||
} else {
|
||||
__asm__ __volatile__(
|
||||
"1: ll.w %1, %2 # atomic_sub_if_positive\n"
|
||||
" sub.w %0, %1, %3 \n"
|
||||
" or %1, %0, $zero \n"
|
||||
" blt %0, $zero, 2f \n"
|
||||
" sc.w %1, %2 \n"
|
||||
" beq $zero, %1, 1b \n"
|
||||
"2: \n"
|
||||
__WEAK_LLSC_MB
|
||||
: "=&r" (result), "=&r" (temp),
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||
: "r" (i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define arch_atomic_cmpxchg(v, o, n) (arch_cmpxchg(&((v)->counter), (o), (n)))
|
||||
#define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), (new)))
|
||||
|
||||
/*
|
||||
* arch_atomic_dec_if_positive - decrement by 1 if old value positive
|
||||
* @v: pointer of type atomic_t
|
||||
*/
|
||||
#define arch_atomic_dec_if_positive(v) arch_atomic_sub_if_positive(1, v)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
#define ATOMIC64_INIT(i) { (i) }
|
||||
|
||||
/*
|
||||
* arch_atomic64_read - read atomic variable
|
||||
* @v: pointer of type atomic64_t
|
||||
*
|
||||
*/
|
||||
#define arch_atomic64_read(v) READ_ONCE((v)->counter)
|
||||
|
||||
/*
|
||||
* arch_atomic64_set - set atomic variable
|
||||
* @v: pointer of type atomic64_t
|
||||
* @i: required value
|
||||
*/
|
||||
#define arch_atomic64_set(v, i) WRITE_ONCE((v)->counter, (i))
|
||||
|
||||
#define ATOMIC64_OP(op, I, asm_op) \
|
||||
static inline void arch_atomic64_##op(long i, atomic64_t *v) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"am"#asm_op"_db.d " " $zero, %1, %0 \n" \
|
||||
: "+ZB" (v->counter) \
|
||||
: "r" (I) \
|
||||
: "memory"); \
|
||||
}
|
||||
|
||||
#define ATOMIC64_OP_RETURN(op, I, asm_op, c_op) \
|
||||
static inline long arch_atomic64_##op##_return_relaxed(long i, atomic64_t *v) \
|
||||
{ \
|
||||
long result; \
|
||||
__asm__ __volatile__( \
|
||||
"am"#asm_op"_db.d " " %1, %2, %0 \n" \
|
||||
: "+ZB" (v->counter), "=&r" (result) \
|
||||
: "r" (I) \
|
||||
: "memory"); \
|
||||
\
|
||||
return result c_op I; \
|
||||
}
|
||||
|
||||
#define ATOMIC64_FETCH_OP(op, I, asm_op) \
|
||||
static inline long arch_atomic64_fetch_##op##_relaxed(long i, atomic64_t *v) \
|
||||
{ \
|
||||
long result; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
"am"#asm_op"_db.d " " %1, %2, %0 \n" \
|
||||
: "+ZB" (v->counter), "=&r" (result) \
|
||||
: "r" (I) \
|
||||
: "memory"); \
|
||||
\
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ATOMIC64_OPS(op, I, asm_op, c_op) \
|
||||
ATOMIC64_OP(op, I, asm_op) \
|
||||
ATOMIC64_OP_RETURN(op, I, asm_op, c_op) \
|
||||
ATOMIC64_FETCH_OP(op, I, asm_op)
|
||||
|
||||
ATOMIC64_OPS(add, i, add, +)
|
||||
ATOMIC64_OPS(sub, -i, add, +)
|
||||
|
||||
#define arch_atomic64_add_return_relaxed arch_atomic64_add_return_relaxed
|
||||
#define arch_atomic64_sub_return_relaxed arch_atomic64_sub_return_relaxed
|
||||
#define arch_atomic64_fetch_add_relaxed arch_atomic64_fetch_add_relaxed
|
||||
#define arch_atomic64_fetch_sub_relaxed arch_atomic64_fetch_sub_relaxed
|
||||
|
||||
#undef ATOMIC64_OPS
|
||||
|
||||
#define ATOMIC64_OPS(op, I, asm_op) \
|
||||
ATOMIC64_OP(op, I, asm_op) \
|
||||
ATOMIC64_FETCH_OP(op, I, asm_op)
|
||||
|
||||
ATOMIC64_OPS(and, i, and)
|
||||
ATOMIC64_OPS(or, i, or)
|
||||
ATOMIC64_OPS(xor, i, xor)
|
||||
|
||||
#define arch_atomic64_fetch_and_relaxed arch_atomic64_fetch_and_relaxed
|
||||
#define arch_atomic64_fetch_or_relaxed arch_atomic64_fetch_or_relaxed
|
||||
#define arch_atomic64_fetch_xor_relaxed arch_atomic64_fetch_xor_relaxed
|
||||
|
||||
#undef ATOMIC64_OPS
|
||||
#undef ATOMIC64_FETCH_OP
|
||||
#undef ATOMIC64_OP_RETURN
|
||||
#undef ATOMIC64_OP
|
||||
|
||||
static inline long arch_atomic64_fetch_add_unless(atomic64_t *v, long a, long u)
|
||||
{
|
||||
long prev, rc;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"0: ll.d %[p], %[c]\n"
|
||||
" beq %[p], %[u], 1f\n"
|
||||
" add.d %[rc], %[p], %[a]\n"
|
||||
" sc.d %[rc], %[c]\n"
|
||||
" beqz %[rc], 0b\n"
|
||||
" b 2f\n"
|
||||
"1:\n"
|
||||
__WEAK_LLSC_MB
|
||||
"2:\n"
|
||||
: [p]"=&r" (prev), [rc]"=&r" (rc),
|
||||
[c] "=ZB" (v->counter)
|
||||
: [a]"r" (a), [u]"r" (u)
|
||||
: "memory");
|
||||
|
||||
return prev;
|
||||
}
|
||||
#define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless
|
||||
|
||||
/*
|
||||
* arch_atomic64_sub_if_positive - conditionally subtract integer from atomic variable
|
||||
* @i: integer value to subtract
|
||||
* @v: pointer of type atomic64_t
|
||||
*
|
||||
* Atomically test @v and subtract @i if @v is greater or equal than @i.
|
||||
* The function returns the old value of @v minus @i.
|
||||
*/
|
||||
static inline long arch_atomic64_sub_if_positive(long i, atomic64_t *v)
|
||||
{
|
||||
long result;
|
||||
long temp;
|
||||
|
||||
if (__builtin_constant_p(i)) {
|
||||
__asm__ __volatile__(
|
||||
"1: ll.d %1, %2 # atomic64_sub_if_positive \n"
|
||||
" addi.d %0, %1, %3 \n"
|
||||
" or %1, %0, $zero \n"
|
||||
" blt %0, $zero, 2f \n"
|
||||
" sc.d %1, %2 \n"
|
||||
" beq %1, $zero, 1b \n"
|
||||
"2: \n"
|
||||
__WEAK_LLSC_MB
|
||||
: "=&r" (result), "=&r" (temp),
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||
: "I" (-i));
|
||||
} else {
|
||||
__asm__ __volatile__(
|
||||
"1: ll.d %1, %2 # atomic64_sub_if_positive \n"
|
||||
" sub.d %0, %1, %3 \n"
|
||||
" or %1, %0, $zero \n"
|
||||
" blt %0, $zero, 2f \n"
|
||||
" sc.d %1, %2 \n"
|
||||
" beq %1, $zero, 1b \n"
|
||||
"2: \n"
|
||||
__WEAK_LLSC_MB
|
||||
: "=&r" (result), "=&r" (temp),
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||
: "r" (i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define arch_atomic64_cmpxchg(v, o, n) \
|
||||
((__typeof__((v)->counter))arch_cmpxchg(&((v)->counter), (o), (n)))
|
||||
#define arch_atomic64_xchg(v, new) (arch_xchg(&((v)->counter), (new)))
|
||||
|
||||
/*
|
||||
* arch_atomic64_dec_if_positive - decrement by 1 if old value positive
|
||||
* @v: pointer of type atomic64_t
|
||||
*/
|
||||
#define arch_atomic64_dec_if_positive(v) arch_atomic64_sub_if_positive(1, v)
|
||||
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
#endif /* _ASM_ATOMIC_H */
|
159
arch/loongarch/include/asm/barrier.h
Normal file
159
arch/loongarch/include/asm/barrier.h
Normal file
@ -0,0 +1,159 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_BARRIER_H
|
||||
#define __ASM_BARRIER_H
|
||||
|
||||
#define __sync() __asm__ __volatile__("dbar 0" : : : "memory")
|
||||
|
||||
#define fast_wmb() __sync()
|
||||
#define fast_rmb() __sync()
|
||||
#define fast_mb() __sync()
|
||||
#define fast_iob() __sync()
|
||||
#define wbflush() __sync()
|
||||
|
||||
#define wmb() fast_wmb()
|
||||
#define rmb() fast_rmb()
|
||||
#define mb() fast_mb()
|
||||
#define iob() fast_iob()
|
||||
|
||||
#define __smp_mb() __asm__ __volatile__("dbar 0" : : : "memory")
|
||||
#define __smp_rmb() __asm__ __volatile__("dbar 0" : : : "memory")
|
||||
#define __smp_wmb() __asm__ __volatile__("dbar 0" : : : "memory")
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define __WEAK_LLSC_MB " dbar 0 \n"
|
||||
#else
|
||||
#define __WEAK_LLSC_MB " \n"
|
||||
#endif
|
||||
|
||||
#define __smp_mb__before_atomic() barrier()
|
||||
#define __smp_mb__after_atomic() barrier()
|
||||
|
||||
/**
|
||||
* array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
|
||||
* @index: array element index
|
||||
* @size: number of elements in array
|
||||
*
|
||||
* Returns:
|
||||
* 0 - (@index < @size)
|
||||
*/
|
||||
#define array_index_mask_nospec array_index_mask_nospec
|
||||
static inline unsigned long array_index_mask_nospec(unsigned long index,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"sltu %0, %1, %2\n\t"
|
||||
#if (__SIZEOF_LONG__ == 4)
|
||||
"sub.w %0, $r0, %0\n\t"
|
||||
#elif (__SIZEOF_LONG__ == 8)
|
||||
"sub.d %0, $r0, %0\n\t"
|
||||
#endif
|
||||
: "=r" (mask)
|
||||
: "r" (index), "r" (size)
|
||||
:);
|
||||
|
||||
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_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; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __smp_store_mb(p, v) \
|
||||
do { \
|
||||
union { typeof(p) __val; char __c[1]; } __u = \
|
||||
{ .__val = (__force typeof(p)) (v) }; \
|
||||
unsigned long __tmp; \
|
||||
switch (sizeof(p)) { \
|
||||
case 1: \
|
||||
*(volatile __u8 *)&p = *(__u8 *)__u.__c; \
|
||||
__smp_mb(); \
|
||||
break; \
|
||||
case 2: \
|
||||
*(volatile __u16 *)&p = *(__u16 *)__u.__c; \
|
||||
__smp_mb(); \
|
||||
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; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#include <asm-generic/barrier.h>
|
||||
|
||||
#endif /* __ASM_BARRIER_H */
|
33
arch/loongarch/include/asm/bitops.h
Normal file
33
arch/loongarch/include/asm/bitops.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_BITOPS_H
|
||||
#define _ASM_BITOPS_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifndef _LINUX_BITOPS_H
|
||||
#error only <linux/bitops.h> can be included directly
|
||||
#endif
|
||||
|
||||
#include <asm/barrier.h>
|
||||
|
||||
#include <asm-generic/bitops/builtin-ffs.h>
|
||||
#include <asm-generic/bitops/builtin-fls.h>
|
||||
#include <asm-generic/bitops/builtin-__ffs.h>
|
||||
#include <asm-generic/bitops/builtin-__fls.h>
|
||||
|
||||
#include <asm-generic/bitops/ffz.h>
|
||||
#include <asm-generic/bitops/fls64.h>
|
||||
|
||||
#include <asm-generic/bitops/sched.h>
|
||||
#include <asm-generic/bitops/hweight.h>
|
||||
|
||||
#include <asm-generic/bitops/atomic.h>
|
||||
#include <asm-generic/bitops/non-atomic.h>
|
||||
#include <asm-generic/bitops/lock.h>
|
||||
#include <asm-generic/bitops/le.h>
|
||||
#include <asm-generic/bitops/ext2-atomic.h>
|
||||
|
||||
#endif /* _ASM_BITOPS_H */
|
34
arch/loongarch/include/asm/bitrev.h
Normal file
34
arch/loongarch/include/asm/bitrev.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __LOONGARCH_ASM_BITREV_H__
|
||||
#define __LOONGARCH_ASM_BITREV_H__
|
||||
|
||||
#include <linux/swab.h>
|
||||
|
||||
static __always_inline __attribute_const__ u32 __arch_bitrev32(u32 x)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
asm("bitrev.4b %0, %1" : "=r"(ret) : "r"(__swab32(x)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __always_inline __attribute_const__ u16 __arch_bitrev16(u16 x)
|
||||
{
|
||||
u16 ret;
|
||||
|
||||
asm("bitrev.4b %0, %1" : "=r"(ret) : "r"(__swab16(x)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x)
|
||||
{
|
||||
u8 ret;
|
||||
|
||||
asm("bitrev.4b %0, %1" : "=r"(ret) : "r"(x));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __LOONGARCH_ASM_BITREV_H__ */
|
43
arch/loongarch/include/asm/bootinfo.h
Normal file
43
arch/loongarch/include/asm/bootinfo.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_BOOTINFO_H
|
||||
#define _ASM_BOOTINFO_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
const char *get_system_type(void);
|
||||
|
||||
extern void init_environ(void);
|
||||
extern void memblock_init(void);
|
||||
extern void platform_init(void);
|
||||
extern void plat_swiotlb_setup(void);
|
||||
extern int __init init_numa_memory(void);
|
||||
|
||||
struct loongson_board_info {
|
||||
int bios_size;
|
||||
const char *bios_vendor;
|
||||
const char *bios_version;
|
||||
const char *bios_release_date;
|
||||
const char *board_name;
|
||||
const char *board_vendor;
|
||||
};
|
||||
|
||||
struct loongson_system_configuration {
|
||||
int nr_cpus;
|
||||
int nr_nodes;
|
||||
int nr_io_pics;
|
||||
int boot_cpu_id;
|
||||
int cores_per_node;
|
||||
int cores_per_package;
|
||||
const char *cpuname;
|
||||
};
|
||||
|
||||
extern u64 efi_system_table;
|
||||
extern unsigned long fw_arg0, fw_arg1;
|
||||
extern struct loongson_board_info b_info;
|
||||
extern struct loongson_system_configuration loongson_sysconf;
|
||||
|
||||
#endif /* _ASM_BOOTINFO_H */
|
21
arch/loongarch/include/asm/branch.h
Normal file
21
arch/loongarch/include/asm/branch.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_BRANCH_H
|
||||
#define _ASM_BRANCH_H
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
static inline unsigned long exception_era(struct pt_regs *regs)
|
||||
{
|
||||
return regs->csr_era;
|
||||
}
|
||||
|
||||
static inline int compute_return_era(struct pt_regs *regs)
|
||||
{
|
||||
regs->csr_era += 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _ASM_BRANCH_H */
|
23
arch/loongarch/include/asm/bug.h
Normal file
23
arch/loongarch/include/asm/bug.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_BUG_H
|
||||
#define __ASM_BUG_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifdef CONFIG_BUG
|
||||
|
||||
#include <asm/break.h>
|
||||
|
||||
static inline void __noreturn BUG(void)
|
||||
{
|
||||
__asm__ __volatile__("break %0" : : "i" (BRK_BUG));
|
||||
unreachable();
|
||||
}
|
||||
|
||||
#define HAVE_ARCH_BUG
|
||||
|
||||
#endif
|
||||
|
||||
#include <asm-generic/bug.h>
|
||||
|
||||
#endif /* __ASM_BUG_H */
|
13
arch/loongarch/include/asm/cache.h
Normal file
13
arch/loongarch/include/asm/cache.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_CACHE_H
|
||||
#define _ASM_CACHE_H
|
||||
|
||||
#define L1_CACHE_SHIFT CONFIG_L1_CACHE_SHIFT
|
||||
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
|
||||
|
||||
#define __read_mostly __section(".data..read_mostly")
|
||||
|
||||
#endif /* _ASM_CACHE_H */
|
80
arch/loongarch/include/asm/cacheflush.h
Normal file
80
arch/loongarch/include/asm/cacheflush.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_CACHEFLUSH_H
|
||||
#define _ASM_CACHEFLUSH_H
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/cacheops.h>
|
||||
|
||||
extern void local_flush_icache_range(unsigned long start, unsigned long end);
|
||||
|
||||
#define flush_icache_range local_flush_icache_range
|
||||
#define flush_icache_user_range local_flush_icache_range
|
||||
|
||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
|
||||
|
||||
#define flush_cache_all() do { } while (0)
|
||||
#define flush_cache_mm(mm) do { } while (0)
|
||||
#define flush_cache_dup_mm(mm) do { } while (0)
|
||||
#define flush_cache_range(vma, start, end) do { } while (0)
|
||||
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
|
||||
#define flush_cache_vmap(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) do { } while (0)
|
||||
#define flush_icache_page(vma, page) do { } while (0)
|
||||
#define flush_icache_user_page(vma, page, addr, len) do { } while (0)
|
||||
#define flush_dcache_page(page) do { } while (0)
|
||||
#define flush_dcache_mmap_lock(mapping) do { } while (0)
|
||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||
|
||||
#define cache_op(op, addr) \
|
||||
__asm__ __volatile__( \
|
||||
" cacop %0, %1 \n" \
|
||||
: \
|
||||
: "i" (op), "ZC" (*(unsigned char *)(addr)))
|
||||
|
||||
static inline void flush_icache_line_indexed(unsigned long addr)
|
||||
{
|
||||
cache_op(Index_Invalidate_I, addr);
|
||||
}
|
||||
|
||||
static inline void flush_dcache_line_indexed(unsigned long addr)
|
||||
{
|
||||
cache_op(Index_Writeback_Inv_D, addr);
|
||||
}
|
||||
|
||||
static inline void flush_vcache_line_indexed(unsigned long addr)
|
||||
{
|
||||
cache_op(Index_Writeback_Inv_V, addr);
|
||||
}
|
||||
|
||||
static inline void flush_scache_line_indexed(unsigned long addr)
|
||||
{
|
||||
cache_op(Index_Writeback_Inv_S, addr);
|
||||
}
|
||||
|
||||
static inline void flush_icache_line(unsigned long addr)
|
||||
{
|
||||
cache_op(Hit_Invalidate_I, addr);
|
||||
}
|
||||
|
||||
static inline void flush_dcache_line(unsigned long addr)
|
||||
{
|
||||
cache_op(Hit_Writeback_Inv_D, addr);
|
||||
}
|
||||
|
||||
static inline void flush_vcache_line(unsigned long addr)
|
||||
{
|
||||
cache_op(Hit_Writeback_Inv_V, addr);
|
||||
}
|
||||
|
||||
static inline void flush_scache_line(unsigned long addr)
|
||||
{
|
||||
cache_op(Hit_Writeback_Inv_S, addr);
|
||||
}
|
||||
|
||||
#include <asm-generic/cacheflush.h>
|
||||
|
||||
#endif /* _ASM_CACHEFLUSH_H */
|
37
arch/loongarch/include/asm/cacheops.h
Normal file
37
arch/loongarch/include/asm/cacheops.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Cache operations for the cache instruction.
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_CACHEOPS_H
|
||||
#define __ASM_CACHEOPS_H
|
||||
|
||||
/*
|
||||
* Most cache ops are split into a 2 bit field identifying the cache, and a 3
|
||||
* bit field identifying the cache operation.
|
||||
*/
|
||||
#define CacheOp_Cache 0x03
|
||||
#define CacheOp_Op 0x1c
|
||||
|
||||
#define Cache_I 0x00
|
||||
#define Cache_D 0x01
|
||||
#define Cache_V 0x02
|
||||
#define Cache_S 0x03
|
||||
|
||||
#define Index_Invalidate 0x08
|
||||
#define Index_Writeback_Inv 0x08
|
||||
#define Hit_Invalidate 0x10
|
||||
#define Hit_Writeback_Inv 0x10
|
||||
#define CacheOp_User_Defined 0x18
|
||||
|
||||
#define Index_Invalidate_I (Cache_I | Index_Invalidate)
|
||||
#define Index_Writeback_Inv_D (Cache_D | Index_Writeback_Inv)
|
||||
#define Index_Writeback_Inv_V (Cache_V | Index_Writeback_Inv)
|
||||
#define Index_Writeback_Inv_S (Cache_S | Index_Writeback_Inv)
|
||||
#define Hit_Invalidate_I (Cache_I | Hit_Invalidate)
|
||||
#define Hit_Writeback_Inv_D (Cache_D | Hit_Writeback_Inv)
|
||||
#define Hit_Writeback_Inv_V (Cache_V | Hit_Writeback_Inv)
|
||||
#define Hit_Writeback_Inv_S (Cache_S | Hit_Writeback_Inv)
|
||||
|
||||
#endif /* __ASM_CACHEOPS_H */
|
12
arch/loongarch/include/asm/clocksource.h
Normal file
12
arch/loongarch/include/asm/clocksource.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Author: Huacai Chen <chenhuacai@loongson.cn>
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef __ASM_CLOCKSOURCE_H
|
||||
#define __ASM_CLOCKSOURCE_H
|
||||
|
||||
#include <asm/vdso/clocksource.h>
|
||||
|
||||
#endif /* __ASM_CLOCKSOURCE_H */
|
123
arch/loongarch/include/asm/cmpxchg.h
Normal file
123
arch/loongarch/include/asm/cmpxchg.h
Normal file
@ -0,0 +1,123 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_CMPXCHG_H
|
||||
#define __ASM_CMPXCHG_H
|
||||
|
||||
#include <asm/barrier.h>
|
||||
#include <linux/build_bug.h>
|
||||
|
||||
#define __xchg_asm(amswap_db, m, val) \
|
||||
({ \
|
||||
__typeof(val) __ret; \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
" "amswap_db" %1, %z2, %0 \n" \
|
||||
: "+ZB" (*m), "=&r" (__ret) \
|
||||
: "Jr" (val) \
|
||||
: "memory"); \
|
||||
\
|
||||
__ret; \
|
||||
})
|
||||
|
||||
static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
|
||||
int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 4:
|
||||
return __xchg_asm("amswap_db.w", (volatile u32 *)ptr, (u32)x);
|
||||
|
||||
case 8:
|
||||
return __xchg_asm("amswap_db.d", (volatile u64 *)ptr, (u64)x);
|
||||
|
||||
default:
|
||||
BUILD_BUG();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define arch_xchg(ptr, x) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) __res; \
|
||||
\
|
||||
__res = (__typeof__(*(ptr))) \
|
||||
__xchg((ptr), (unsigned long)(x), sizeof(*(ptr))); \
|
||||
\
|
||||
__res; \
|
||||
})
|
||||
|
||||
#define __cmpxchg_asm(ld, st, m, old, new) \
|
||||
({ \
|
||||
__typeof(old) __ret; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
"1: " ld " %0, %2 # __cmpxchg_asm \n" \
|
||||
" bne %0, %z3, 2f \n" \
|
||||
" or $t0, %z4, $zero \n" \
|
||||
" " st " $t0, %1 \n" \
|
||||
" beq $zero, $t0, 1b \n" \
|
||||
"2: \n" \
|
||||
__WEAK_LLSC_MB \
|
||||
: "=&r" (__ret), "=ZB"(*m) \
|
||||
: "ZB"(*m), "Jr" (old), "Jr" (new) \
|
||||
: "t0", "memory"); \
|
||||
\
|
||||
__ret; \
|
||||
})
|
||||
|
||||
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
|
||||
unsigned long new, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 4:
|
||||
return __cmpxchg_asm("ll.w", "sc.w", (volatile u32 *)ptr,
|
||||
(u32)old, new);
|
||||
|
||||
case 8:
|
||||
return __cmpxchg_asm("ll.d", "sc.d", (volatile u64 *)ptr,
|
||||
(u64)old, new);
|
||||
|
||||
default:
|
||||
BUILD_BUG();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define arch_cmpxchg_local(ptr, old, new) \
|
||||
((__typeof__(*(ptr))) \
|
||||
__cmpxchg((ptr), \
|
||||
(unsigned long)(__typeof__(*(ptr)))(old), \
|
||||
(unsigned long)(__typeof__(*(ptr)))(new), \
|
||||
sizeof(*(ptr))))
|
||||
|
||||
#define arch_cmpxchg(ptr, old, new) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) __res; \
|
||||
\
|
||||
__res = arch_cmpxchg_local((ptr), (old), (new)); \
|
||||
\
|
||||
__res; \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define arch_cmpxchg64_local(ptr, o, n) \
|
||||
({ \
|
||||
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
|
||||
arch_cmpxchg_local((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#define arch_cmpxchg64(ptr, o, n) \
|
||||
({ \
|
||||
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
|
||||
arch_cmpxchg((ptr), (o), (n)); \
|
||||
})
|
||||
#else
|
||||
#include <asm-generic/cmpxchg-local.h>
|
||||
#define arch_cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n))
|
||||
#define arch_cmpxchg64(ptr, o, n) arch_cmpxchg64_local((ptr), (o), (n))
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_CMPXCHG_H */
|
15
arch/loongarch/include/asm/compiler.h
Normal file
15
arch/loongarch/include/asm/compiler.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_COMPILER_H
|
||||
#define _ASM_COMPILER_H
|
||||
|
||||
#define GCC_OFF_SMALL_ASM() "ZC"
|
||||
|
||||
#define LOONGARCH_ISA_LEVEL "loongarch"
|
||||
#define LOONGARCH_ISA_ARCH_LEVEL "arch=loongarch"
|
||||
#define LOONGARCH_ISA_LEVEL_RAW loongarch
|
||||
#define LOONGARCH_ISA_ARCH_LEVEL_RAW LOONGARCH_ISA_LEVEL_RAW
|
||||
|
||||
#endif /* _ASM_COMPILER_H */
|
73
arch/loongarch/include/asm/cpu-features.h
Normal file
73
arch/loongarch/include/asm/cpu-features.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*
|
||||
* Derived from MIPS:
|
||||
* Copyright (C) 2003, 2004 Ralf Baechle
|
||||
* Copyright (C) 2004 Maciej W. Rozycki
|
||||
*/
|
||||
#ifndef __ASM_CPU_FEATURES_H
|
||||
#define __ASM_CPU_FEATURES_H
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpu-info.h>
|
||||
|
||||
#define cpu_opt(opt) (cpu_data[0].options & (opt))
|
||||
#define cpu_has(feat) (cpu_data[0].options & BIT_ULL(feat))
|
||||
|
||||
#define cpu_has_loongarch (cpu_has_loongarch32 | cpu_has_loongarch64)
|
||||
#define cpu_has_loongarch32 (cpu_data[0].isa_level & LOONGARCH_CPU_ISA_32BIT)
|
||||
#define cpu_has_loongarch64 (cpu_data[0].isa_level & LOONGARCH_CPU_ISA_64BIT)
|
||||
|
||||
#define cpu_icache_line_size() cpu_data[0].icache.linesz
|
||||
#define cpu_dcache_line_size() cpu_data[0].dcache.linesz
|
||||
#define cpu_vcache_line_size() cpu_data[0].vcache.linesz
|
||||
#define cpu_scache_line_size() cpu_data[0].scache.linesz
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
# define cpu_has_64bits (cpu_data[0].isa_level & LOONGARCH_CPU_ISA_64BIT)
|
||||
# define cpu_vabits 31
|
||||
# define cpu_pabits 31
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
# define cpu_has_64bits 1
|
||||
# define cpu_vabits cpu_data[0].vabits
|
||||
# define cpu_pabits cpu_data[0].pabits
|
||||
# define __NEED_ADDRBITS_PROBE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SMP assumption: Options of CPU 0 are a superset of all processors.
|
||||
* This is true for all known LoongArch systems.
|
||||
*/
|
||||
#define cpu_has_cpucfg cpu_opt(LOONGARCH_CPU_CPUCFG)
|
||||
#define cpu_has_lam cpu_opt(LOONGARCH_CPU_LAM)
|
||||
#define cpu_has_ual cpu_opt(LOONGARCH_CPU_UAL)
|
||||
#define cpu_has_fpu cpu_opt(LOONGARCH_CPU_FPU)
|
||||
#define cpu_has_lsx cpu_opt(LOONGARCH_CPU_LSX)
|
||||
#define cpu_has_lasx cpu_opt(LOONGARCH_CPU_LASX)
|
||||
#define cpu_has_complex cpu_opt(LOONGARCH_CPU_COMPLEX)
|
||||
#define cpu_has_crypto cpu_opt(LOONGARCH_CPU_CRYPTO)
|
||||
#define cpu_has_lvz cpu_opt(LOONGARCH_CPU_LVZ)
|
||||
#define cpu_has_lbt_x86 cpu_opt(LOONGARCH_CPU_LBT_X86)
|
||||
#define cpu_has_lbt_arm cpu_opt(LOONGARCH_CPU_LBT_ARM)
|
||||
#define cpu_has_lbt_mips cpu_opt(LOONGARCH_CPU_LBT_MIPS)
|
||||
#define cpu_has_lbt (cpu_has_lbt_x86|cpu_has_lbt_arm|cpu_has_lbt_mips)
|
||||
#define cpu_has_csr cpu_opt(LOONGARCH_CPU_CSR)
|
||||
#define cpu_has_tlb cpu_opt(LOONGARCH_CPU_TLB)
|
||||
#define cpu_has_watch cpu_opt(LOONGARCH_CPU_WATCH)
|
||||
#define cpu_has_vint cpu_opt(LOONGARCH_CPU_VINT)
|
||||
#define cpu_has_csripi cpu_opt(LOONGARCH_CPU_CSRIPI)
|
||||
#define cpu_has_extioi cpu_opt(LOONGARCH_CPU_EXTIOI)
|
||||
#define cpu_has_prefetch cpu_opt(LOONGARCH_CPU_PREFETCH)
|
||||
#define cpu_has_pmp cpu_opt(LOONGARCH_CPU_PMP)
|
||||
#define cpu_has_perf cpu_opt(LOONGARCH_CPU_PMP)
|
||||
#define cpu_has_scalefreq cpu_opt(LOONGARCH_CPU_SCALEFREQ)
|
||||
#define cpu_has_flatmode cpu_opt(LOONGARCH_CPU_FLATMODE)
|
||||
#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)
|
||||
|
||||
|
||||
#endif /* __ASM_CPU_FEATURES_H */
|
116
arch/loongarch/include/asm/cpu-info.h
Normal file
116
arch/loongarch/include/asm/cpu-info.h
Normal file
@ -0,0 +1,116 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_CPU_INFO_H
|
||||
#define __ASM_CPU_INFO_H
|
||||
|
||||
#include <linux/cache.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/loongarch.h>
|
||||
|
||||
/*
|
||||
* Descriptor for a cache
|
||||
*/
|
||||
struct cache_desc {
|
||||
unsigned int waysize; /* Bytes per way */
|
||||
unsigned short sets; /* Number of lines per set */
|
||||
unsigned char ways; /* Number of ways */
|
||||
unsigned char linesz; /* Size of line in bytes */
|
||||
unsigned char waybit; /* Bits to select in a cache set */
|
||||
unsigned char flags; /* Flags describing cache properties */
|
||||
};
|
||||
|
||||
struct cpuinfo_loongarch {
|
||||
u64 asid_cache;
|
||||
unsigned long asid_mask;
|
||||
|
||||
/*
|
||||
* Capability and feature descriptor structure for LoongArch CPU
|
||||
*/
|
||||
unsigned long long options;
|
||||
unsigned int processor_id;
|
||||
unsigned int fpu_vers;
|
||||
unsigned int fpu_csr0;
|
||||
unsigned int fpu_mask;
|
||||
unsigned int cputype;
|
||||
int isa_level;
|
||||
int tlbsize;
|
||||
int tlbsizemtlb;
|
||||
int tlbsizestlbsets;
|
||||
int tlbsizestlbways;
|
||||
struct cache_desc icache; /* Primary I-cache */
|
||||
struct cache_desc dcache; /* Primary D or combined I/D cache */
|
||||
struct cache_desc vcache; /* Victim cache, between pcache and scache */
|
||||
struct cache_desc scache; /* Secondary cache */
|
||||
struct cache_desc tcache; /* Tertiary/split secondary cache */
|
||||
int core; /* physical core number in package */
|
||||
int package;/* physical package number */
|
||||
int vabits; /* Virtual Address size in bits */
|
||||
int pabits; /* Physical Address size in bits */
|
||||
unsigned int ksave_mask; /* Usable KSave mask. */
|
||||
unsigned int watch_dreg_count; /* Number data breakpoints */
|
||||
unsigned int watch_ireg_count; /* Number instruction breakpoints */
|
||||
unsigned int watch_reg_use_cnt; /* min(NUM_WATCH_REGS, watch_dreg_count + watch_ireg_count), Usable by ptrace */
|
||||
} __aligned(SMP_CACHE_BYTES);
|
||||
|
||||
extern struct cpuinfo_loongarch cpu_data[];
|
||||
#define boot_cpu_data cpu_data[0]
|
||||
#define current_cpu_data cpu_data[smp_processor_id()]
|
||||
#define raw_current_cpu_data cpu_data[raw_smp_processor_id()]
|
||||
|
||||
extern void cpu_probe(void);
|
||||
|
||||
extern const char *__cpu_family[];
|
||||
extern const char *__cpu_full_name[];
|
||||
#define cpu_family_string() __cpu_family[raw_smp_processor_id()]
|
||||
#define cpu_full_name_string() __cpu_full_name[raw_smp_processor_id()]
|
||||
|
||||
struct seq_file;
|
||||
struct notifier_block;
|
||||
|
||||
extern int register_proc_cpuinfo_notifier(struct notifier_block *nb);
|
||||
extern int proc_cpuinfo_notifier_call_chain(unsigned long val, void *v);
|
||||
|
||||
#define proc_cpuinfo_notifier(fn, pri) \
|
||||
({ \
|
||||
static struct notifier_block fn##_nb = { \
|
||||
.notifier_call = fn, \
|
||||
.priority = pri \
|
||||
}; \
|
||||
\
|
||||
register_proc_cpuinfo_notifier(&fn##_nb); \
|
||||
})
|
||||
|
||||
struct proc_cpuinfo_notifier_args {
|
||||
struct seq_file *m;
|
||||
unsigned long n;
|
||||
};
|
||||
|
||||
static inline bool cpus_are_siblings(int cpua, int cpub)
|
||||
{
|
||||
struct cpuinfo_loongarch *infoa = &cpu_data[cpua];
|
||||
struct cpuinfo_loongarch *infob = &cpu_data[cpub];
|
||||
|
||||
if (infoa->package != infob->package)
|
||||
return false;
|
||||
|
||||
if (infoa->core != infob->core)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline unsigned long cpu_asid_mask(struct cpuinfo_loongarch *cpuinfo)
|
||||
{
|
||||
return cpuinfo->asid_mask;
|
||||
}
|
||||
|
||||
static inline void set_cpu_asid_mask(struct cpuinfo_loongarch *cpuinfo,
|
||||
unsigned long asid_mask)
|
||||
{
|
||||
cpuinfo->asid_mask = asid_mask;
|
||||
}
|
||||
|
||||
#endif /* __ASM_CPU_INFO_H */
|
127
arch/loongarch/include/asm/cpu.h
Normal file
127
arch/loongarch/include/asm/cpu.h
Normal file
@ -0,0 +1,127 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* cpu.h: Values of the PRID register used to match up
|
||||
* various LoongArch CPU types.
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_CPU_H
|
||||
#define _ASM_CPU_H
|
||||
|
||||
/*
|
||||
* As described in LoongArch specs from Loongson Technology, the PRID register
|
||||
* (CPUCFG.00) has the following layout:
|
||||
*
|
||||
* +---------------+----------------+------------+--------------------+
|
||||
* | Reserved | Company ID | Series ID | Product ID |
|
||||
* +---------------+----------------+------------+--------------------+
|
||||
* 31 24 23 16 15 12 11 0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Assigned Company values for bits 23:16 of the PRID register.
|
||||
*/
|
||||
|
||||
#define PRID_COMP_MASK 0xff0000
|
||||
|
||||
#define PRID_COMP_LOONGSON 0x140000
|
||||
|
||||
/*
|
||||
* Assigned Series ID values for bits 15:12 of the PRID register. In order
|
||||
* to detect a certain CPU type exactly eventually additional registers may
|
||||
* need to be examined.
|
||||
*/
|
||||
|
||||
#define PRID_SERIES_MASK 0xf000
|
||||
|
||||
#define PRID_SERIES_LA132 0x8000 /* Loongson 32bit */
|
||||
#define PRID_SERIES_LA264 0xa000 /* Loongson 64bit, 2-issue */
|
||||
#define PRID_SERIES_LA364 0xb000 /* Loongson 64bit,3-issue */
|
||||
#define PRID_SERIES_LA464 0xc000 /* Loongson 64bit, 4-issue */
|
||||
#define PRID_SERIES_LA664 0xd000 /* Loongson 64bit, 6-issue */
|
||||
|
||||
/*
|
||||
* Particular Product ID values for bits 11:0 of the PRID register.
|
||||
*/
|
||||
|
||||
#define PRID_PRODUCT_MASK 0x0fff
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
|
||||
enum cpu_type_enum {
|
||||
CPU_UNKNOWN,
|
||||
CPU_LOONGSON32,
|
||||
CPU_LOONGSON64,
|
||||
CPU_LAST
|
||||
};
|
||||
|
||||
#endif /* !__ASSEMBLY */
|
||||
|
||||
/*
|
||||
* ISA Level encodings
|
||||
*
|
||||
*/
|
||||
|
||||
#define LOONGARCH_CPU_ISA_LA32R 0x00000001
|
||||
#define LOONGARCH_CPU_ISA_LA32S 0x00000002
|
||||
#define LOONGARCH_CPU_ISA_LA64 0x00000004
|
||||
|
||||
#define LOONGARCH_CPU_ISA_32BIT (LOONGARCH_CPU_ISA_LA32R | LOONGARCH_CPU_ISA_LA32S)
|
||||
#define LOONGARCH_CPU_ISA_64BIT LOONGARCH_CPU_ISA_LA64
|
||||
|
||||
/*
|
||||
* CPU Option encodings
|
||||
*/
|
||||
#define CPU_FEATURE_CPUCFG 0 /* CPU has CPUCFG */
|
||||
#define CPU_FEATURE_LAM 1 /* CPU has Atomic instructions */
|
||||
#define CPU_FEATURE_UAL 2 /* CPU supports unaligned access */
|
||||
#define CPU_FEATURE_FPU 3 /* CPU has FPU */
|
||||
#define CPU_FEATURE_LSX 4 /* CPU has LSX (128-bit SIMD) */
|
||||
#define CPU_FEATURE_LASX 5 /* CPU has LASX (256-bit SIMD) */
|
||||
#define CPU_FEATURE_COMPLEX 6 /* CPU has Complex instructions */
|
||||
#define CPU_FEATURE_CRYPTO 7 /* CPU has Crypto instructions */
|
||||
#define CPU_FEATURE_LVZ 8 /* CPU has Virtualization extension */
|
||||
#define CPU_FEATURE_LBT_X86 9 /* CPU has X86 Binary Translation */
|
||||
#define CPU_FEATURE_LBT_ARM 10 /* CPU has ARM Binary Translation */
|
||||
#define CPU_FEATURE_LBT_MIPS 11 /* CPU has MIPS Binary Translation */
|
||||
#define CPU_FEATURE_TLB 12 /* CPU has TLB */
|
||||
#define CPU_FEATURE_CSR 13 /* CPU has CSR */
|
||||
#define CPU_FEATURE_WATCH 14 /* CPU has watchpoint registers */
|
||||
#define CPU_FEATURE_VINT 15 /* CPU has vectored interrupts */
|
||||
#define CPU_FEATURE_CSRIPI 16 /* CPU has CSR-IPI */
|
||||
#define CPU_FEATURE_EXTIOI 17 /* CPU has EXT-IOI */
|
||||
#define CPU_FEATURE_PREFETCH 18 /* CPU has prefetch instructions */
|
||||
#define CPU_FEATURE_PMP 19 /* CPU has perfermance counter */
|
||||
#define CPU_FEATURE_SCALEFREQ 20 /* CPU supports cpufreq scaling */
|
||||
#define CPU_FEATURE_FLATMODE 21 /* CPU has flat mode */
|
||||
#define CPU_FEATURE_EIODECODE 22 /* CPU has EXTIOI interrupt pin decode mode */
|
||||
#define CPU_FEATURE_GUESTID 23 /* CPU has GuestID feature */
|
||||
#define CPU_FEATURE_HYPERVISOR 24 /* CPU has hypervisor (running in VM) */
|
||||
|
||||
#define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG)
|
||||
#define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM)
|
||||
#define LOONGARCH_CPU_UAL BIT_ULL(CPU_FEATURE_UAL)
|
||||
#define LOONGARCH_CPU_FPU BIT_ULL(CPU_FEATURE_FPU)
|
||||
#define LOONGARCH_CPU_LSX BIT_ULL(CPU_FEATURE_LSX)
|
||||
#define LOONGARCH_CPU_LASX BIT_ULL(CPU_FEATURE_LASX)
|
||||
#define LOONGARCH_CPU_COMPLEX BIT_ULL(CPU_FEATURE_COMPLEX)
|
||||
#define LOONGARCH_CPU_CRYPTO BIT_ULL(CPU_FEATURE_CRYPTO)
|
||||
#define LOONGARCH_CPU_LVZ BIT_ULL(CPU_FEATURE_LVZ)
|
||||
#define LOONGARCH_CPU_LBT_X86 BIT_ULL(CPU_FEATURE_LBT_X86)
|
||||
#define LOONGARCH_CPU_LBT_ARM BIT_ULL(CPU_FEATURE_LBT_ARM)
|
||||
#define LOONGARCH_CPU_LBT_MIPS BIT_ULL(CPU_FEATURE_LBT_MIPS)
|
||||
#define LOONGARCH_CPU_TLB BIT_ULL(CPU_FEATURE_TLB)
|
||||
#define LOONGARCH_CPU_CSR BIT_ULL(CPU_FEATURE_CSR)
|
||||
#define LOONGARCH_CPU_WATCH BIT_ULL(CPU_FEATURE_WATCH)
|
||||
#define LOONGARCH_CPU_VINT BIT_ULL(CPU_FEATURE_VINT)
|
||||
#define LOONGARCH_CPU_CSRIPI BIT_ULL(CPU_FEATURE_CSRIPI)
|
||||
#define LOONGARCH_CPU_EXTIOI BIT_ULL(CPU_FEATURE_EXTIOI)
|
||||
#define LOONGARCH_CPU_PREFETCH BIT_ULL(CPU_FEATURE_PREFETCH)
|
||||
#define LOONGARCH_CPU_PMP BIT_ULL(CPU_FEATURE_PMP)
|
||||
#define LOONGARCH_CPU_SCALEFREQ BIT_ULL(CPU_FEATURE_SCALEFREQ)
|
||||
#define LOONGARCH_CPU_FLATMODE BIT_ULL(CPU_FEATURE_FLATMODE)
|
||||
#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)
|
||||
|
||||
#endif /* _ASM_CPU_H */
|
24
arch/loongarch/include/asm/cpufeature.h
Normal file
24
arch/loongarch/include/asm/cpufeature.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* CPU feature definitions for module loading, used by
|
||||
* module_cpu_feature_match(), see uapi/asm/hwcap.h for LoongArch CPU features.
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef __ASM_CPUFEATURE_H
|
||||
#define __ASM_CPUFEATURE_H
|
||||
|
||||
#include <uapi/asm/hwcap.h>
|
||||
#include <asm/elf.h>
|
||||
|
||||
#define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap))
|
||||
|
||||
#define cpu_feature(x) ilog2(HWCAP_ ## x)
|
||||
|
||||
static inline bool cpu_have_feature(unsigned int num)
|
||||
{
|
||||
return elf_hwcap & (1UL << num);
|
||||
}
|
||||
|
||||
#endif /* __ASM_CPUFEATURE_H */
|
26
arch/loongarch/include/asm/delay.h
Normal file
26
arch/loongarch/include/asm/delay.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_DELAY_H
|
||||
#define _ASM_DELAY_H
|
||||
|
||||
#include <linux/param.h>
|
||||
|
||||
extern void __delay(unsigned long cycles);
|
||||
extern void __ndelay(unsigned long ns);
|
||||
extern void __udelay(unsigned long us);
|
||||
|
||||
#define ndelay(ns) __ndelay(ns)
|
||||
#define udelay(us) __udelay(us)
|
||||
|
||||
/* make sure "usecs *= ..." in udelay do not overflow. */
|
||||
#if HZ >= 1000
|
||||
#define MAX_UDELAY_MS 1
|
||||
#elif HZ <= 200
|
||||
#define MAX_UDELAY_MS 5
|
||||
#else
|
||||
#define MAX_UDELAY_MS (1000 / HZ)
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_DELAY_H */
|
11
arch/loongarch/include/asm/dma-direct.h
Normal file
11
arch/loongarch/include/asm/dma-direct.h
Normal file
@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _LOONGARCH_DMA_DIRECT_H
|
||||
#define _LOONGARCH_DMA_DIRECT_H
|
||||
|
||||
dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
|
||||
phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
|
||||
|
||||
#endif /* _LOONGARCH_DMA_DIRECT_H */
|
24
arch/loongarch/include/asm/dmi.h
Normal file
24
arch/loongarch/include/asm/dmi.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_DMI_H
|
||||
#define _ASM_DMI_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/memblock.h>
|
||||
|
||||
#define dmi_early_remap(x, l) dmi_remap(x, l)
|
||||
#define dmi_early_unmap(x, l) dmi_unmap(x)
|
||||
#define dmi_alloc(l) memblock_alloc(l, PAGE_SIZE)
|
||||
|
||||
static inline void *dmi_remap(u64 phys_addr, unsigned long size)
|
||||
{
|
||||
return ((void *)TO_CACHE(phys_addr));
|
||||
}
|
||||
|
||||
static inline void dmi_unmap(void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* _ASM_DMI_H */
|
41
arch/loongarch/include/asm/efi.h
Normal file
41
arch/loongarch/include/asm/efi.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_LOONGARCH_EFI_H
|
||||
#define _ASM_LOONGARCH_EFI_H
|
||||
|
||||
#include <linux/efi.h>
|
||||
|
||||
void __init efi_init(void);
|
||||
void __init efi_runtime_init(void);
|
||||
void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
|
||||
|
||||
#define ARCH_EFI_IRQ_FLAGS_MASK 0x00000004 /* Bit 2: CSR.CRMD.IE */
|
||||
|
||||
#define arch_efi_call_virt_setup() \
|
||||
({ \
|
||||
})
|
||||
|
||||
#define arch_efi_call_virt(p, f, args...) \
|
||||
({ \
|
||||
efi_##f##_t * __f; \
|
||||
__f = p->f; \
|
||||
__f(args); \
|
||||
})
|
||||
|
||||
#define arch_efi_call_virt_teardown() \
|
||||
({ \
|
||||
})
|
||||
|
||||
#define EFI_ALLOC_ALIGN SZ_64K
|
||||
|
||||
struct screen_info *alloc_screen_info(void);
|
||||
void free_screen_info(struct screen_info *si);
|
||||
|
||||
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
|
||||
{
|
||||
return ULONG_MAX;
|
||||
}
|
||||
|
||||
#endif /* _ASM_LOONGARCH_EFI_H */
|
301
arch/loongarch/include/asm/elf.h
Normal file
301
arch/loongarch/include/asm/elf.h
Normal file
@ -0,0 +1,301 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_ELF_H
|
||||
#define _ASM_ELF_H
|
||||
|
||||
#include <linux/auxvec.h>
|
||||
#include <linux/fs.h>
|
||||
#include <uapi/linux/elf.h>
|
||||
|
||||
#include <asm/current.h>
|
||||
#include <asm/vdso.h>
|
||||
|
||||
/* The ABI of a file. */
|
||||
#define EF_LOONGARCH_ABI_LP64_SOFT_FLOAT 0x1
|
||||
#define EF_LOONGARCH_ABI_LP64_SINGLE_FLOAT 0x2
|
||||
#define EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT 0x3
|
||||
|
||||
#define EF_LOONGARCH_ABI_ILP32_SOFT_FLOAT 0x5
|
||||
#define EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT 0x6
|
||||
#define EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT 0x7
|
||||
|
||||
/* LoongArch relocation types used by the dynamic linker */
|
||||
#define R_LARCH_NONE 0
|
||||
#define R_LARCH_32 1
|
||||
#define R_LARCH_64 2
|
||||
#define R_LARCH_RELATIVE 3
|
||||
#define R_LARCH_COPY 4
|
||||
#define R_LARCH_JUMP_SLOT 5
|
||||
#define R_LARCH_TLS_DTPMOD32 6
|
||||
#define R_LARCH_TLS_DTPMOD64 7
|
||||
#define R_LARCH_TLS_DTPREL32 8
|
||||
#define R_LARCH_TLS_DTPREL64 9
|
||||
#define R_LARCH_TLS_TPREL32 10
|
||||
#define R_LARCH_TLS_TPREL64 11
|
||||
#define R_LARCH_IRELATIVE 12
|
||||
#define R_LARCH_MARK_LA 20
|
||||
#define R_LARCH_MARK_PCREL 21
|
||||
#define R_LARCH_SOP_PUSH_PCREL 22
|
||||
#define R_LARCH_SOP_PUSH_ABSOLUTE 23
|
||||
#define R_LARCH_SOP_PUSH_DUP 24
|
||||
#define R_LARCH_SOP_PUSH_GPREL 25
|
||||
#define R_LARCH_SOP_PUSH_TLS_TPREL 26
|
||||
#define R_LARCH_SOP_PUSH_TLS_GOT 27
|
||||
#define R_LARCH_SOP_PUSH_TLS_GD 28
|
||||
#define R_LARCH_SOP_PUSH_PLT_PCREL 29
|
||||
#define R_LARCH_SOP_ASSERT 30
|
||||
#define R_LARCH_SOP_NOT 31
|
||||
#define R_LARCH_SOP_SUB 32
|
||||
#define R_LARCH_SOP_SL 33
|
||||
#define R_LARCH_SOP_SR 34
|
||||
#define R_LARCH_SOP_ADD 35
|
||||
#define R_LARCH_SOP_AND 36
|
||||
#define R_LARCH_SOP_IF_ELSE 37
|
||||
#define R_LARCH_SOP_POP_32_S_10_5 38
|
||||
#define R_LARCH_SOP_POP_32_U_10_12 39
|
||||
#define R_LARCH_SOP_POP_32_S_10_12 40
|
||||
#define R_LARCH_SOP_POP_32_S_10_16 41
|
||||
#define R_LARCH_SOP_POP_32_S_10_16_S2 42
|
||||
#define R_LARCH_SOP_POP_32_S_5_20 43
|
||||
#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44
|
||||
#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45
|
||||
#define R_LARCH_SOP_POP_32_U 46
|
||||
#define R_LARCH_ADD8 47
|
||||
#define R_LARCH_ADD16 48
|
||||
#define R_LARCH_ADD24 49
|
||||
#define R_LARCH_ADD32 50
|
||||
#define R_LARCH_ADD64 51
|
||||
#define R_LARCH_SUB8 52
|
||||
#define R_LARCH_SUB16 53
|
||||
#define R_LARCH_SUB24 54
|
||||
#define R_LARCH_SUB32 55
|
||||
#define R_LARCH_SUB64 56
|
||||
#define R_LARCH_GNU_VTINHERIT 57
|
||||
#define R_LARCH_GNU_VTENTRY 58
|
||||
|
||||
#ifndef ELF_ARCH
|
||||
|
||||
/* ELF register definitions */
|
||||
|
||||
/*
|
||||
* General purpose have the following registers:
|
||||
* Register Number
|
||||
* GPRs 32
|
||||
* ORIG_A0 1
|
||||
* ERA 1
|
||||
* BADVADDR 1
|
||||
* CRMD 1
|
||||
* PRMD 1
|
||||
* EUEN 1
|
||||
* ECFG 1
|
||||
* ESTAT 1
|
||||
* Reserved 5
|
||||
*/
|
||||
#define ELF_NGREG 45
|
||||
|
||||
/*
|
||||
* Floating point have the following registers:
|
||||
* Register Number
|
||||
* FPR 32
|
||||
* FCC 1
|
||||
* FCSR 1
|
||||
*/
|
||||
#define ELF_NFPREG 34
|
||||
|
||||
typedef unsigned long elf_greg_t;
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
|
||||
typedef double elf_fpreg_t;
|
||||
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
|
||||
|
||||
void loongarch_dump_regs64(u64 *uregs, const struct pt_regs *regs);
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
/*
|
||||
* This is used to ensure we don't load something for the wrong architecture.
|
||||
*/
|
||||
#define elf_check_arch elf32_check_arch
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
*/
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
|
||||
#define ELF_CORE_COPY_REGS(dest, regs) \
|
||||
loongarch_dump_regs32((u32 *)&(dest), (regs));
|
||||
|
||||
#endif /* CONFIG_32BIT */
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/*
|
||||
* This is used to ensure we don't load something for the wrong architecture.
|
||||
*/
|
||||
#define elf_check_arch elf64_check_arch
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
*/
|
||||
#define ELF_CLASS ELFCLASS64
|
||||
|
||||
#define ELF_CORE_COPY_REGS(dest, regs) \
|
||||
loongarch_dump_regs64((u64 *)&(dest), (regs));
|
||||
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
*/
|
||||
#define ELF_DATA ELFDATA2LSB
|
||||
#define ELF_ARCH EM_LOONGARCH
|
||||
|
||||
#endif /* !defined(ELF_ARCH) */
|
||||
|
||||
#define loongarch_elf_check_machine(x) ((x)->e_machine == EM_LOONGARCH)
|
||||
|
||||
#define vmcore_elf32_check_arch loongarch_elf_check_machine
|
||||
#define vmcore_elf64_check_arch loongarch_elf_check_machine
|
||||
|
||||
/*
|
||||
* Return non-zero if HDR identifies an 32bit ELF binary.
|
||||
*/
|
||||
#define elf32_check_arch(hdr) \
|
||||
({ \
|
||||
int __res = 1; \
|
||||
struct elfhdr *__h = (hdr); \
|
||||
\
|
||||
if (!loongarch_elf_check_machine(__h)) \
|
||||
__res = 0; \
|
||||
if (__h->e_ident[EI_CLASS] != ELFCLASS32) \
|
||||
__res = 0; \
|
||||
\
|
||||
__res; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Return non-zero if HDR identifies an 64bit ELF binary.
|
||||
*/
|
||||
#define elf64_check_arch(hdr) \
|
||||
({ \
|
||||
int __res = 1; \
|
||||
struct elfhdr *__h = (hdr); \
|
||||
\
|
||||
if (!loongarch_elf_check_machine(__h)) \
|
||||
__res = 0; \
|
||||
if (__h->e_ident[EI_CLASS] != ELFCLASS64) \
|
||||
__res = 0; \
|
||||
\
|
||||
__res; \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
|
||||
#define SET_PERSONALITY2(ex, state) \
|
||||
do { \
|
||||
current->thread.vdso = &vdso_info; \
|
||||
\
|
||||
loongarch_set_personality_fcsr(state); \
|
||||
\
|
||||
if (personality(current->personality) != PER_LINUX) \
|
||||
set_personality(PER_LINUX); \
|
||||
} while (0)
|
||||
|
||||
#endif /* CONFIG_32BIT */
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
#define SET_PERSONALITY2(ex, state) \
|
||||
do { \
|
||||
unsigned int p; \
|
||||
\
|
||||
clear_thread_flag(TIF_32BIT_REGS); \
|
||||
clear_thread_flag(TIF_32BIT_ADDR); \
|
||||
\
|
||||
current->thread.vdso = &vdso_info; \
|
||||
loongarch_set_personality_fcsr(state); \
|
||||
\
|
||||
p = personality(current->personality); \
|
||||
if (p != PER_LINUX32 && p != PER_LINUX) \
|
||||
set_personality(PER_LINUX); \
|
||||
} while (0)
|
||||
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
#define CORE_DUMP_USE_REGSET
|
||||
#define ELF_EXEC_PAGESIZE PAGE_SIZE
|
||||
|
||||
/*
|
||||
* This yields a mask that user programs can use to figure out what
|
||||
* instruction set this cpu supports. This could be done in userspace,
|
||||
* but it's not easy, and we've already done it here.
|
||||
*/
|
||||
|
||||
#define ELF_HWCAP (elf_hwcap)
|
||||
extern unsigned int elf_hwcap;
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
/*
|
||||
* This yields a string that ld.so will use to load implementation
|
||||
* specific libraries for optimization. This is more specific in
|
||||
* intent than poking at uname or /proc/cpuinfo.
|
||||
*/
|
||||
|
||||
#define ELF_PLATFORM __elf_platform
|
||||
extern const char *__elf_platform;
|
||||
|
||||
#define ELF_PLAT_INIT(_r, load_addr) do { \
|
||||
_r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0; \
|
||||
_r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \
|
||||
_r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \
|
||||
_r->regs[13] = _r->regs[14] = _r->regs[15] = _r->regs[16] = 0; \
|
||||
_r->regs[17] = _r->regs[18] = _r->regs[19] = _r->regs[20] = 0; \
|
||||
_r->regs[21] = _r->regs[22] = _r->regs[23] = _r->regs[24] = 0; \
|
||||
_r->regs[25] = _r->regs[26] = _r->regs[27] = _r->regs[28] = 0; \
|
||||
_r->regs[29] = _r->regs[30] = _r->regs[31] = 0; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This is the location that an ET_DYN program is loaded if exec'ed. Typical
|
||||
* use of this is to invoke "./ld.so someprog" to test out a new version of
|
||||
* the loader. We need to make sure that it is out of the way of the program
|
||||
* that it will "exec", and that there is sufficient room for the brk.
|
||||
*/
|
||||
|
||||
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
|
||||
|
||||
/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
|
||||
#define ARCH_DLINFO \
|
||||
do { \
|
||||
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
|
||||
(unsigned long)current->mm->context.vdso); \
|
||||
} while (0)
|
||||
|
||||
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
|
||||
struct linux_binprm;
|
||||
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
|
||||
int uses_interp);
|
||||
|
||||
struct arch_elf_state {
|
||||
int fp_abi;
|
||||
int interp_fp_abi;
|
||||
};
|
||||
|
||||
#define LOONGARCH_ABI_FP_ANY (0)
|
||||
|
||||
#define INIT_ARCH_ELF_STATE { \
|
||||
.fp_abi = LOONGARCH_ABI_FP_ANY, \
|
||||
.interp_fp_abi = LOONGARCH_ABI_FP_ANY, \
|
||||
}
|
||||
|
||||
#define elf_read_implies_exec(ex, exec_stk) (exec_stk == EXSTACK_DEFAULT)
|
||||
|
||||
extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
|
||||
bool is_interp, struct arch_elf_state *state);
|
||||
|
||||
extern int arch_check_elf(void *ehdr, bool has_interpreter, void *interp_ehdr,
|
||||
struct arch_elf_state *state);
|
||||
|
||||
extern void loongarch_set_personality_fcsr(struct arch_elf_state *state);
|
||||
|
||||
#endif /* _ASM_ELF_H */
|
13
arch/loongarch/include/asm/entry-common.h
Normal file
13
arch/loongarch/include/asm/entry-common.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef ARCH_LOONGARCH_ENTRY_COMMON_H
|
||||
#define ARCH_LOONGARCH_ENTRY_COMMON_H
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/processor.h>
|
||||
|
||||
static inline bool on_thread_stack(void)
|
||||
{
|
||||
return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
|
||||
}
|
||||
|
||||
#endif
|
10
arch/loongarch/include/asm/exec.h
Normal file
10
arch/loongarch/include/asm/exec.h
Normal file
@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_EXEC_H
|
||||
#define _ASM_EXEC_H
|
||||
|
||||
extern unsigned long arch_align_stack(unsigned long sp);
|
||||
|
||||
#endif /* _ASM_EXEC_H */
|
23
arch/loongarch/include/asm/fb.h
Normal file
23
arch/loongarch/include/asm/fb.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_FB_H_
|
||||
#define _ASM_FB_H_
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
|
||||
unsigned long off)
|
||||
{
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
}
|
||||
|
||||
static inline int fb_is_primary_device(struct fb_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _ASM_FB_H_ */
|
13
arch/loongarch/include/asm/fixmap.h
Normal file
13
arch/loongarch/include/asm/fixmap.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* fixmap.h: compile-time virtual memory allocation
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _ASM_FIXMAP_H
|
||||
#define _ASM_FIXMAP_H
|
||||
|
||||
#define NR_FIX_BTMAPS 64
|
||||
|
||||
#endif
|
53
arch/loongarch/include/asm/fpregdef.h
Normal file
53
arch/loongarch/include/asm/fpregdef.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Definitions for the FPU register names
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_FPREGDEF_H
|
||||
#define _ASM_FPREGDEF_H
|
||||
|
||||
#define fa0 $f0 /* argument registers, fa0/fa1 reused as fv0/fv1 for return value */
|
||||
#define fa1 $f1
|
||||
#define fa2 $f2
|
||||
#define fa3 $f3
|
||||
#define fa4 $f4
|
||||
#define fa5 $f5
|
||||
#define fa6 $f6
|
||||
#define fa7 $f7
|
||||
#define ft0 $f8 /* caller saved */
|
||||
#define ft1 $f9
|
||||
#define ft2 $f10
|
||||
#define ft3 $f11
|
||||
#define ft4 $f12
|
||||
#define ft5 $f13
|
||||
#define ft6 $f14
|
||||
#define ft7 $f15
|
||||
#define ft8 $f16
|
||||
#define ft9 $f17
|
||||
#define ft10 $f18
|
||||
#define ft11 $f19
|
||||
#define ft12 $f20
|
||||
#define ft13 $f21
|
||||
#define ft14 $f22
|
||||
#define ft15 $f23
|
||||
#define fs0 $f24 /* callee saved */
|
||||
#define fs1 $f25
|
||||
#define fs2 $f26
|
||||
#define fs3 $f27
|
||||
#define fs4 $f28
|
||||
#define fs5 $f29
|
||||
#define fs6 $f30
|
||||
#define fs7 $f31
|
||||
|
||||
/*
|
||||
* Current binutils expects *GPRs* at FCSR position for the FCSR
|
||||
* operation instructions, so define aliases for those used.
|
||||
*/
|
||||
#define fcsr0 $r0
|
||||
#define fcsr1 $r1
|
||||
#define fcsr2 $r2
|
||||
#define fcsr3 $r3
|
||||
#define vcsr16 $r16
|
||||
|
||||
#endif /* _ASM_FPREGDEF_H */
|
129
arch/loongarch/include/asm/fpu.h
Normal file
129
arch/loongarch/include/asm/fpu.h
Normal file
@ -0,0 +1,129 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Author: Huacai Chen <chenhuacai@loongson.cn>
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_FPU_H
|
||||
#define _ASM_FPU_H
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/loongarch.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
struct sigcontext;
|
||||
|
||||
extern void _init_fpu(unsigned int);
|
||||
extern void _save_fp(struct loongarch_fpu *);
|
||||
extern void _restore_fp(struct loongarch_fpu *);
|
||||
|
||||
/*
|
||||
* Mask the FCSR Cause bits according to the Enable bits, observing
|
||||
* that Unimplemented is always enabled.
|
||||
*/
|
||||
static inline unsigned long mask_fcsr_x(unsigned long fcsr)
|
||||
{
|
||||
return fcsr & ((fcsr & FPU_CSR_ALL_E) <<
|
||||
(ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)));
|
||||
}
|
||||
|
||||
static inline int is_fp_enabled(void)
|
||||
{
|
||||
return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_FPEN) ?
|
||||
1 : 0;
|
||||
}
|
||||
|
||||
#define enable_fpu() set_csr_euen(CSR_EUEN_FPEN)
|
||||
|
||||
#define disable_fpu() clear_csr_euen(CSR_EUEN_FPEN)
|
||||
|
||||
#define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU)
|
||||
|
||||
static inline int is_fpu_owner(void)
|
||||
{
|
||||
return test_thread_flag(TIF_USEDFPU);
|
||||
}
|
||||
|
||||
static inline void __own_fpu(void)
|
||||
{
|
||||
enable_fpu();
|
||||
set_thread_flag(TIF_USEDFPU);
|
||||
KSTK_EUEN(current) |= CSR_EUEN_FPEN;
|
||||
}
|
||||
|
||||
static inline void own_fpu_inatomic(int restore)
|
||||
{
|
||||
if (cpu_has_fpu && !is_fpu_owner()) {
|
||||
__own_fpu();
|
||||
if (restore)
|
||||
_restore_fp(¤t->thread.fpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void own_fpu(int restore)
|
||||
{
|
||||
preempt_disable();
|
||||
own_fpu_inatomic(restore);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
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();
|
||||
clear_tsk_thread_flag(tsk, TIF_USEDFPU);
|
||||
}
|
||||
KSTK_EUEN(tsk) &= ~(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN);
|
||||
}
|
||||
|
||||
static inline void lose_fpu(int save)
|
||||
{
|
||||
preempt_disable();
|
||||
lose_fpu_inatomic(save, current);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static inline void init_fpu(void)
|
||||
{
|
||||
unsigned int fcsr = current->thread.fpu.fcsr;
|
||||
|
||||
__own_fpu();
|
||||
_init_fpu(fcsr);
|
||||
set_used_math();
|
||||
}
|
||||
|
||||
static inline void save_fp(struct task_struct *tsk)
|
||||
{
|
||||
if (cpu_has_fpu)
|
||||
_save_fp(&tsk->thread.fpu);
|
||||
}
|
||||
|
||||
static inline void restore_fp(struct task_struct *tsk)
|
||||
{
|
||||
if (cpu_has_fpu)
|
||||
_restore_fp(&tsk->thread.fpu);
|
||||
}
|
||||
|
||||
static inline union fpureg *get_fpu_regs(struct task_struct *tsk)
|
||||
{
|
||||
if (tsk == current) {
|
||||
preempt_disable();
|
||||
if (is_fpu_owner())
|
||||
_save_fp(¤t->thread.fpu);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
return tsk->thread.fpu.fpr;
|
||||
}
|
||||
|
||||
#endif /* _ASM_FPU_H */
|
108
arch/loongarch/include/asm/futex.h
Normal file
108
arch/loongarch/include/asm/futex.h
Normal file
@ -0,0 +1,108 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_FUTEX_H
|
||||
#define _ASM_FUTEX_H
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"1: ll.w %1, %4 # __futex_atomic_op\n" \
|
||||
" " insn " \n" \
|
||||
"2: sc.w $t0, %2 \n" \
|
||||
" beq $t0, $zero, 1b \n" \
|
||||
"3: \n" \
|
||||
" .section .fixup,\"ax\" \n" \
|
||||
"4: li.w %0, %6 \n" \
|
||||
" b 3b \n" \
|
||||
" .previous \n" \
|
||||
" .section __ex_table,\"a\" \n" \
|
||||
" "__UA_ADDR "\t1b, 4b \n" \
|
||||
" "__UA_ADDR "\t2b, 4b \n" \
|
||||
" .previous \n" \
|
||||
: "=r" (ret), "=&r" (oldval), \
|
||||
"=ZC" (*uaddr) \
|
||||
: "0" (0), "ZC" (*uaddr), "Jr" (oparg), \
|
||||
"i" (-EFAULT) \
|
||||
: "memory", "t0"); \
|
||||
}
|
||||
|
||||
static inline int
|
||||
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
|
||||
{
|
||||
int oldval = 0, ret = 0;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
case FUTEX_OP_SET:
|
||||
__futex_atomic_op("move $t0, %z5", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ADD:
|
||||
__futex_atomic_op("add.w $t0, %1, %z5", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_OR:
|
||||
__futex_atomic_op("or $t0, %1, %z5", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ANDN:
|
||||
__futex_atomic_op("and $t0, %1, %z5", ret, oldval, uaddr, ~oparg);
|
||||
break;
|
||||
case FUTEX_OP_XOR:
|
||||
__futex_atomic_op("xor $t0, %1, %z5", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret)
|
||||
*oval = oldval;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, u32 newval)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val = 0;
|
||||
|
||||
if (!access_ok(uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"# futex_atomic_cmpxchg_inatomic \n"
|
||||
"1: ll.w %1, %3 \n"
|
||||
" bne %1, %z4, 3f \n"
|
||||
" or $t0, %z5, $zero \n"
|
||||
"2: sc.w $t0, %2 \n"
|
||||
" beq $zero, $t0, 1b \n"
|
||||
"3: \n"
|
||||
__WEAK_LLSC_MB
|
||||
" .section .fixup,\"ax\" \n"
|
||||
"4: li.d %0, %6 \n"
|
||||
" b 3b \n"
|
||||
" .previous \n"
|
||||
" .section __ex_table,\"a\" \n"
|
||||
" "__UA_ADDR "\t1b, 4b \n"
|
||||
" "__UA_ADDR "\t2b, 4b \n"
|
||||
" .previous \n"
|
||||
: "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
|
||||
: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
|
||||
"i" (-EFAULT)
|
||||
: "memory", "t0");
|
||||
|
||||
*uval = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* _ASM_FUTEX_H */
|
26
arch/loongarch/include/asm/hardirq.h
Normal file
26
arch/loongarch/include/asm/hardirq.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_HARDIRQ_H
|
||||
#define _ASM_HARDIRQ_H
|
||||
|
||||
#include <linux/cache.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
extern void ack_bad_irq(unsigned int irq);
|
||||
#define ack_bad_irq ack_bad_irq
|
||||
|
||||
#define NR_IPI 2
|
||||
|
||||
typedef struct {
|
||||
unsigned int ipi_irqs[NR_IPI];
|
||||
unsigned int __softirq_pending;
|
||||
} ____cacheline_aligned irq_cpustat_t;
|
||||
|
||||
DECLARE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat);
|
||||
|
||||
#define __ARCH_IRQ_STAT
|
||||
|
||||
#endif /* _ASM_HARDIRQ_H */
|
83
arch/loongarch/include/asm/hugetlb.h
Normal file
83
arch/loongarch/include/asm/hugetlb.h
Normal file
@ -0,0 +1,83 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef __ASM_HUGETLB_H
|
||||
#define __ASM_HUGETLB_H
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
uint64_t pmd_to_entrylo(unsigned long pmd_val);
|
||||
|
||||
#define __HAVE_ARCH_PREPARE_HUGEPAGE_RANGE
|
||||
static inline int prepare_hugepage_range(struct file *file,
|
||||
unsigned long addr,
|
||||
unsigned long len)
|
||||
{
|
||||
unsigned long task_size = STACK_TOP;
|
||||
struct hstate *h = hstate_file(file);
|
||||
|
||||
if (len & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
if (addr & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
if (len > task_size)
|
||||
return -ENOMEM;
|
||||
if (task_size - len < addr)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
|
||||
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t clear;
|
||||
pte_t pte = *ptep;
|
||||
|
||||
pte_val(clear) = (unsigned long)invalid_pte_table;
|
||||
set_pte_at(mm, addr, ptep, clear);
|
||||
return pte;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
|
||||
static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t pte;
|
||||
|
||||
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
|
||||
flush_tlb_page(vma, addr);
|
||||
return pte;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTE_NONE
|
||||
static inline int huge_pte_none(pte_t pte)
|
||||
{
|
||||
unsigned long val = pte_val(pte) & ~_PAGE_GLOBAL;
|
||||
return !val || (val == (unsigned long)invalid_pte_table);
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
|
||||
static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long addr,
|
||||
pte_t *ptep, pte_t pte,
|
||||
int dirty)
|
||||
{
|
||||
int changed = !pte_same(*ptep, pte);
|
||||
|
||||
if (changed) {
|
||||
set_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
/*
|
||||
* There could be some standard sized pages in there,
|
||||
* get them all.
|
||||
*/
|
||||
flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
#include <asm-generic/hugetlb.h>
|
||||
|
||||
#endif /* __ASM_HUGETLB_H */
|
17
arch/loongarch/include/asm/hw_irq.h
Normal file
17
arch/loongarch/include/asm/hw_irq.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_HW_IRQ_H
|
||||
#define __ASM_HW_IRQ_H
|
||||
|
||||
#include <linux/atomic.h>
|
||||
|
||||
extern atomic_t irq_err_count;
|
||||
|
||||
/*
|
||||
* interrupt-retrigger: NOP for now. This may not be appropriate for all
|
||||
* machines, we'll see ...
|
||||
*/
|
||||
|
||||
#endif /* __ASM_HW_IRQ_H */
|
9
arch/loongarch/include/asm/idle.h
Normal file
9
arch/loongarch/include/asm/idle.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_IDLE_H
|
||||
#define __ASM_IDLE_H
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
extern asmlinkage void __arch_cpu_idle(void);
|
||||
|
||||
#endif /* __ASM_IDLE_H */
|
117
arch/loongarch/include/asm/inst.h
Normal file
117
arch/loongarch/include/asm/inst.h
Normal file
@ -0,0 +1,117 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_INST_H
|
||||
#define _ASM_INST_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
#define ADDR_IMMMASK_LU52ID 0xFFF0000000000000
|
||||
#define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000
|
||||
#define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000
|
||||
|
||||
#define ADDR_IMMSHIFT_LU52ID 52
|
||||
#define ADDR_IMMSHIFT_LU32ID 32
|
||||
#define ADDR_IMMSHIFT_ADDU16ID 16
|
||||
|
||||
#define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN)
|
||||
|
||||
enum reg1i20_op {
|
||||
lu12iw_op = 0x0a,
|
||||
lu32id_op = 0x0b,
|
||||
};
|
||||
|
||||
enum reg2i12_op {
|
||||
lu52id_op = 0x0c,
|
||||
};
|
||||
|
||||
enum reg2i16_op {
|
||||
jirl_op = 0x13,
|
||||
};
|
||||
|
||||
struct reg0i26_format {
|
||||
unsigned int immediate_h : 10;
|
||||
unsigned int immediate_l : 16;
|
||||
unsigned int opcode : 6;
|
||||
};
|
||||
|
||||
struct reg1i20_format {
|
||||
unsigned int rd : 5;
|
||||
unsigned int immediate : 20;
|
||||
unsigned int opcode : 7;
|
||||
};
|
||||
|
||||
struct reg1i21_format {
|
||||
unsigned int immediate_h : 5;
|
||||
unsigned int rj : 5;
|
||||
unsigned int immediate_l : 16;
|
||||
unsigned int opcode : 6;
|
||||
};
|
||||
|
||||
struct reg2i12_format {
|
||||
unsigned int rd : 5;
|
||||
unsigned int rj : 5;
|
||||
unsigned int immediate : 12;
|
||||
unsigned int opcode : 10;
|
||||
};
|
||||
|
||||
struct reg2i16_format {
|
||||
unsigned int rd : 5;
|
||||
unsigned int rj : 5;
|
||||
unsigned int immediate : 16;
|
||||
unsigned int opcode : 6;
|
||||
};
|
||||
|
||||
union loongarch_instruction {
|
||||
unsigned int word;
|
||||
struct reg0i26_format reg0i26_format;
|
||||
struct reg1i20_format reg1i20_format;
|
||||
struct reg1i21_format reg1i21_format;
|
||||
struct reg2i12_format reg2i12_format;
|
||||
struct reg2i16_format reg2i16_format;
|
||||
};
|
||||
|
||||
#define LOONGARCH_INSN_SIZE sizeof(union loongarch_instruction)
|
||||
|
||||
enum loongarch_gpr {
|
||||
LOONGARCH_GPR_ZERO = 0,
|
||||
LOONGARCH_GPR_RA = 1,
|
||||
LOONGARCH_GPR_TP = 2,
|
||||
LOONGARCH_GPR_SP = 3,
|
||||
LOONGARCH_GPR_A0 = 4, /* Reused as V0 for return value */
|
||||
LOONGARCH_GPR_A1, /* Reused as V1 for return value */
|
||||
LOONGARCH_GPR_A2,
|
||||
LOONGARCH_GPR_A3,
|
||||
LOONGARCH_GPR_A4,
|
||||
LOONGARCH_GPR_A5,
|
||||
LOONGARCH_GPR_A6,
|
||||
LOONGARCH_GPR_A7,
|
||||
LOONGARCH_GPR_T0 = 12,
|
||||
LOONGARCH_GPR_T1,
|
||||
LOONGARCH_GPR_T2,
|
||||
LOONGARCH_GPR_T3,
|
||||
LOONGARCH_GPR_T4,
|
||||
LOONGARCH_GPR_T5,
|
||||
LOONGARCH_GPR_T6,
|
||||
LOONGARCH_GPR_T7,
|
||||
LOONGARCH_GPR_T8,
|
||||
LOONGARCH_GPR_FP = 22,
|
||||
LOONGARCH_GPR_S0 = 23,
|
||||
LOONGARCH_GPR_S1,
|
||||
LOONGARCH_GPR_S2,
|
||||
LOONGARCH_GPR_S3,
|
||||
LOONGARCH_GPR_S4,
|
||||
LOONGARCH_GPR_S5,
|
||||
LOONGARCH_GPR_S6,
|
||||
LOONGARCH_GPR_S7,
|
||||
LOONGARCH_GPR_S8,
|
||||
LOONGARCH_GPR_MAX
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
#endif /* _ASM_INST_H */
|
129
arch/loongarch/include/asm/io.h
Normal file
129
arch/loongarch/include/asm/io.h
Normal file
@ -0,0 +1,129 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_IO_H
|
||||
#define _ASM_IO_H
|
||||
|
||||
#define ARCH_HAS_IOREMAP_WC
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/bug.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable-bits.h>
|
||||
#include <asm/string.h>
|
||||
|
||||
/*
|
||||
* On LoongArch, I/O ports mappring is following:
|
||||
*
|
||||
* | .... |
|
||||
* |-----------------------|
|
||||
* | pci io ports(64K~32M) |
|
||||
* |-----------------------|
|
||||
* | isa io ports(0 ~16K) |
|
||||
* PCI_IOBASE ->|-----------------------|
|
||||
* | .... |
|
||||
*/
|
||||
#define PCI_IOBASE ((void __iomem *)(vm_map_base + (2 * PAGE_SIZE)))
|
||||
#define PCI_IOSIZE SZ_32M
|
||||
#define ISA_IOSIZE SZ_16K
|
||||
#define IO_SPACE_LIMIT (PCI_IOSIZE - 1)
|
||||
|
||||
/*
|
||||
* Change "struct page" to physical address.
|
||||
*/
|
||||
#define page_to_phys(page) ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT)
|
||||
|
||||
extern void __init __iomem *early_ioremap(u64 phys_addr, unsigned long size);
|
||||
extern void __init early_iounmap(void __iomem *addr, unsigned long size);
|
||||
|
||||
#define early_memremap early_ioremap
|
||||
#define early_memunmap early_iounmap
|
||||
|
||||
static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
|
||||
unsigned long prot_val)
|
||||
{
|
||||
if (prot_val == _CACHE_CC)
|
||||
return (void __iomem *)(unsigned long)(CACHE_BASE + offset);
|
||||
else
|
||||
return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* ioremap - map bus memory into CPU space
|
||||
* @offset: bus address of the memory
|
||||
* @size: size of the resource to map
|
||||
*
|
||||
* ioremap performs a platform specific sequence of operations to
|
||||
* make bus memory CPU accessible via the readb/readw/readl/writeb/
|
||||
* writew/writel functions and the other mmio helpers. The returned
|
||||
* address is not guaranteed to be usable directly as a virtual
|
||||
* address.
|
||||
*/
|
||||
#define ioremap(offset, size) \
|
||||
ioremap_prot((offset), (size), _CACHE_SUC)
|
||||
|
||||
/*
|
||||
* ioremap_wc - map bus memory into CPU space
|
||||
* @offset: bus address of the memory
|
||||
* @size: size of the resource to map
|
||||
*
|
||||
* ioremap_wc performs a platform specific sequence of operations to
|
||||
* make bus memory CPU accessible via the readb/readw/readl/writeb/
|
||||
* writew/writel functions and the other mmio helpers. The returned
|
||||
* address is not guaranteed to be usable directly as a virtual
|
||||
* address.
|
||||
*
|
||||
* This version of ioremap ensures that the memory is marked uncachable
|
||||
* but accelerated by means of write-combining feature. It is specifically
|
||||
* useful for PCIe prefetchable windows, which may vastly improve a
|
||||
* communications performance. If it was determined on boot stage, what
|
||||
* CPU CCA doesn't support WUC, the method shall fall-back to the
|
||||
* _CACHE_SUC option (see cpu_probe() method).
|
||||
*/
|
||||
#define ioremap_wc(offset, size) \
|
||||
ioremap_prot((offset), (size), _CACHE_WUC)
|
||||
|
||||
/*
|
||||
* ioremap_cache - map bus memory into CPU space
|
||||
* @offset: bus address of the memory
|
||||
* @size: size of the resource to map
|
||||
*
|
||||
* ioremap_cache performs a platform specific sequence of operations to
|
||||
* make bus memory CPU accessible via the readb/readw/readl/writeb/
|
||||
* writew/writel functions and the other mmio helpers. The returned
|
||||
* address is not guaranteed to be usable directly as a virtual
|
||||
* address.
|
||||
*
|
||||
* This version of ioremap ensures that the memory is marked cachable by
|
||||
* the CPU. Also enables full write-combining. Useful for some
|
||||
* memory-like regions on I/O busses.
|
||||
*/
|
||||
#define ioremap_cache(offset, size) \
|
||||
ioremap_prot((offset), (size), _CACHE_CC)
|
||||
|
||||
static inline void iounmap(const volatile void __iomem *addr)
|
||||
{
|
||||
}
|
||||
|
||||
#define mmiowb() asm volatile ("dbar 0" ::: "memory")
|
||||
|
||||
/*
|
||||
* String version of I/O memory access operations.
|
||||
*/
|
||||
extern void __memset_io(volatile void __iomem *dst, int c, size_t count);
|
||||
extern void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count);
|
||||
extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count);
|
||||
#define memset_io(c, v, l) __memset_io((c), (v), (l))
|
||||
#define memcpy_fromio(a, c, l) __memcpy_fromio((a), (c), (l))
|
||||
#define memcpy_toio(c, a, l) __memcpy_toio((c), (a), (l))
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
#endif /* _ASM_IO_H */
|
132
arch/loongarch/include/asm/irq.h
Normal file
132
arch/loongarch/include/asm/irq.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_IRQ_H
|
||||
#define _ASM_IRQ_H
|
||||
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqreturn.h>
|
||||
|
||||
#define IRQ_STACK_SIZE THREAD_SIZE
|
||||
#define IRQ_STACK_START (IRQ_STACK_SIZE - 16)
|
||||
|
||||
DECLARE_PER_CPU(unsigned long, irq_stack);
|
||||
|
||||
/*
|
||||
* The highest address on the IRQ stack contains a dummy frame which is
|
||||
* structured as follows:
|
||||
*
|
||||
* top ------------
|
||||
* | task sp | <- irq_stack[cpu] + IRQ_STACK_START
|
||||
* ------------
|
||||
* | | <- First frame of IRQ context
|
||||
* ------------
|
||||
*
|
||||
* task sp holds a copy of the task stack pointer where the struct pt_regs
|
||||
* from exception entry can be found.
|
||||
*/
|
||||
|
||||
static inline bool on_irq_stack(int cpu, unsigned long sp)
|
||||
{
|
||||
unsigned long low = per_cpu(irq_stack, cpu);
|
||||
unsigned long high = low + IRQ_STACK_SIZE;
|
||||
|
||||
return (low <= sp && sp <= high);
|
||||
}
|
||||
|
||||
int get_ipi_irq(void);
|
||||
int get_pmc_irq(void);
|
||||
int get_timer_irq(void);
|
||||
void spurious_interrupt(void);
|
||||
|
||||
#define NR_IRQS_LEGACY 16
|
||||
|
||||
#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
|
||||
void arch_trigger_cpumask_backtrace(const struct cpumask *mask, bool exclude_self);
|
||||
|
||||
#define MAX_IO_PICS 2
|
||||
#define NR_IRQS (64 + (256 * MAX_IO_PICS))
|
||||
|
||||
#define CORES_PER_EIO_NODE 4
|
||||
|
||||
#define LOONGSON_CPU_UART0_VEC 10 /* CPU UART0 */
|
||||
#define LOONGSON_CPU_THSENS_VEC 14 /* CPU Thsens */
|
||||
#define LOONGSON_CPU_HT0_VEC 16 /* CPU HT0 irq vector base number */
|
||||
#define LOONGSON_CPU_HT1_VEC 24 /* CPU HT1 irq vector base number */
|
||||
|
||||
/* IRQ number definitions */
|
||||
#define LOONGSON_LPC_IRQ_BASE 0
|
||||
#define LOONGSON_LPC_LAST_IRQ (LOONGSON_LPC_IRQ_BASE + 15)
|
||||
|
||||
#define LOONGSON_CPU_IRQ_BASE 16
|
||||
#define LOONGSON_CPU_LAST_IRQ (LOONGSON_CPU_IRQ_BASE + 14)
|
||||
|
||||
#define LOONGSON_PCH_IRQ_BASE 64
|
||||
#define LOONGSON_PCH_ACPI_IRQ (LOONGSON_PCH_IRQ_BASE + 47)
|
||||
#define LOONGSON_PCH_LAST_IRQ (LOONGSON_PCH_IRQ_BASE + 64 - 1)
|
||||
|
||||
#define LOONGSON_MSI_IRQ_BASE (LOONGSON_PCH_IRQ_BASE + 64)
|
||||
#define LOONGSON_MSI_LAST_IRQ (LOONGSON_PCH_IRQ_BASE + 256 - 1)
|
||||
|
||||
#define GSI_MIN_LPC_IRQ LOONGSON_LPC_IRQ_BASE
|
||||
#define GSI_MAX_LPC_IRQ (LOONGSON_LPC_IRQ_BASE + 16 - 1)
|
||||
#define GSI_MIN_CPU_IRQ LOONGSON_CPU_IRQ_BASE
|
||||
#define GSI_MAX_CPU_IRQ (LOONGSON_CPU_IRQ_BASE + 48 - 1)
|
||||
#define GSI_MIN_PCH_IRQ LOONGSON_PCH_IRQ_BASE
|
||||
#define GSI_MAX_PCH_IRQ (LOONGSON_PCH_IRQ_BASE + 256 - 1)
|
||||
|
||||
extern int find_pch_pic(u32 gsi);
|
||||
extern int eiointc_get_node(int id);
|
||||
|
||||
static inline void eiointc_enable(void)
|
||||
{
|
||||
uint64_t misc;
|
||||
|
||||
misc = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC);
|
||||
misc |= IOCSR_MISC_FUNC_EXT_IOI_EN;
|
||||
iocsr_write64(misc, LOONGARCH_IOCSR_MISC_FUNC);
|
||||
}
|
||||
|
||||
struct acpi_madt_lio_pic;
|
||||
struct acpi_madt_eio_pic;
|
||||
struct acpi_madt_ht_pic;
|
||||
struct acpi_madt_bio_pic;
|
||||
struct acpi_madt_msi_pic;
|
||||
struct acpi_madt_lpc_pic;
|
||||
|
||||
struct irq_domain *loongarch_cpu_irq_init(void);
|
||||
|
||||
struct irq_domain *liointc_acpi_init(struct irq_domain *parent,
|
||||
struct acpi_madt_lio_pic *acpi_liointc);
|
||||
struct irq_domain *eiointc_acpi_init(struct irq_domain *parent,
|
||||
struct acpi_madt_eio_pic *acpi_eiointc);
|
||||
|
||||
struct irq_domain *htvec_acpi_init(struct irq_domain *parent,
|
||||
struct acpi_madt_ht_pic *acpi_htvec);
|
||||
struct irq_domain *pch_lpc_acpi_init(struct irq_domain *parent,
|
||||
struct acpi_madt_lpc_pic *acpi_pchlpc);
|
||||
struct irq_domain *pch_msi_acpi_init(struct irq_domain *parent,
|
||||
struct acpi_madt_msi_pic *acpi_pchmsi);
|
||||
struct irq_domain *pch_pic_acpi_init(struct irq_domain *parent,
|
||||
struct acpi_madt_bio_pic *acpi_pchpic);
|
||||
|
||||
extern struct acpi_madt_lio_pic *acpi_liointc;
|
||||
extern struct acpi_madt_eio_pic *acpi_eiointc[MAX_IO_PICS];
|
||||
|
||||
extern struct acpi_madt_ht_pic *acpi_htintc;
|
||||
extern struct acpi_madt_lpc_pic *acpi_pchlpc;
|
||||
extern struct acpi_madt_msi_pic *acpi_pchmsi[MAX_IO_PICS];
|
||||
extern struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS];
|
||||
|
||||
extern struct irq_domain *cpu_domain;
|
||||
extern struct irq_domain *liointc_domain;
|
||||
extern struct irq_domain *pch_lpc_domain;
|
||||
extern struct irq_domain *pch_msi_domain[MAX_IO_PICS];
|
||||
extern struct irq_domain *pch_pic_domain[MAX_IO_PICS];
|
||||
|
||||
extern irqreturn_t loongson3_ipi_interrupt(int irq, void *dev);
|
||||
|
||||
#include <asm-generic/irq.h>
|
||||
|
||||
#endif /* _ASM_IRQ_H */
|
27
arch/loongarch/include/asm/irq_regs.h
Normal file
27
arch/loongarch/include/asm/irq_regs.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_IRQ_REGS_H
|
||||
#define __ASM_IRQ_REGS_H
|
||||
|
||||
#define ARCH_HAS_OWN_IRQ_REGS
|
||||
|
||||
#include <linux/thread_info.h>
|
||||
|
||||
static inline struct pt_regs *get_irq_regs(void)
|
||||
{
|
||||
return current_thread_info()->regs;
|
||||
}
|
||||
|
||||
static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
|
||||
{
|
||||
struct pt_regs *old_regs;
|
||||
|
||||
old_regs = get_irq_regs();
|
||||
current_thread_info()->regs = new_regs;
|
||||
|
||||
return old_regs;
|
||||
}
|
||||
|
||||
#endif /* __ASM_IRQ_REGS_H */
|
78
arch/loongarch/include/asm/irqflags.h
Normal file
78
arch/loongarch/include/asm/irqflags.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_IRQFLAGS_H
|
||||
#define _ASM_IRQFLAGS_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/loongarch.h>
|
||||
|
||||
static inline void arch_local_irq_enable(void)
|
||||
{
|
||||
u32 flags = CSR_CRMD_IE;
|
||||
__asm__ __volatile__(
|
||||
"csrxchg %[val], %[mask], %[reg]\n\t"
|
||||
: [val] "+r" (flags)
|
||||
: [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_disable(void)
|
||||
{
|
||||
u32 flags = 0;
|
||||
__asm__ __volatile__(
|
||||
"csrxchg %[val], %[mask], %[reg]\n\t"
|
||||
: [val] "+r" (flags)
|
||||
: [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline unsigned long arch_local_irq_save(void)
|
||||
{
|
||||
u32 flags = 0;
|
||||
__asm__ __volatile__(
|
||||
"csrxchg %[val], %[mask], %[reg]\n\t"
|
||||
: [val] "+r" (flags)
|
||||
: [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
|
||||
: "memory");
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_restore(unsigned long flags)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"csrxchg %[val], %[mask], %[reg]\n\t"
|
||||
: [val] "+r" (flags)
|
||||
: [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline unsigned long arch_local_save_flags(void)
|
||||
{
|
||||
u32 flags;
|
||||
__asm__ __volatile__(
|
||||
"csrrd %[val], %[reg]\n\t"
|
||||
: [val] "=r" (flags)
|
||||
: [reg] "i" (LOONGARCH_CSR_CRMD)
|
||||
: "memory");
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline int arch_irqs_disabled_flags(unsigned long flags)
|
||||
{
|
||||
return !(flags & CSR_CRMD_IE);
|
||||
}
|
||||
|
||||
static inline int arch_irqs_disabled(void)
|
||||
{
|
||||
return arch_irqs_disabled_flags(arch_local_save_flags());
|
||||
}
|
||||
|
||||
#endif /* #ifndef __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_IRQFLAGS_H */
|
23
arch/loongarch/include/asm/kdebug.h
Normal file
23
arch/loongarch/include/asm/kdebug.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_LOONGARCH_KDEBUG_H
|
||||
#define _ASM_LOONGARCH_KDEBUG_H
|
||||
|
||||
#include <linux/notifier.h>
|
||||
|
||||
enum die_val {
|
||||
DIE_OOPS = 1,
|
||||
DIE_RI,
|
||||
DIE_FP,
|
||||
DIE_SIMD,
|
||||
DIE_TRAP,
|
||||
DIE_PAGE_FAULT,
|
||||
DIE_BREAK,
|
||||
DIE_SSTEPBP,
|
||||
DIE_UPROBE,
|
||||
DIE_UPROBE_XOL,
|
||||
};
|
||||
|
||||
#endif /* _ASM_LOONGARCH_KDEBUG_H */
|
36
arch/loongarch/include/asm/linkage.h
Normal file
36
arch/loongarch/include/asm/linkage.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_LINKAGE_H
|
||||
#define __ASM_LINKAGE_H
|
||||
|
||||
#define __ALIGN .align 2
|
||||
#define __ALIGN_STR __stringify(__ALIGN)
|
||||
|
||||
#define SYM_FUNC_START(name) \
|
||||
SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) \
|
||||
.cfi_startproc;
|
||||
|
||||
#define SYM_FUNC_START_NOALIGN(name) \
|
||||
SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) \
|
||||
.cfi_startproc;
|
||||
|
||||
#define SYM_FUNC_START_LOCAL(name) \
|
||||
SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) \
|
||||
.cfi_startproc;
|
||||
|
||||
#define SYM_FUNC_START_LOCAL_NOALIGN(name) \
|
||||
SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) \
|
||||
.cfi_startproc;
|
||||
|
||||
#define SYM_FUNC_START_WEAK(name) \
|
||||
SYM_START(name, SYM_L_WEAK, SYM_A_ALIGN) \
|
||||
.cfi_startproc;
|
||||
|
||||
#define SYM_FUNC_START_WEAK_NOALIGN(name) \
|
||||
SYM_START(name, SYM_L_WEAK, SYM_A_NONE) \
|
||||
.cfi_startproc;
|
||||
|
||||
#define SYM_FUNC_END(name) \
|
||||
.cfi_endproc; \
|
||||
SYM_END(name, SYM_T_FUNC)
|
||||
|
||||
#endif
|
138
arch/loongarch/include/asm/local.h
Normal file
138
arch/loongarch/include/asm/local.h
Normal file
@ -0,0 +1,138 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ARCH_LOONGARCH_LOCAL_H
|
||||
#define _ARCH_LOONGARCH_LOCAL_H
|
||||
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/cmpxchg.h>
|
||||
#include <asm/compiler.h>
|
||||
|
||||
typedef struct {
|
||||
atomic_long_t a;
|
||||
} local_t;
|
||||
|
||||
#define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) }
|
||||
|
||||
#define local_read(l) atomic_long_read(&(l)->a)
|
||||
#define local_set(l, i) atomic_long_set(&(l)->a, (i))
|
||||
|
||||
#define local_add(i, l) atomic_long_add((i), (&(l)->a))
|
||||
#define local_sub(i, l) atomic_long_sub((i), (&(l)->a))
|
||||
#define local_inc(l) atomic_long_inc(&(l)->a)
|
||||
#define local_dec(l) atomic_long_dec(&(l)->a)
|
||||
|
||||
/*
|
||||
* Same as above, but return the result value
|
||||
*/
|
||||
static inline long local_add_return(long i, local_t *l)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" " __AMADD " %1, %2, %0 \n"
|
||||
: "+ZB" (l->a.counter), "=&r" (result)
|
||||
: "r" (i)
|
||||
: "memory");
|
||||
result = result + i;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline long local_sub_return(long i, local_t *l)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" " __AMADD "%1, %2, %0 \n"
|
||||
: "+ZB" (l->a.counter), "=&r" (result)
|
||||
: "r" (-i)
|
||||
: "memory");
|
||||
|
||||
result = result - i;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define local_cmpxchg(l, o, n) \
|
||||
((long)cmpxchg_local(&((l)->a.counter), (o), (n)))
|
||||
#define local_xchg(l, n) (atomic_long_xchg((&(l)->a), (n)))
|
||||
|
||||
/**
|
||||
* local_add_unless - add unless the number is a given value
|
||||
* @l: pointer of type local_t
|
||||
* @a: the amount to add to l...
|
||||
* @u: ...unless l is equal to u.
|
||||
*
|
||||
* Atomically adds @a to @l, so long as it was not @u.
|
||||
* Returns non-zero if @l was not @u, and zero otherwise.
|
||||
*/
|
||||
#define local_add_unless(l, a, u) \
|
||||
({ \
|
||||
long c, old; \
|
||||
c = local_read(l); \
|
||||
while (c != (u) && (old = local_cmpxchg((l), c, c + (a))) != c) \
|
||||
c = old; \
|
||||
c != (u); \
|
||||
})
|
||||
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
|
||||
|
||||
#define local_dec_return(l) local_sub_return(1, (l))
|
||||
#define local_inc_return(l) local_add_return(1, (l))
|
||||
|
||||
/*
|
||||
* local_sub_and_test - subtract value from variable and test result
|
||||
* @i: integer value to subtract
|
||||
* @l: pointer of type local_t
|
||||
*
|
||||
* Atomically subtracts @i from @l and returns
|
||||
* true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
#define local_sub_and_test(i, l) (local_sub_return((i), (l)) == 0)
|
||||
|
||||
/*
|
||||
* local_inc_and_test - increment and test
|
||||
* @l: pointer of type local_t
|
||||
*
|
||||
* Atomically increments @l by 1
|
||||
* and returns true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
#define local_inc_and_test(l) (local_inc_return(l) == 0)
|
||||
|
||||
/*
|
||||
* local_dec_and_test - decrement by 1 and test
|
||||
* @l: pointer of type local_t
|
||||
*
|
||||
* Atomically decrements @l by 1 and
|
||||
* returns true if the result is 0, or false for all other
|
||||
* cases.
|
||||
*/
|
||||
#define local_dec_and_test(l) (local_sub_return(1, (l)) == 0)
|
||||
|
||||
/*
|
||||
* local_add_negative - add and test if negative
|
||||
* @l: pointer of type local_t
|
||||
* @i: integer value to add
|
||||
*
|
||||
* Atomically adds @i to @l and returns true
|
||||
* if the result is negative, or false when
|
||||
* result is greater than or equal to zero.
|
||||
*/
|
||||
#define local_add_negative(i, l) (local_add_return(i, (l)) < 0)
|
||||
|
||||
/* Use these for per-cpu local_t variables: on some archs they are
|
||||
* much more efficient than these naive implementations. Note they take
|
||||
* a variable, not an address.
|
||||
*/
|
||||
|
||||
#define __local_inc(l) ((l)->a.counter++)
|
||||
#define __local_dec(l) ((l)->a.counter++)
|
||||
#define __local_add(i, l) ((l)->a.counter += (i))
|
||||
#define __local_sub(i, l) ((l)->a.counter -= (i))
|
||||
|
||||
#endif /* _ARCH_LOONGARCH_LOCAL_H */
|
1516
arch/loongarch/include/asm/loongarch.h
Normal file
1516
arch/loongarch/include/asm/loongarch.h
Normal file
File diff suppressed because it is too large
Load Diff
153
arch/loongarch/include/asm/loongson.h
Normal file
153
arch/loongarch/include/asm/loongson.h
Normal file
@ -0,0 +1,153 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Author: Huacai Chen <chenhuacai@loongson.cn>
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef __ASM_LOONGSON_H
|
||||
#define __ASM_LOONGSON_H
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/bootinfo.h>
|
||||
|
||||
extern const struct plat_smp_ops loongson3_smp_ops;
|
||||
|
||||
#define LOONGSON_REG(x) \
|
||||
(*(volatile u32 *)((char *)TO_UNCACHE(LOONGSON_REG_BASE) + (x)))
|
||||
|
||||
#define LOONGSON_LIO_BASE 0x18000000
|
||||
#define LOONGSON_LIO_SIZE 0x00100000 /* 1M */
|
||||
#define LOONGSON_LIO_TOP (LOONGSON_LIO_BASE+LOONGSON_LIO_SIZE-1)
|
||||
|
||||
#define LOONGSON_BOOT_BASE 0x1c000000
|
||||
#define LOONGSON_BOOT_SIZE 0x02000000 /* 32M */
|
||||
#define LOONGSON_BOOT_TOP (LOONGSON_BOOT_BASE+LOONGSON_BOOT_SIZE-1)
|
||||
|
||||
#define LOONGSON_REG_BASE 0x1fe00000
|
||||
#define LOONGSON_REG_SIZE 0x00100000 /* 1M */
|
||||
#define LOONGSON_REG_TOP (LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
|
||||
|
||||
/* GPIO Regs - r/w */
|
||||
|
||||
#define LOONGSON_GPIODATA LOONGSON_REG(0x11c)
|
||||
#define LOONGSON_GPIOIE LOONGSON_REG(0x120)
|
||||
#define LOONGSON_REG_GPIO_BASE (LOONGSON_REG_BASE + 0x11c)
|
||||
|
||||
#define MAX_PACKAGES 16
|
||||
|
||||
/* Chip Config register of each physical cpu package */
|
||||
extern u64 loongson_chipcfg[MAX_PACKAGES];
|
||||
#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))
|
||||
|
||||
/* Chip Temperature register of each physical cpu package */
|
||||
extern u64 loongson_chiptemp[MAX_PACKAGES];
|
||||
#define LOONGSON_CHIPTEMP(id) (*(volatile u32 *)(loongson_chiptemp[id]))
|
||||
|
||||
/* Freq Control register of each physical cpu package */
|
||||
extern u64 loongson_freqctrl[MAX_PACKAGES];
|
||||
#define LOONGSON_FREQCTRL(id) (*(volatile u32 *)(loongson_freqctrl[id]))
|
||||
|
||||
#define xconf_readl(addr) readl(addr)
|
||||
#define xconf_readq(addr) readq(addr)
|
||||
|
||||
static inline void xconf_writel(u32 val, volatile void __iomem *addr)
|
||||
{
|
||||
asm volatile (
|
||||
" st.w %[v], %[hw], 0 \n"
|
||||
" ld.b $r0, %[hw], 0 \n"
|
||||
:
|
||||
: [hw] "r" (addr), [v] "r" (val)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void xconf_writeq(u64 val64, volatile void __iomem *addr)
|
||||
{
|
||||
asm volatile (
|
||||
" st.d %[v], %[hw], 0 \n"
|
||||
" ld.b $r0, %[hw], 0 \n"
|
||||
:
|
||||
: [hw] "r" (addr), [v] "r" (val64)
|
||||
);
|
||||
}
|
||||
|
||||
/* ============== LS7A registers =============== */
|
||||
#define LS7A_PCH_REG_BASE 0x10000000UL
|
||||
/* LPC regs */
|
||||
#define LS7A_LPC_REG_BASE (LS7A_PCH_REG_BASE + 0x00002000)
|
||||
/* CHIPCFG regs */
|
||||
#define LS7A_CHIPCFG_REG_BASE (LS7A_PCH_REG_BASE + 0x00010000)
|
||||
/* MISC reg base */
|
||||
#define LS7A_MISC_REG_BASE (LS7A_PCH_REG_BASE + 0x00080000)
|
||||
/* ACPI regs */
|
||||
#define LS7A_ACPI_REG_BASE (LS7A_MISC_REG_BASE + 0x00050000)
|
||||
/* RTC regs */
|
||||
#define LS7A_RTC_REG_BASE (LS7A_MISC_REG_BASE + 0x00050100)
|
||||
|
||||
#define LS7A_DMA_CFG (volatile void *)TO_UNCACHE(LS7A_CHIPCFG_REG_BASE + 0x041c)
|
||||
#define LS7A_DMA_NODE_SHF 8
|
||||
#define LS7A_DMA_NODE_MASK 0x1F00
|
||||
|
||||
#define LS7A_INT_MASK_REG (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x020)
|
||||
#define LS7A_INT_EDGE_REG (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x060)
|
||||
#define LS7A_INT_CLEAR_REG (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x080)
|
||||
#define LS7A_INT_HTMSI_EN_REG (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x040)
|
||||
#define LS7A_INT_ROUTE_ENTRY_REG (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x100)
|
||||
#define LS7A_INT_HTMSI_VEC_REG (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x200)
|
||||
#define LS7A_INT_STATUS_REG (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x3a0)
|
||||
#define LS7A_INT_POL_REG (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x3e0)
|
||||
#define LS7A_LPC_INT_CTL (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x2000)
|
||||
#define LS7A_LPC_INT_ENA (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x2004)
|
||||
#define LS7A_LPC_INT_STS (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x2008)
|
||||
#define LS7A_LPC_INT_CLR (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x200c)
|
||||
#define LS7A_LPC_INT_POL (volatile void *)TO_UNCACHE(LS7A_PCH_REG_BASE + 0x2010)
|
||||
|
||||
#define LS7A_PMCON_SOC_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x000)
|
||||
#define LS7A_PMCON_RESUME_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x004)
|
||||
#define LS7A_PMCON_RTC_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x008)
|
||||
#define LS7A_PM1_EVT_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x00c)
|
||||
#define LS7A_PM1_ENA_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x010)
|
||||
#define LS7A_PM1_CNT_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x014)
|
||||
#define LS7A_PM1_TMR_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x018)
|
||||
#define LS7A_P_CNT_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x01c)
|
||||
#define LS7A_GPE0_STS_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x028)
|
||||
#define LS7A_GPE0_ENA_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x02c)
|
||||
#define LS7A_RST_CNT_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x030)
|
||||
#define LS7A_WD_SET_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x034)
|
||||
#define LS7A_WD_TIMER_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x038)
|
||||
#define LS7A_THSENS_CNT_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x04c)
|
||||
#define LS7A_GEN_RTC_1_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x050)
|
||||
#define LS7A_GEN_RTC_2_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x054)
|
||||
#define LS7A_DPM_CFG_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x400)
|
||||
#define LS7A_DPM_STS_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x404)
|
||||
#define LS7A_DPM_CNT_REG (volatile void *)TO_UNCACHE(LS7A_ACPI_REG_BASE + 0x408)
|
||||
|
||||
typedef enum {
|
||||
ACPI_PCI_HOTPLUG_STATUS = 1 << 1,
|
||||
ACPI_CPU_HOTPLUG_STATUS = 1 << 2,
|
||||
ACPI_MEM_HOTPLUG_STATUS = 1 << 3,
|
||||
ACPI_POWERBUTTON_STATUS = 1 << 8,
|
||||
ACPI_RTC_WAKE_STATUS = 1 << 10,
|
||||
ACPI_PCI_WAKE_STATUS = 1 << 14,
|
||||
ACPI_ANY_WAKE_STATUS = 1 << 15,
|
||||
} AcpiEventStatusBits;
|
||||
|
||||
#define HT1LO_OFFSET 0xe0000000000UL
|
||||
|
||||
/* PCI Configuration Space Base */
|
||||
#define MCFG_EXT_PCICFG_BASE 0xefe00000000UL
|
||||
|
||||
/* REG ACCESS*/
|
||||
#define ls7a_readb(addr) (*(volatile unsigned char *)TO_UNCACHE(addr))
|
||||
#define ls7a_readw(addr) (*(volatile unsigned short *)TO_UNCACHE(addr))
|
||||
#define ls7a_readl(addr) (*(volatile unsigned int *)TO_UNCACHE(addr))
|
||||
#define ls7a_readq(addr) (*(volatile unsigned long *)TO_UNCACHE(addr))
|
||||
#define ls7a_writeb(val, addr) *(volatile unsigned char *)TO_UNCACHE(addr) = (val)
|
||||
#define ls7a_writew(val, addr) *(volatile unsigned short *)TO_UNCACHE(addr) = (val)
|
||||
#define ls7a_writel(val, addr) *(volatile unsigned int *)TO_UNCACHE(addr) = (val)
|
||||
#define ls7a_writeq(val, addr) *(volatile unsigned long *)TO_UNCACHE(addr) = (val)
|
||||
|
||||
#endif /* __ASM_LOONGSON_H */
|
16
arch/loongarch/include/asm/mmu.h
Normal file
16
arch/loongarch/include/asm/mmu.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_MMU_H
|
||||
#define __ASM_MMU_H
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
typedef struct {
|
||||
u64 asid[NR_CPUS];
|
||||
void *vdso;
|
||||
} mm_context_t;
|
||||
|
||||
#endif /* __ASM_MMU_H */
|
152
arch/loongarch/include/asm/mmu_context.h
Normal file
152
arch/loongarch/include/asm/mmu_context.h
Normal file
@ -0,0 +1,152 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Switch a MMU context.
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_MMU_CONTEXT_H
|
||||
#define _ASM_MMU_CONTEXT_H
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm-generic/mm_hooks.h>
|
||||
|
||||
/*
|
||||
* All unused by hardware upper bits will be considered
|
||||
* as a software asid extension.
|
||||
*/
|
||||
static inline u64 asid_version_mask(unsigned int cpu)
|
||||
{
|
||||
return ~(u64)(cpu_asid_mask(&cpu_data[cpu]));
|
||||
}
|
||||
|
||||
static inline u64 asid_first_version(unsigned int cpu)
|
||||
{
|
||||
return cpu_asid_mask(&cpu_data[cpu]) + 1;
|
||||
}
|
||||
|
||||
#define cpu_context(cpu, mm) ((mm)->context.asid[cpu])
|
||||
#define asid_cache(cpu) (cpu_data[cpu].asid_cache)
|
||||
#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & cpu_asid_mask(&cpu_data[cpu]))
|
||||
|
||||
static inline int asid_valid(struct mm_struct *mm, unsigned int cpu)
|
||||
{
|
||||
if ((cpu_context(cpu, mm) ^ asid_cache(cpu)) & asid_version_mask(cpu))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
|
||||
{
|
||||
}
|
||||
|
||||
/* Normal, classic get_new_mmu_context */
|
||||
static inline void
|
||||
get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
|
||||
{
|
||||
u64 asid = asid_cache(cpu);
|
||||
|
||||
if (!((++asid) & cpu_asid_mask(&cpu_data[cpu])))
|
||||
local_flush_tlb_user(); /* start new asid cycle */
|
||||
|
||||
cpu_context(cpu, mm) = asid_cache(cpu) = asid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the context related info for a new mm_struct
|
||||
* instance.
|
||||
*/
|
||||
static inline int
|
||||
init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_possible_cpu(i)
|
||||
cpu_context(i, mm) = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
/* Check if our ASID is of an older version and thus invalid */
|
||||
if (!asid_valid(next, cpu))
|
||||
get_new_mmu_context(next, cpu);
|
||||
|
||||
write_csr_asid(cpu_asid(cpu, next));
|
||||
|
||||
if (next != &init_mm)
|
||||
csr_write64((unsigned long)next->pgd, LOONGARCH_CSR_PGDL);
|
||||
else
|
||||
csr_write64((unsigned long)invalid_pg_dir, LOONGARCH_CSR_PGDL);
|
||||
|
||||
/*
|
||||
* Mark current->active_mm as not "active" anymore.
|
||||
* We don't want to mislead possible IPI tlb flush routines.
|
||||
*/
|
||||
cpumask_set_cpu(cpu, mm_cpumask(next));
|
||||
}
|
||||
|
||||
#define switch_mm_irqs_off switch_mm_irqs_off
|
||||
|
||||
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
switch_mm_irqs_off(prev, next, tsk);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy context related info for an mm_struct that is about
|
||||
* to be put to rest.
|
||||
*/
|
||||
static inline void destroy_context(struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
|
||||
#define activate_mm(prev, next) switch_mm(prev, next, current)
|
||||
#define deactivate_mm(task, mm) do { } while (0)
|
||||
|
||||
/*
|
||||
* If mm is currently active, we can't really drop it.
|
||||
* Instead, we will get a new one for it.
|
||||
*/
|
||||
static inline void
|
||||
drop_mmu_context(struct mm_struct *mm, unsigned int cpu)
|
||||
{
|
||||
int asid;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
asid = read_csr_asid() & cpu_asid_mask(¤t_cpu_data);
|
||||
|
||||
if (asid == cpu_asid(cpu, mm)) {
|
||||
if (!current->mm || (current->mm == mm)) {
|
||||
get_new_mmu_context(mm, cpu);
|
||||
write_csr_asid(cpu_asid(cpu, mm));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Will get a new context next time */
|
||||
cpu_context(cpu, mm) = 0;
|
||||
cpumask_clear_cpu(cpu, mm_cpumask(mm));
|
||||
out:
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
#endif /* _ASM_MMU_CONTEXT_H */
|
18
arch/loongarch/include/asm/mmzone.h
Normal file
18
arch/loongarch/include/asm/mmzone.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Author: Huacai Chen (chenhuacai@loongson.cn)
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_MMZONE_H_
|
||||
#define _ASM_MMZONE_H_
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/numa.h>
|
||||
|
||||
extern struct pglist_data *node_data[];
|
||||
|
||||
#define NODE_DATA(nid) (node_data[(nid)])
|
||||
|
||||
extern void setup_zero_pages(void);
|
||||
|
||||
#endif /* _ASM_MMZONE_H_ */
|
80
arch/loongarch/include/asm/module.h
Normal file
80
arch/loongarch/include/asm/module.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_MODULE_H
|
||||
#define _ASM_MODULE_H
|
||||
|
||||
#include <asm/inst.h>
|
||||
#include <asm-generic/module.h>
|
||||
|
||||
#define RELA_STACK_DEPTH 16
|
||||
|
||||
struct mod_section {
|
||||
Elf_Shdr *shdr;
|
||||
int num_entries;
|
||||
int max_entries;
|
||||
};
|
||||
|
||||
struct mod_arch_specific {
|
||||
struct mod_section plt;
|
||||
struct mod_section plt_idx;
|
||||
};
|
||||
|
||||
struct plt_entry {
|
||||
u32 inst_lu12iw;
|
||||
u32 inst_lu32id;
|
||||
u32 inst_lu52id;
|
||||
u32 inst_jirl;
|
||||
};
|
||||
|
||||
struct plt_idx_entry {
|
||||
unsigned long symbol_addr;
|
||||
};
|
||||
|
||||
Elf_Addr module_emit_plt_entry(struct module *mod, unsigned long val);
|
||||
|
||||
static inline struct plt_entry emit_plt_entry(unsigned long val)
|
||||
{
|
||||
u32 lu12iw, lu32id, lu52id, jirl;
|
||||
|
||||
lu12iw = (lu12iw_op << 25 | (((val >> 12) & 0xfffff) << 5) | LOONGARCH_GPR_T1);
|
||||
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));
|
||||
|
||||
return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl };
|
||||
}
|
||||
|
||||
static inline struct plt_idx_entry emit_plt_idx_entry(unsigned long val)
|
||||
{
|
||||
return (struct plt_idx_entry) { val };
|
||||
}
|
||||
|
||||
static inline int get_plt_idx(unsigned long val, const struct mod_section *sec)
|
||||
{
|
||||
int i;
|
||||
struct plt_idx_entry *plt_idx = (struct plt_idx_entry *)sec->shdr->sh_addr;
|
||||
|
||||
for (i = 0; i < sec->num_entries; i++) {
|
||||
if (plt_idx[i].symbol_addr == val)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline struct plt_entry *get_plt_entry(unsigned long val,
|
||||
const struct mod_section *sec_plt,
|
||||
const struct mod_section *sec_plt_idx)
|
||||
{
|
||||
int plt_idx = get_plt_idx(val, sec_plt_idx);
|
||||
struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr;
|
||||
|
||||
if (plt_idx < 0)
|
||||
return NULL;
|
||||
|
||||
return plt + plt_idx;
|
||||
}
|
||||
|
||||
#endif /* _ASM_MODULE_H */
|
7
arch/loongarch/include/asm/module.lds.h
Normal file
7
arch/loongarch/include/asm/module.lds.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2020-2022 Loongson Technology Corporation Limited */
|
||||
SECTIONS {
|
||||
. = ALIGN(4);
|
||||
.plt : { BYTE(0) }
|
||||
.plt.idx : { BYTE(0) }
|
||||
}
|
67
arch/loongarch/include/asm/numa.h
Normal file
67
arch/loongarch/include/asm/numa.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Author: Jianmin Lv <lvjianmin@loongson.cn>
|
||||
* Huacai Chen <chenhuacai@loongson.cn>
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _ASM_LOONGARCH_NUMA_H
|
||||
#define _ASM_LOONGARCH_NUMA_H
|
||||
|
||||
#include <linux/nodemask.h>
|
||||
|
||||
#define NODE_ADDRSPACE_SHIFT 44
|
||||
|
||||
#define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
|
||||
#define nid_to_addrbase(nid) (_ULCAST_(nid) << NODE_ADDRSPACE_SHIFT)
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
|
||||
extern int numa_off;
|
||||
extern s16 __cpuid_to_node[CONFIG_NR_CPUS];
|
||||
extern nodemask_t numa_nodes_parsed __initdata;
|
||||
|
||||
struct numa_memblk {
|
||||
u64 start;
|
||||
u64 end;
|
||||
int nid;
|
||||
};
|
||||
|
||||
#define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
|
||||
struct numa_meminfo {
|
||||
int nr_blks;
|
||||
struct numa_memblk blk[NR_NODE_MEMBLKS];
|
||||
};
|
||||
|
||||
extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
|
||||
|
||||
extern void __init early_numa_add_cpu(int cpuid, s16 node);
|
||||
extern void numa_add_cpu(unsigned int cpu);
|
||||
extern void numa_remove_cpu(unsigned int cpu);
|
||||
|
||||
static inline void numa_clear_node(int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void set_cpuid_to_node(int cpuid, s16 node)
|
||||
{
|
||||
__cpuid_to_node[cpuid] = node;
|
||||
}
|
||||
|
||||
extern int early_cpu_to_node(int cpu);
|
||||
|
||||
#else
|
||||
|
||||
static inline void early_numa_add_cpu(int cpuid, s16 node) { }
|
||||
static inline void numa_add_cpu(unsigned int cpu) { }
|
||||
static inline void numa_remove_cpu(unsigned int cpu) { }
|
||||
|
||||
static inline int early_cpu_to_node(int cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NUMA */
|
||||
|
||||
#endif /* _ASM_LOONGARCH_NUMA_H */
|
115
arch/loongarch/include/asm/page.h
Normal file
115
arch/loongarch/include/asm/page.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_PAGE_H
|
||||
#define _ASM_PAGE_H
|
||||
|
||||
#include <linux/const.h>
|
||||
|
||||
/*
|
||||
* PAGE_SHIFT determines the page size
|
||||
*/
|
||||
#ifdef CONFIG_PAGE_SIZE_4KB
|
||||
#define PAGE_SHIFT 12
|
||||
#endif
|
||||
#ifdef CONFIG_PAGE_SIZE_16KB
|
||||
#define PAGE_SHIFT 14
|
||||
#endif
|
||||
#ifdef CONFIG_PAGE_SIZE_64KB
|
||||
#define PAGE_SHIFT 16
|
||||
#endif
|
||||
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||
|
||||
#define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
|
||||
#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pfn.h>
|
||||
|
||||
#define MAX_DMA32_PFN (1UL << (32 - PAGE_SHIFT))
|
||||
|
||||
/*
|
||||
* It's normally defined only for FLATMEM config but it's
|
||||
* used in our early mem init code for all memory models.
|
||||
* So always define it.
|
||||
*/
|
||||
#define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET)
|
||||
|
||||
extern void clear_page(void *page);
|
||||
extern void copy_page(void *to, void *from);
|
||||
|
||||
#define clear_user_page(page, vaddr, pg) clear_page(page)
|
||||
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
|
||||
|
||||
extern unsigned long shm_align_mask;
|
||||
|
||||
struct page;
|
||||
struct vm_area_struct;
|
||||
void copy_user_highpage(struct page *to, struct page *from,
|
||||
unsigned long vaddr, struct vm_area_struct *vma);
|
||||
|
||||
#define __HAVE_ARCH_COPY_USER_HIGHPAGE
|
||||
|
||||
typedef struct { unsigned long pte; } pte_t;
|
||||
#define pte_val(x) ((x).pte)
|
||||
#define __pte(x) ((pte_t) { (x) })
|
||||
typedef struct page *pgtable_t;
|
||||
|
||||
typedef struct { unsigned long pgd; } pgd_t;
|
||||
#define pgd_val(x) ((x).pgd)
|
||||
#define __pgd(x) ((pgd_t) { (x) })
|
||||
|
||||
/*
|
||||
* Manipulate page protection bits
|
||||
*/
|
||||
typedef struct { unsigned long pgprot; } pgprot_t;
|
||||
#define pgprot_val(x) ((x).pgprot)
|
||||
#define __pgprot(x) ((pgprot_t) { (x) })
|
||||
#define pte_pgprot(x) __pgprot(pte_val(x) & ~_PFN_MASK)
|
||||
|
||||
#define ptep_buddy(x) ((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
|
||||
|
||||
/*
|
||||
* __pa()/__va() should be used only during mem init.
|
||||
*/
|
||||
#define __pa(x) PHYSADDR(x)
|
||||
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
|
||||
|
||||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
|
||||
#ifdef CONFIG_FLATMEM
|
||||
|
||||
static inline int pfn_valid(unsigned long pfn)
|
||||
{
|
||||
/* avoid <linux/mm.h> include hell */
|
||||
extern unsigned long max_mapnr;
|
||||
unsigned long pfn_offset = ARCH_PFN_OFFSET;
|
||||
|
||||
return pfn >= pfn_offset && pfn < max_mapnr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define virt_to_pfn(kaddr) PFN_DOWN(virt_to_phys((void *)(kaddr)))
|
||||
#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
|
||||
|
||||
extern int __virt_addr_valid(volatile void *kaddr);
|
||||
#define virt_addr_valid(kaddr) __virt_addr_valid((volatile void *)(kaddr))
|
||||
|
||||
#define VM_DATA_DEFAULT_FLAGS \
|
||||
(VM_READ | VM_WRITE | \
|
||||
((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
|
||||
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
||||
|
||||
#include <asm-generic/memory_model.h>
|
||||
#include <asm-generic/getorder.h>
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_PAGE_H */
|
214
arch/loongarch/include/asm/percpu.h
Normal file
214
arch/loongarch/include/asm/percpu.h
Normal file
@ -0,0 +1,214 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_PERCPU_H
|
||||
#define __ASM_PERCPU_H
|
||||
|
||||
#include <asm/cmpxchg.h>
|
||||
|
||||
/* Use r21 for fast access */
|
||||
register unsigned long __my_cpu_offset __asm__("$r21");
|
||||
|
||||
static inline void set_my_cpu_offset(unsigned long off)
|
||||
{
|
||||
__my_cpu_offset = off;
|
||||
csr_write64(off, PERCPU_BASE_KS);
|
||||
}
|
||||
#define __my_cpu_offset __my_cpu_offset
|
||||
|
||||
#define PERCPU_OP(op, asm_op, c_op) \
|
||||
static inline unsigned long __percpu_##op(void *ptr, \
|
||||
unsigned long val, int size) \
|
||||
{ \
|
||||
unsigned long ret; \
|
||||
\
|
||||
switch (size) { \
|
||||
case 4: \
|
||||
__asm__ __volatile__( \
|
||||
"am"#asm_op".w" " %[ret], %[val], %[ptr] \n" \
|
||||
: [ret] "=&r" (ret), [ptr] "+ZB"(*(u32 *)ptr) \
|
||||
: [val] "r" (val)); \
|
||||
break; \
|
||||
case 8: \
|
||||
__asm__ __volatile__( \
|
||||
"am"#asm_op".d" " %[ret], %[val], %[ptr] \n" \
|
||||
: [ret] "=&r" (ret), [ptr] "+ZB"(*(u64 *)ptr) \
|
||||
: [val] "r" (val)); \
|
||||
break; \
|
||||
default: \
|
||||
ret = 0; \
|
||||
BUILD_BUG(); \
|
||||
} \
|
||||
\
|
||||
return ret c_op val; \
|
||||
}
|
||||
|
||||
PERCPU_OP(add, add, +)
|
||||
PERCPU_OP(and, and, &)
|
||||
PERCPU_OP(or, or, |)
|
||||
#undef PERCPU_OP
|
||||
|
||||
static inline unsigned long __percpu_read(void *ptr, int size)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
__asm__ __volatile__ ("ldx.b %[ret], $r21, %[ptr] \n"
|
||||
: [ret] "=&r"(ret)
|
||||
: [ptr] "r"(ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 2:
|
||||
__asm__ __volatile__ ("ldx.h %[ret], $r21, %[ptr] \n"
|
||||
: [ret] "=&r"(ret)
|
||||
: [ptr] "r"(ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 4:
|
||||
__asm__ __volatile__ ("ldx.w %[ret], $r21, %[ptr] \n"
|
||||
: [ret] "=&r"(ret)
|
||||
: [ptr] "r"(ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 8:
|
||||
__asm__ __volatile__ ("ldx.d %[ret], $r21, %[ptr] \n"
|
||||
: [ret] "=&r"(ret)
|
||||
: [ptr] "r"(ptr)
|
||||
: "memory");
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
BUILD_BUG();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void __percpu_write(void *ptr, unsigned long val, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
__asm__ __volatile__("stx.b %[val], $r21, %[ptr] \n"
|
||||
:
|
||||
: [val] "r" (val), [ptr] "r" (ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 2:
|
||||
__asm__ __volatile__("stx.h %[val], $r21, %[ptr] \n"
|
||||
:
|
||||
: [val] "r" (val), [ptr] "r" (ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 4:
|
||||
__asm__ __volatile__("stx.w %[val], $r21, %[ptr] \n"
|
||||
:
|
||||
: [val] "r" (val), [ptr] "r" (ptr)
|
||||
: "memory");
|
||||
break;
|
||||
case 8:
|
||||
__asm__ __volatile__("stx.d %[val], $r21, %[ptr] \n"
|
||||
:
|
||||
: [val] "r" (val), [ptr] "r" (ptr)
|
||||
: "memory");
|
||||
break;
|
||||
default:
|
||||
BUILD_BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
|
||||
int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 4:
|
||||
return __xchg_asm("amswap.w", (volatile u32 *)ptr, (u32)val);
|
||||
|
||||
case 8:
|
||||
return __xchg_asm("amswap.d", (volatile u64 *)ptr, (u64)val);
|
||||
|
||||
default:
|
||||
BUILD_BUG();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this_cpu_cmpxchg */
|
||||
#define _protect_cmpxchg_local(pcp, o, n) \
|
||||
({ \
|
||||
typeof(*raw_cpu_ptr(&(pcp))) __ret; \
|
||||
preempt_disable_notrace(); \
|
||||
__ret = cmpxchg_local(raw_cpu_ptr(&(pcp)), o, n); \
|
||||
preempt_enable_notrace(); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define _percpu_read(pcp) \
|
||||
({ \
|
||||
typeof(pcp) __retval; \
|
||||
__retval = (typeof(pcp))__percpu_read(&(pcp), sizeof(pcp)); \
|
||||
__retval; \
|
||||
})
|
||||
|
||||
#define _percpu_write(pcp, val) \
|
||||
do { \
|
||||
__percpu_write(&(pcp), (unsigned long)(val), sizeof(pcp)); \
|
||||
} while (0) \
|
||||
|
||||
#define _pcp_protect(operation, pcp, val) \
|
||||
({ \
|
||||
typeof(pcp) __retval; \
|
||||
preempt_disable_notrace(); \
|
||||
__retval = (typeof(pcp))operation(raw_cpu_ptr(&(pcp)), \
|
||||
(val), sizeof(pcp)); \
|
||||
preempt_enable_notrace(); \
|
||||
__retval; \
|
||||
})
|
||||
|
||||
#define _percpu_add(pcp, val) \
|
||||
_pcp_protect(__percpu_add, pcp, val)
|
||||
|
||||
#define _percpu_add_return(pcp, val) _percpu_add(pcp, val)
|
||||
|
||||
#define _percpu_and(pcp, val) \
|
||||
_pcp_protect(__percpu_and, pcp, val)
|
||||
|
||||
#define _percpu_or(pcp, val) \
|
||||
_pcp_protect(__percpu_or, pcp, val)
|
||||
|
||||
#define _percpu_xchg(pcp, val) ((typeof(pcp)) \
|
||||
_pcp_protect(__percpu_xchg, pcp, (unsigned long)(val)))
|
||||
|
||||
#define this_cpu_add_4(pcp, val) _percpu_add(pcp, val)
|
||||
#define this_cpu_add_8(pcp, val) _percpu_add(pcp, val)
|
||||
|
||||
#define this_cpu_add_return_4(pcp, val) _percpu_add_return(pcp, val)
|
||||
#define this_cpu_add_return_8(pcp, val) _percpu_add_return(pcp, val)
|
||||
|
||||
#define this_cpu_and_4(pcp, val) _percpu_and(pcp, val)
|
||||
#define this_cpu_and_8(pcp, val) _percpu_and(pcp, val)
|
||||
|
||||
#define this_cpu_or_4(pcp, val) _percpu_or(pcp, val)
|
||||
#define this_cpu_or_8(pcp, val) _percpu_or(pcp, val)
|
||||
|
||||
#define this_cpu_read_1(pcp) _percpu_read(pcp)
|
||||
#define this_cpu_read_2(pcp) _percpu_read(pcp)
|
||||
#define this_cpu_read_4(pcp) _percpu_read(pcp)
|
||||
#define this_cpu_read_8(pcp) _percpu_read(pcp)
|
||||
|
||||
#define this_cpu_write_1(pcp, val) _percpu_write(pcp, val)
|
||||
#define this_cpu_write_2(pcp, val) _percpu_write(pcp, val)
|
||||
#define this_cpu_write_4(pcp, val) _percpu_write(pcp, val)
|
||||
#define this_cpu_write_8(pcp, val) _percpu_write(pcp, val)
|
||||
|
||||
#define this_cpu_xchg_4(pcp, val) _percpu_xchg(pcp, val)
|
||||
#define this_cpu_xchg_8(pcp, val) _percpu_xchg(pcp, val)
|
||||
|
||||
#define this_cpu_cmpxchg_4(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
|
||||
#define this_cpu_cmpxchg_8(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
|
||||
|
||||
#include <asm-generic/percpu.h>
|
||||
|
||||
#endif /* __ASM_PERCPU_H */
|
10
arch/loongarch/include/asm/perf_event.h
Normal file
10
arch/loongarch/include/asm/perf_event.h
Normal file
@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Author: Huacai Chen <chenhuacai@loongson.cn>
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef __LOONGARCH_PERF_EVENT_H__
|
||||
#define __LOONGARCH_PERF_EVENT_H__
|
||||
/* Nothing to show here; the file is required by linux/perf_event.h. */
|
||||
#endif /* __LOONGARCH_PERF_EVENT_H__ */
|
103
arch/loongarch/include/asm/pgalloc.h
Normal file
103
arch/loongarch/include/asm/pgalloc.h
Normal file
@ -0,0 +1,103 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_PGALLOC_H
|
||||
#define _ASM_PGALLOC_H
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#define __HAVE_ARCH_PMD_ALLOC_ONE
|
||||
#define __HAVE_ARCH_PUD_ALLOC_ONE
|
||||
#include <asm-generic/pgalloc.h>
|
||||
|
||||
static inline void pmd_populate_kernel(struct mm_struct *mm,
|
||||
pmd_t *pmd, pte_t *pte)
|
||||
{
|
||||
set_pmd(pmd, __pmd((unsigned long)pte));
|
||||
}
|
||||
|
||||
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t pte)
|
||||
{
|
||||
set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
|
||||
}
|
||||
|
||||
#ifndef __PAGETABLE_PMD_FOLDED
|
||||
|
||||
static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
|
||||
{
|
||||
set_pud(pud, __pud((unsigned long)pmd));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __PAGETABLE_PUD_FOLDED
|
||||
|
||||
static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
|
||||
{
|
||||
set_p4d(p4d, __p4d((unsigned long)pud));
|
||||
}
|
||||
|
||||
#endif /* __PAGETABLE_PUD_FOLDED */
|
||||
|
||||
extern void pagetable_init(void);
|
||||
|
||||
/*
|
||||
* Initialize a new pmd table with invalid pointers.
|
||||
*/
|
||||
extern void pmd_init(unsigned long page, unsigned long pagetable);
|
||||
|
||||
/*
|
||||
* Initialize a new pgd / pmd table with invalid pointers.
|
||||
*/
|
||||
extern void pgd_init(unsigned long page);
|
||||
extern pgd_t *pgd_alloc(struct mm_struct *mm);
|
||||
|
||||
#define __pte_free_tlb(tlb, pte, address) \
|
||||
do { \
|
||||
pgtable_pte_page_dtor(pte); \
|
||||
tlb_remove_page((tlb), pte); \
|
||||
} while (0)
|
||||
|
||||
#ifndef __PAGETABLE_PMD_FOLDED
|
||||
|
||||
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
struct page *pg;
|
||||
|
||||
pg = alloc_pages(GFP_KERNEL_ACCOUNT, PMD_ORDER);
|
||||
if (!pg)
|
||||
return NULL;
|
||||
|
||||
if (!pgtable_pmd_page_ctor(pg)) {
|
||||
__free_pages(pg, PMD_ORDER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pmd = (pmd_t *)page_address(pg);
|
||||
pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
|
||||
return pmd;
|
||||
}
|
||||
|
||||
#define __pmd_free_tlb(tlb, x, addr) pmd_free((tlb)->mm, x)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __PAGETABLE_PUD_FOLDED
|
||||
|
||||
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
|
||||
{
|
||||
pud_t *pud;
|
||||
|
||||
pud = (pud_t *) __get_free_pages(GFP_KERNEL, PUD_ORDER);
|
||||
if (pud)
|
||||
pud_init((unsigned long)pud, (unsigned long)invalid_pmd_table);
|
||||
return pud;
|
||||
}
|
||||
|
||||
#define __pud_free_tlb(tlb, x, addr) pud_free((tlb)->mm, x)
|
||||
|
||||
#endif /* __PAGETABLE_PUD_FOLDED */
|
||||
|
||||
#endif /* _ASM_PGALLOC_H */
|
131
arch/loongarch/include/asm/pgtable-bits.h
Normal file
131
arch/loongarch/include/asm/pgtable-bits.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_PGTABLE_BITS_H
|
||||
#define _ASM_PGTABLE_BITS_H
|
||||
|
||||
/* Page table bits */
|
||||
#define _PAGE_VALID_SHIFT 0
|
||||
#define _PAGE_ACCESSED_SHIFT 0 /* Reuse Valid for Accessed */
|
||||
#define _PAGE_DIRTY_SHIFT 1
|
||||
#define _PAGE_PLV_SHIFT 2 /* 2~3, two bits */
|
||||
#define _CACHE_SHIFT 4 /* 4~5, two bits */
|
||||
#define _PAGE_GLOBAL_SHIFT 6
|
||||
#define _PAGE_HUGE_SHIFT 6 /* HUGE is a PMD bit */
|
||||
#define _PAGE_PRESENT_SHIFT 7
|
||||
#define _PAGE_WRITE_SHIFT 8
|
||||
#define _PAGE_MODIFIED_SHIFT 9
|
||||
#define _PAGE_PROTNONE_SHIFT 10
|
||||
#define _PAGE_SPECIAL_SHIFT 11
|
||||
#define _PAGE_HGLOBAL_SHIFT 12 /* HGlobal is a PMD bit */
|
||||
#define _PAGE_PFN_SHIFT 12
|
||||
#define _PAGE_PFN_END_SHIFT 48
|
||||
#define _PAGE_NO_READ_SHIFT 61
|
||||
#define _PAGE_NO_EXEC_SHIFT 62
|
||||
#define _PAGE_RPLV_SHIFT 63
|
||||
|
||||
/* Used by software */
|
||||
#define _PAGE_PRESENT (_ULCAST_(1) << _PAGE_PRESENT_SHIFT)
|
||||
#define _PAGE_WRITE (_ULCAST_(1) << _PAGE_WRITE_SHIFT)
|
||||
#define _PAGE_ACCESSED (_ULCAST_(1) << _PAGE_ACCESSED_SHIFT)
|
||||
#define _PAGE_MODIFIED (_ULCAST_(1) << _PAGE_MODIFIED_SHIFT)
|
||||
#define _PAGE_PROTNONE (_ULCAST_(1) << _PAGE_PROTNONE_SHIFT)
|
||||
#define _PAGE_SPECIAL (_ULCAST_(1) << _PAGE_SPECIAL_SHIFT)
|
||||
|
||||
/* Used by TLB hardware (placed in EntryLo*) */
|
||||
#define _PAGE_VALID (_ULCAST_(1) << _PAGE_VALID_SHIFT)
|
||||
#define _PAGE_DIRTY (_ULCAST_(1) << _PAGE_DIRTY_SHIFT)
|
||||
#define _PAGE_PLV (_ULCAST_(3) << _PAGE_PLV_SHIFT)
|
||||
#define _PAGE_GLOBAL (_ULCAST_(1) << _PAGE_GLOBAL_SHIFT)
|
||||
#define _PAGE_HUGE (_ULCAST_(1) << _PAGE_HUGE_SHIFT)
|
||||
#define _PAGE_HGLOBAL (_ULCAST_(1) << _PAGE_HGLOBAL_SHIFT)
|
||||
#define _PAGE_NO_READ (_ULCAST_(1) << _PAGE_NO_READ_SHIFT)
|
||||
#define _PAGE_NO_EXEC (_ULCAST_(1) << _PAGE_NO_EXEC_SHIFT)
|
||||
#define _PAGE_RPLV (_ULCAST_(1) << _PAGE_RPLV_SHIFT)
|
||||
#define _CACHE_MASK (_ULCAST_(3) << _CACHE_SHIFT)
|
||||
#define _PFN_SHIFT (PAGE_SHIFT - 12 + _PAGE_PFN_SHIFT)
|
||||
|
||||
#define _PAGE_USER (PLV_USER << _PAGE_PLV_SHIFT)
|
||||
#define _PAGE_KERN (PLV_KERN << _PAGE_PLV_SHIFT)
|
||||
|
||||
#define _PFN_MASK (~((_ULCAST_(1) << (_PFN_SHIFT)) - 1) & \
|
||||
((_ULCAST_(1) << (_PAGE_PFN_END_SHIFT)) - 1))
|
||||
|
||||
/*
|
||||
* Cache attributes
|
||||
*/
|
||||
#ifndef _CACHE_SUC
|
||||
#define _CACHE_SUC (0<<_CACHE_SHIFT) /* Strong-ordered UnCached */
|
||||
#endif
|
||||
#ifndef _CACHE_CC
|
||||
#define _CACHE_CC (1<<_CACHE_SHIFT) /* Coherent Cached */
|
||||
#endif
|
||||
#ifndef _CACHE_WUC
|
||||
#define _CACHE_WUC (2<<_CACHE_SHIFT) /* Weak-ordered UnCached */
|
||||
#endif
|
||||
|
||||
#define __READABLE (_PAGE_VALID)
|
||||
#define __WRITEABLE (_PAGE_DIRTY | _PAGE_WRITE)
|
||||
|
||||
#define _PAGE_CHG_MASK (_PAGE_MODIFIED | _PAGE_SPECIAL | _PFN_MASK | _CACHE_MASK | _PAGE_PLV)
|
||||
#define _HPAGE_CHG_MASK (_PAGE_MODIFIED | _PAGE_SPECIAL | _PFN_MASK | _CACHE_MASK | _PAGE_PLV | _PAGE_HUGE)
|
||||
|
||||
#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_NO_READ | \
|
||||
_PAGE_USER | _CACHE_CC)
|
||||
#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_WRITE | \
|
||||
_PAGE_USER | _CACHE_CC)
|
||||
#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _CACHE_CC)
|
||||
|
||||
#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
|
||||
_PAGE_GLOBAL | _PAGE_KERN | _CACHE_CC)
|
||||
#define PAGE_KERNEL_SUC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
|
||||
_PAGE_GLOBAL | _PAGE_KERN | _CACHE_SUC)
|
||||
#define PAGE_KERNEL_WUC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
|
||||
_PAGE_GLOBAL | _PAGE_KERN | _CACHE_WUC)
|
||||
|
||||
#define __P000 __pgprot(_CACHE_CC | _PAGE_USER | _PAGE_PROTNONE | _PAGE_NO_EXEC | _PAGE_NO_READ)
|
||||
#define __P001 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT | _PAGE_NO_EXEC)
|
||||
#define __P010 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT | _PAGE_NO_EXEC)
|
||||
#define __P011 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT | _PAGE_NO_EXEC)
|
||||
#define __P100 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT)
|
||||
#define __P101 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT)
|
||||
#define __P110 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT)
|
||||
#define __P111 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT)
|
||||
|
||||
#define __S000 __pgprot(_CACHE_CC | _PAGE_USER | _PAGE_PROTNONE | _PAGE_NO_EXEC | _PAGE_NO_READ)
|
||||
#define __S001 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT | _PAGE_NO_EXEC)
|
||||
#define __S010 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE)
|
||||
#define __S011 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE)
|
||||
#define __S100 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT)
|
||||
#define __S101 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT)
|
||||
#define __S110 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT | _PAGE_WRITE)
|
||||
#define __S111 __pgprot(_CACHE_CC | _PAGE_VALID | _PAGE_USER | _PAGE_PRESENT | _PAGE_WRITE)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#define pgprot_noncached pgprot_noncached
|
||||
|
||||
static inline pgprot_t pgprot_noncached(pgprot_t _prot)
|
||||
{
|
||||
unsigned long prot = pgprot_val(_prot);
|
||||
|
||||
prot = (prot & ~_CACHE_MASK) | _CACHE_SUC;
|
||||
|
||||
return __pgprot(prot);
|
||||
}
|
||||
|
||||
#define pgprot_writecombine pgprot_writecombine
|
||||
|
||||
static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
|
||||
{
|
||||
unsigned long prot = pgprot_val(_prot);
|
||||
|
||||
prot = (prot & ~_CACHE_MASK) | _CACHE_WUC;
|
||||
|
||||
return __pgprot(prot);
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_PGTABLE_BITS_H */
|
565
arch/loongarch/include/asm/pgtable.h
Normal file
565
arch/loongarch/include/asm/pgtable.h
Normal file
@ -0,0 +1,565 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*
|
||||
* Derived from MIPS:
|
||||
* Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 2003 Ralf Baechle
|
||||
* Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc.
|
||||
*/
|
||||
#ifndef _ASM_PGTABLE_H
|
||||
#define _ASM_PGTABLE_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/pgtable-bits.h>
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS == 2
|
||||
#include <asm-generic/pgtable-nopmd.h>
|
||||
#elif CONFIG_PGTABLE_LEVELS == 3
|
||||
#include <asm-generic/pgtable-nopud.h>
|
||||
#else
|
||||
#include <asm-generic/pgtable-nop4d.h>
|
||||
#endif
|
||||
|
||||
#define PGD_ORDER 0
|
||||
#define PUD_ORDER 0
|
||||
#define PMD_ORDER 0
|
||||
#define PTE_ORDER 0
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS == 2
|
||||
#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT + PTE_ORDER - 3))
|
||||
#elif CONFIG_PGTABLE_LEVELS == 3
|
||||
#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT + PTE_ORDER - 3))
|
||||
#define PMD_SIZE (1UL << PMD_SHIFT)
|
||||
#define PMD_MASK (~(PMD_SIZE-1))
|
||||
#define PGDIR_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3))
|
||||
#elif CONFIG_PGTABLE_LEVELS == 4
|
||||
#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT + PTE_ORDER - 3))
|
||||
#define PMD_SIZE (1UL << PMD_SHIFT)
|
||||
#define PMD_MASK (~(PMD_SIZE-1))
|
||||
#define PUD_SHIFT (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3))
|
||||
#define PUD_SIZE (1UL << PUD_SHIFT)
|
||||
#define PUD_MASK (~(PUD_SIZE-1))
|
||||
#define PGDIR_SHIFT (PUD_SHIFT + (PAGE_SHIFT + PUD_ORDER - 3))
|
||||
#endif
|
||||
|
||||
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
|
||||
#define PGDIR_MASK (~(PGDIR_SIZE-1))
|
||||
|
||||
#define VA_BITS (PGDIR_SHIFT + (PAGE_SHIFT + PGD_ORDER - 3))
|
||||
|
||||
#define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) >> 3)
|
||||
#if CONFIG_PGTABLE_LEVELS > 3
|
||||
#define PTRS_PER_PUD ((PAGE_SIZE << PUD_ORDER) >> 3)
|
||||
#endif
|
||||
#if CONFIG_PGTABLE_LEVELS > 2
|
||||
#define PTRS_PER_PMD ((PAGE_SIZE << PMD_ORDER) >> 3)
|
||||
#endif
|
||||
#define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) >> 3)
|
||||
|
||||
#define USER_PTRS_PER_PGD ((TASK_SIZE64 / PGDIR_SIZE)?(TASK_SIZE64 / PGDIR_SIZE):1)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/mmzone.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
struct mm_struct;
|
||||
struct vm_area_struct;
|
||||
|
||||
/*
|
||||
* ZERO_PAGE is a global shared page that is always zero; used
|
||||
* for zero-mapped memory areas etc..
|
||||
*/
|
||||
|
||||
extern unsigned long empty_zero_page;
|
||||
extern unsigned long zero_page_mask;
|
||||
|
||||
#define ZERO_PAGE(vaddr) \
|
||||
(virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))))
|
||||
#define __HAVE_COLOR_ZERO_PAGE
|
||||
|
||||
/*
|
||||
* TLB refill handlers may also map the vmalloc area into xkvrange.
|
||||
* Avoid the first couple of pages so NULL pointer dereferences will
|
||||
* still reliably trap.
|
||||
*/
|
||||
#define MODULES_VADDR (vm_map_base + PCI_IOSIZE + (2 * PAGE_SIZE))
|
||||
#define MODULES_END (MODULES_VADDR + SZ_256M)
|
||||
|
||||
#define VMALLOC_START MODULES_END
|
||||
#define VMALLOC_END \
|
||||
(vm_map_base + \
|
||||
min(PTRS_PER_PGD * PTRS_PER_PUD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, (1UL << cpu_vabits)) - PMD_SIZE)
|
||||
|
||||
#define pte_ERROR(e) \
|
||||
pr_err("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
|
||||
#ifndef __PAGETABLE_PMD_FOLDED
|
||||
#define pmd_ERROR(e) \
|
||||
pr_err("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
|
||||
#endif
|
||||
#ifndef __PAGETABLE_PUD_FOLDED
|
||||
#define pud_ERROR(e) \
|
||||
pr_err("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_val(e))
|
||||
#endif
|
||||
#define pgd_ERROR(e) \
|
||||
pr_err("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
|
||||
|
||||
extern pte_t invalid_pte_table[PTRS_PER_PTE];
|
||||
|
||||
#ifndef __PAGETABLE_PUD_FOLDED
|
||||
|
||||
typedef struct { unsigned long pud; } pud_t;
|
||||
#define pud_val(x) ((x).pud)
|
||||
#define __pud(x) ((pud_t) { (x) })
|
||||
|
||||
extern pud_t invalid_pud_table[PTRS_PER_PUD];
|
||||
|
||||
/*
|
||||
* Empty pgd/p4d entries point to the invalid_pud_table.
|
||||
*/
|
||||
static inline int p4d_none(p4d_t p4d)
|
||||
{
|
||||
return p4d_val(p4d) == (unsigned long)invalid_pud_table;
|
||||
}
|
||||
|
||||
static inline int p4d_bad(p4d_t p4d)
|
||||
{
|
||||
return p4d_val(p4d) & ~PAGE_MASK;
|
||||
}
|
||||
|
||||
static inline int p4d_present(p4d_t p4d)
|
||||
{
|
||||
return p4d_val(p4d) != (unsigned long)invalid_pud_table;
|
||||
}
|
||||
|
||||
static inline void p4d_clear(p4d_t *p4dp)
|
||||
{
|
||||
p4d_val(*p4dp) = (unsigned long)invalid_pud_table;
|
||||
}
|
||||
|
||||
static inline pud_t *p4d_pgtable(p4d_t p4d)
|
||||
{
|
||||
return (pud_t *)p4d_val(p4d);
|
||||
}
|
||||
|
||||
static inline void set_p4d(p4d_t *p4d, p4d_t p4dval)
|
||||
{
|
||||
*p4d = p4dval;
|
||||
}
|
||||
|
||||
#define p4d_phys(p4d) virt_to_phys((void *)p4d_val(p4d))
|
||||
#define p4d_page(p4d) (pfn_to_page(p4d_phys(p4d) >> PAGE_SHIFT))
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __PAGETABLE_PMD_FOLDED
|
||||
|
||||
typedef struct { unsigned long pmd; } pmd_t;
|
||||
#define pmd_val(x) ((x).pmd)
|
||||
#define __pmd(x) ((pmd_t) { (x) })
|
||||
|
||||
extern pmd_t invalid_pmd_table[PTRS_PER_PMD];
|
||||
|
||||
/*
|
||||
* Empty pud entries point to the invalid_pmd_table.
|
||||
*/
|
||||
static inline int pud_none(pud_t pud)
|
||||
{
|
||||
return pud_val(pud) == (unsigned long)invalid_pmd_table;
|
||||
}
|
||||
|
||||
static inline int pud_bad(pud_t pud)
|
||||
{
|
||||
return pud_val(pud) & ~PAGE_MASK;
|
||||
}
|
||||
|
||||
static inline int pud_present(pud_t pud)
|
||||
{
|
||||
return pud_val(pud) != (unsigned long)invalid_pmd_table;
|
||||
}
|
||||
|
||||
static inline void pud_clear(pud_t *pudp)
|
||||
{
|
||||
pud_val(*pudp) = ((unsigned long)invalid_pmd_table);
|
||||
}
|
||||
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return (pmd_t *)pud_val(pud);
|
||||
}
|
||||
|
||||
#define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while (0)
|
||||
|
||||
#define pud_phys(pud) virt_to_phys((void *)pud_val(pud))
|
||||
#define pud_page(pud) (pfn_to_page(pud_phys(pud) >> PAGE_SHIFT))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Empty pmd entries point to the invalid_pte_table.
|
||||
*/
|
||||
static inline int pmd_none(pmd_t pmd)
|
||||
{
|
||||
return pmd_val(pmd) == (unsigned long)invalid_pte_table;
|
||||
}
|
||||
|
||||
static inline int pmd_bad(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & ~PAGE_MASK);
|
||||
}
|
||||
|
||||
static inline int pmd_present(pmd_t pmd)
|
||||
{
|
||||
if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
|
||||
return !!(pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE));
|
||||
|
||||
return pmd_val(pmd) != (unsigned long)invalid_pte_table;
|
||||
}
|
||||
|
||||
static inline void pmd_clear(pmd_t *pmdp)
|
||||
{
|
||||
pmd_val(*pmdp) = ((unsigned long)invalid_pte_table);
|
||||
}
|
||||
|
||||
#define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while (0)
|
||||
|
||||
#define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd))
|
||||
|
||||
#ifndef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
#define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
#define pmd_page_vaddr(pmd) pmd_val(pmd)
|
||||
|
||||
extern pmd_t mk_pmd(struct page *page, pgprot_t prot);
|
||||
extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pmd_t pmd);
|
||||
|
||||
#define pte_page(x) pfn_to_page(pte_pfn(x))
|
||||
#define pte_pfn(x) ((unsigned long)(((x).pte & _PFN_MASK) >> _PFN_SHIFT))
|
||||
#define pfn_pte(pfn, prot) __pte(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
|
||||
#define pfn_pmd(pfn, prot) __pmd(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
|
||||
|
||||
/*
|
||||
* Initialize a new pgd / pmd table with invalid pointers.
|
||||
*/
|
||||
extern void pgd_init(unsigned long page);
|
||||
extern void pud_init(unsigned long page, unsigned long pagetable);
|
||||
extern void pmd_init(unsigned long page, unsigned long pagetable);
|
||||
|
||||
/*
|
||||
* Non-present pages: high 40 bits are offset, next 8 bits type,
|
||||
* low 16 bits zero.
|
||||
*/
|
||||
static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
|
||||
{ pte_t pte; pte_val(pte) = (type << 16) | (offset << 24); return pte; }
|
||||
|
||||
#define __swp_type(x) (((x).val >> 16) & 0xff)
|
||||
#define __swp_offset(x) ((x).val >> 24)
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type), (offset))) })
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
#define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val(pmd) })
|
||||
#define __swp_entry_to_pmd(x) ((pmd_t) { (x).val | _PAGE_HUGE })
|
||||
|
||||
extern void paging_init(void);
|
||||
|
||||
#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL))
|
||||
#define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE))
|
||||
#define pte_no_exec(pte) (pte_val(pte) & _PAGE_NO_EXEC)
|
||||
|
||||
static inline void set_pte(pte_t *ptep, pte_t pteval)
|
||||
{
|
||||
*ptep = pteval;
|
||||
if (pte_val(pteval) & _PAGE_GLOBAL) {
|
||||
pte_t *buddy = ptep_buddy(ptep);
|
||||
/*
|
||||
* Make sure the buddy is global too (if it's !none,
|
||||
* it better already be global)
|
||||
*/
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* For SMP, multiple CPUs can race, so we need to do
|
||||
* this atomically.
|
||||
*/
|
||||
unsigned long page_global = _PAGE_GLOBAL;
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"1:" __LL "%[tmp], %[buddy] \n"
|
||||
" bnez %[tmp], 2f \n"
|
||||
" or %[tmp], %[tmp], %[global] \n"
|
||||
__SC "%[tmp], %[buddy] \n"
|
||||
" beqz %[tmp], 1b \n"
|
||||
" nop \n"
|
||||
"2: \n"
|
||||
__WEAK_LLSC_MB
|
||||
: [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
|
||||
: [global] "r" (page_global));
|
||||
#else /* !CONFIG_SMP */
|
||||
if (pte_none(*buddy))
|
||||
pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL;
|
||||
#endif /* CONFIG_SMP */
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pteval)
|
||||
{
|
||||
set_pte(ptep, pteval);
|
||||
}
|
||||
|
||||
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
/* Preserve global status for the pair */
|
||||
if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
|
||||
set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL));
|
||||
else
|
||||
set_pte_at(mm, addr, ptep, __pte(0));
|
||||
}
|
||||
|
||||
#define PGD_T_LOG2 (__builtin_ffs(sizeof(pgd_t)) - 1)
|
||||
#define PMD_T_LOG2 (__builtin_ffs(sizeof(pmd_t)) - 1)
|
||||
#define PTE_T_LOG2 (__builtin_ffs(sizeof(pte_t)) - 1)
|
||||
|
||||
extern pgd_t swapper_pg_dir[];
|
||||
extern pgd_t invalid_pg_dir[];
|
||||
|
||||
/*
|
||||
* The following only work if pte_present() is true.
|
||||
* Undefined behaviour if not..
|
||||
*/
|
||||
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 pte_t pte_mkold(pte_t pte)
|
||||
{
|
||||
pte_val(pte) &= ~_PAGE_ACCESSED;
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkyoung(pte_t pte)
|
||||
{
|
||||
pte_val(pte) |= _PAGE_ACCESSED;
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkclean(pte_t pte)
|
||||
{
|
||||
pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_MODIFIED);
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkdirty(pte_t pte)
|
||||
{
|
||||
pte_val(pte) |= (_PAGE_DIRTY | _PAGE_MODIFIED);
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkwrite(pte_t pte)
|
||||
{
|
||||
pte_val(pte) |= (_PAGE_WRITE | _PAGE_DIRTY);
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_wrprotect(pte_t pte)
|
||||
{
|
||||
pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE; }
|
||||
|
||||
static inline pte_t pte_mkhuge(pte_t pte)
|
||||
{
|
||||
pte_val(pte) |= _PAGE_HUGE;
|
||||
return pte;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_HAS_PTE_SPECIAL)
|
||||
static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
|
||||
static inline pte_t pte_mkspecial(pte_t pte) { pte_val(pte) |= _PAGE_SPECIAL; return pte; }
|
||||
#endif /* CONFIG_ARCH_HAS_PTE_SPECIAL */
|
||||
|
||||
#define pte_accessible pte_accessible
|
||||
static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
|
||||
{
|
||||
if (pte_val(a) & _PAGE_PRESENT)
|
||||
return true;
|
||||
|
||||
if ((pte_val(a) & _PAGE_PROTNONE) &&
|
||||
atomic_read(&mm->tlb_flush_pending))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Conversion functions: convert a page and protection to a page entry,
|
||||
* and a page entry and page directory to the page they refer to.
|
||||
*/
|
||||
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
|
||||
|
||||
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
{
|
||||
return __pte((pte_val(pte) & _PAGE_CHG_MASK) |
|
||||
(pgprot_val(newprot) & ~_PAGE_CHG_MASK));
|
||||
}
|
||||
|
||||
extern void __update_tlb(struct vm_area_struct *vma,
|
||||
unsigned long address, pte_t *ptep);
|
||||
|
||||
static inline void update_mmu_cache(struct vm_area_struct *vma,
|
||||
unsigned long address, pte_t *ptep)
|
||||
{
|
||||
__update_tlb(vma, address, ptep);
|
||||
}
|
||||
|
||||
static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
|
||||
unsigned long address, pmd_t *pmdp)
|
||||
{
|
||||
__update_tlb(vma, address, (pte_t *)pmdp);
|
||||
}
|
||||
|
||||
#define kern_addr_valid(addr) (1)
|
||||
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
|
||||
/* We don't have hardware dirty/accessed bits, generic_pmdp_establish is fine.*/
|
||||
#define pmdp_establish generic_pmdp_establish
|
||||
|
||||
static inline int pmd_trans_huge(pmd_t pmd)
|
||||
{
|
||||
return !!(pmd_val(pmd) & _PAGE_HUGE) && pmd_present(pmd);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkhuge(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) = (pmd_val(pmd) & ~(_PAGE_GLOBAL)) |
|
||||
((pmd_val(pmd) & _PAGE_GLOBAL) << (_PAGE_HGLOBAL_SHIFT - _PAGE_GLOBAL_SHIFT));
|
||||
pmd_val(pmd) |= _PAGE_HUGE;
|
||||
|
||||
return pmd;
|
||||
}
|
||||
|
||||
#define pmd_write pmd_write
|
||||
static inline int pmd_write(pmd_t pmd)
|
||||
{
|
||||
return !!(pmd_val(pmd) & _PAGE_WRITE);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkwrite(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) |= (_PAGE_WRITE | _PAGE_DIRTY);
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_wrprotect(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline int pmd_dirty(pmd_t pmd)
|
||||
{
|
||||
return !!(pmd_val(pmd) & _PAGE_MODIFIED);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkclean(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) &= ~(_PAGE_DIRTY | _PAGE_MODIFIED);
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkdirty(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) |= (_PAGE_DIRTY | _PAGE_MODIFIED);
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline int pmd_young(pmd_t pmd)
|
||||
{
|
||||
return !!(pmd_val(pmd) & _PAGE_ACCESSED);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkold(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) &= ~_PAGE_ACCESSED;
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkyoung(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) |= _PAGE_ACCESSED;
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline unsigned long pmd_pfn(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & _PFN_MASK) >> _PFN_SHIFT;
|
||||
}
|
||||
|
||||
static inline struct page *pmd_page(pmd_t pmd)
|
||||
{
|
||||
if (pmd_trans_huge(pmd))
|
||||
return pfn_to_page(pmd_pfn(pmd));
|
||||
|
||||
return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
||||
{
|
||||
pmd_val(pmd) = (pmd_val(pmd) & _HPAGE_CHG_MASK) |
|
||||
(pgprot_val(newprot) & ~_HPAGE_CHG_MASK);
|
||||
return pmd;
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkinvalid(pmd_t pmd)
|
||||
{
|
||||
pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY | _PAGE_PROTNONE);
|
||||
|
||||
return pmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* The generic version pmdp_huge_get_and_clear uses a version of pmd_clear() with a
|
||||
* different prototype.
|
||||
*/
|
||||
#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
|
||||
static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
|
||||
unsigned long address, pmd_t *pmdp)
|
||||
{
|
||||
pmd_t old = *pmdp;
|
||||
|
||||
pmd_clear(pmdp);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
static inline long pte_protnone(pte_t pte)
|
||||
{
|
||||
return (pte_val(pte) & _PAGE_PROTNONE);
|
||||
}
|
||||
|
||||
static inline long pmd_protnone(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & _PAGE_PROTNONE);
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
|
||||
/*
|
||||
* We provide our own get_unmapped area to cope with the virtual aliasing
|
||||
* constraints placed on us by the cache architecture.
|
||||
*/
|
||||
#define HAVE_ARCH_UNMAPPED_AREA
|
||||
#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_PGTABLE_H */
|
29
arch/loongarch/include/asm/prefetch.h
Normal file
29
arch/loongarch/include/asm/prefetch.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_PREFETCH_H
|
||||
#define __ASM_PREFETCH_H
|
||||
|
||||
#define Pref_Load 0
|
||||
#define Pref_Store 8
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
.macro __pref hint addr
|
||||
#ifdef CONFIG_CPU_HAS_PREFETCH
|
||||
preld \hint, \addr, 0
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro pref_load addr
|
||||
__pref Pref_Load, \addr
|
||||
.endm
|
||||
|
||||
.macro pref_store addr
|
||||
__pref Pref_Store, \addr
|
||||
.endm
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_PREFETCH_H */
|
209
arch/loongarch/include/asm/processor.h
Normal file
209
arch/loongarch/include/asm/processor.h
Normal file
@ -0,0 +1,209 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_PROCESSOR_H
|
||||
#define _ASM_PROCESSOR_H
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpu-info.h>
|
||||
#include <asm/loongarch.h>
|
||||
#include <asm/vdso/processor.h>
|
||||
#include <uapi/asm/ptrace.h>
|
||||
#include <uapi/asm/sigcontext.h>
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
|
||||
#define TASK_SIZE 0x80000000UL
|
||||
#define TASK_SIZE_MIN TASK_SIZE
|
||||
#define STACK_TOP_MAX TASK_SIZE
|
||||
|
||||
#define TASK_IS_32BIT_ADDR 1
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
#define TASK_SIZE32 0x100000000UL
|
||||
#define TASK_SIZE64 (0x1UL << ((cpu_vabits > VA_BITS) ? VA_BITS : cpu_vabits))
|
||||
|
||||
#define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
|
||||
#define TASK_SIZE_MIN TASK_SIZE32
|
||||
#define STACK_TOP_MAX TASK_SIZE64
|
||||
|
||||
#define TASK_SIZE_OF(tsk) \
|
||||
(test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
|
||||
|
||||
#define TASK_IS_32BIT_ADDR test_thread_flag(TIF_32BIT_ADDR)
|
||||
|
||||
#endif
|
||||
|
||||
#define VDSO_RANDOMIZE_SIZE (TASK_IS_32BIT_ADDR ? SZ_1M : SZ_64M)
|
||||
|
||||
unsigned long stack_top(void);
|
||||
#define STACK_TOP stack_top()
|
||||
|
||||
/*
|
||||
* This decides where the kernel will search for a free chunk of vm
|
||||
* space during mmap's.
|
||||
*/
|
||||
#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3)
|
||||
|
||||
#define FPU_REG_WIDTH 256
|
||||
#define FPU_ALIGN __attribute__((aligned(32)))
|
||||
|
||||
union fpureg {
|
||||
__u32 val32[FPU_REG_WIDTH / 32];
|
||||
__u64 val64[FPU_REG_WIDTH / 64];
|
||||
};
|
||||
|
||||
#define FPR_IDX(width, idx) (idx)
|
||||
|
||||
#define BUILD_FPR_ACCESS(width) \
|
||||
static inline u##width get_fpr##width(union fpureg *fpr, unsigned idx) \
|
||||
{ \
|
||||
return fpr->val##width[FPR_IDX(width, idx)]; \
|
||||
} \
|
||||
\
|
||||
static inline void set_fpr##width(union fpureg *fpr, unsigned int idx, \
|
||||
u##width val) \
|
||||
{ \
|
||||
fpr->val##width[FPR_IDX(width, idx)] = val; \
|
||||
}
|
||||
|
||||
BUILD_FPR_ACCESS(32)
|
||||
BUILD_FPR_ACCESS(64)
|
||||
|
||||
struct loongarch_fpu {
|
||||
unsigned int fcsr;
|
||||
unsigned int vcsr;
|
||||
uint64_t fcc; /* 8x8 */
|
||||
union fpureg fpr[NUM_FPU_REGS];
|
||||
};
|
||||
|
||||
#define INIT_CPUMASK { \
|
||||
{0,} \
|
||||
}
|
||||
|
||||
#define ARCH_MIN_TASKALIGN 32
|
||||
|
||||
struct loongarch_vdso_info;
|
||||
|
||||
/*
|
||||
* If you change thread_struct remember to change the #defines below too!
|
||||
*/
|
||||
struct thread_struct {
|
||||
/* Main processor registers. */
|
||||
unsigned long reg01, reg03, reg22; /* ra sp fp */
|
||||
unsigned long reg23, reg24, reg25, reg26; /* s0-s3 */
|
||||
unsigned long reg27, reg28, reg29, reg30, reg31; /* s4-s8 */
|
||||
|
||||
/* CSR registers */
|
||||
unsigned long csr_prmd;
|
||||
unsigned long csr_crmd;
|
||||
unsigned long csr_euen;
|
||||
unsigned long csr_ecfg;
|
||||
unsigned long csr_badvaddr; /* Last user fault */
|
||||
|
||||
/* Scratch registers */
|
||||
unsigned long scr0;
|
||||
unsigned long scr1;
|
||||
unsigned long scr2;
|
||||
unsigned long scr3;
|
||||
|
||||
/* Eflags register */
|
||||
unsigned long eflags;
|
||||
|
||||
/* Other stuff associated with the thread. */
|
||||
unsigned long trap_nr;
|
||||
unsigned long error_code;
|
||||
struct loongarch_vdso_info *vdso;
|
||||
|
||||
/*
|
||||
* FPU & vector registers, must be at last because
|
||||
* they are conditionally copied at fork().
|
||||
*/
|
||||
struct loongarch_fpu fpu FPU_ALIGN;
|
||||
};
|
||||
|
||||
#define INIT_THREAD { \
|
||||
/* \
|
||||
* Main processor registers \
|
||||
*/ \
|
||||
.reg01 = 0, \
|
||||
.reg03 = 0, \
|
||||
.reg22 = 0, \
|
||||
.reg23 = 0, \
|
||||
.reg24 = 0, \
|
||||
.reg25 = 0, \
|
||||
.reg26 = 0, \
|
||||
.reg27 = 0, \
|
||||
.reg28 = 0, \
|
||||
.reg29 = 0, \
|
||||
.reg30 = 0, \
|
||||
.reg31 = 0, \
|
||||
.csr_crmd = 0, \
|
||||
.csr_prmd = 0, \
|
||||
.csr_euen = 0, \
|
||||
.csr_ecfg = 0, \
|
||||
.csr_badvaddr = 0, \
|
||||
/* \
|
||||
* Other stuff associated with the process \
|
||||
*/ \
|
||||
.trap_nr = 0, \
|
||||
.error_code = 0, \
|
||||
/* \
|
||||
* FPU & vector registers \
|
||||
*/ \
|
||||
.fpu = { \
|
||||
.fcsr = 0, \
|
||||
.vcsr = 0, \
|
||||
.fcc = 0, \
|
||||
.fpr = {{{0,},},}, \
|
||||
}, \
|
||||
}
|
||||
|
||||
struct task_struct;
|
||||
|
||||
/* Free all resources held by a thread. */
|
||||
#define release_thread(thread) do { } while (0)
|
||||
|
||||
enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_HALT, IDLE_NOMWAIT, IDLE_POLL};
|
||||
|
||||
extern unsigned long boot_option_idle_override;
|
||||
/*
|
||||
* Do necessary setup to start up a newly executed thread.
|
||||
*/
|
||||
extern void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp);
|
||||
|
||||
static inline void flush_thread(void)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long __get_wchan(struct task_struct *p);
|
||||
|
||||
#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \
|
||||
THREAD_SIZE - 32 - sizeof(struct pt_regs))
|
||||
#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk))
|
||||
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->csr_era)
|
||||
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[3])
|
||||
#define KSTK_EUEN(tsk) (task_pt_regs(tsk)->csr_euen)
|
||||
#define KSTK_ECFG(tsk) (task_pt_regs(tsk)->csr_ecfg)
|
||||
|
||||
#define return_address() ({__asm__ __volatile__("":::"$1"); __builtin_return_address(0);})
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_PREFETCH
|
||||
|
||||
#define ARCH_HAS_PREFETCH
|
||||
#define prefetch(x) __builtin_prefetch((x), 0, 1)
|
||||
|
||||
#define ARCH_HAS_PREFETCHW
|
||||
#define prefetchw(x) __builtin_prefetch((x), 1, 1)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_PROCESSOR_H */
|
152
arch/loongarch/include/asm/ptrace.h
Normal file
152
arch/loongarch/include/asm/ptrace.h
Normal file
@ -0,0 +1,152 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_PTRACE_H
|
||||
#define _ASM_PTRACE_H
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <uapi/asm/ptrace.h>
|
||||
|
||||
/*
|
||||
* This struct defines the way the registers are stored on the stack during
|
||||
* a system call/exception. If you add a register here, please also add it to
|
||||
* regoffset_table[] in arch/loongarch/kernel/ptrace.c.
|
||||
*/
|
||||
struct pt_regs {
|
||||
/* Main processor registers. */
|
||||
unsigned long regs[32];
|
||||
|
||||
/* Original syscall arg0. */
|
||||
unsigned long orig_a0;
|
||||
|
||||
/* Special CSR registers. */
|
||||
unsigned long csr_era;
|
||||
unsigned long csr_badvaddr;
|
||||
unsigned long csr_crmd;
|
||||
unsigned long csr_prmd;
|
||||
unsigned long csr_euen;
|
||||
unsigned long csr_ecfg;
|
||||
unsigned long csr_estat;
|
||||
unsigned long __last[0];
|
||||
} __aligned(8);
|
||||
|
||||
static inline int regs_irqs_disabled(struct pt_regs *regs)
|
||||
{
|
||||
return arch_irqs_disabled_flags(regs->csr_prmd);
|
||||
}
|
||||
|
||||
static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
|
||||
{
|
||||
return regs->regs[3];
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't use asm-generic/ptrace.h it defines FP accessors that don't make
|
||||
* sense on LoongArch. We rather want an error if they get invoked.
|
||||
*/
|
||||
|
||||
static inline void instruction_pointer_set(struct pt_regs *regs, unsigned long val)
|
||||
{
|
||||
regs->csr_era = val;
|
||||
}
|
||||
|
||||
/* Query offset/name of register from its name/offset */
|
||||
extern int regs_query_register_offset(const char *name);
|
||||
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
|
||||
|
||||
/**
|
||||
* regs_get_register() - get register value from its offset
|
||||
* @regs: pt_regs from which register value is gotten.
|
||||
* @offset: offset number of the register.
|
||||
*
|
||||
* regs_get_register returns the value of a register. The @offset is the
|
||||
* offset of the register in struct pt_regs address which specified by @regs.
|
||||
* If @offset is bigger than MAX_REG_OFFSET, this returns 0.
|
||||
*/
|
||||
static inline unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset)
|
||||
{
|
||||
if (unlikely(offset > MAX_REG_OFFSET))
|
||||
return 0;
|
||||
|
||||
return *(unsigned long *)((unsigned long)regs + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* regs_within_kernel_stack() - check the address in the stack
|
||||
* @regs: pt_regs which contains kernel stack pointer.
|
||||
* @addr: address which is checked.
|
||||
*
|
||||
* regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
|
||||
* If @addr is within the kernel stack, it returns true. If not, returns false.
|
||||
*/
|
||||
static inline int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
|
||||
{
|
||||
return ((addr & ~(THREAD_SIZE - 1)) ==
|
||||
(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* regs_get_kernel_stack_nth() - get Nth entry of the stack
|
||||
* @regs: pt_regs which contains kernel stack pointer.
|
||||
* @n: stack entry number.
|
||||
*
|
||||
* regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
|
||||
* is specified by @regs. If the @n th entry is NOT in the kernel stack,
|
||||
* this returns 0.
|
||||
*/
|
||||
static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
|
||||
{
|
||||
unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
|
||||
|
||||
addr += n;
|
||||
if (regs_within_kernel_stack(regs, (unsigned long)addr))
|
||||
return *addr;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct task_struct;
|
||||
|
||||
/*
|
||||
* Does the process account for user or for system time?
|
||||
*/
|
||||
#define user_mode(regs) (((regs)->csr_prmd & PLV_MASK) == PLV_USER)
|
||||
|
||||
static inline long regs_return_value(struct pt_regs *regs)
|
||||
{
|
||||
return regs->regs[4];
|
||||
}
|
||||
|
||||
#define instruction_pointer(regs) ((regs)->csr_era)
|
||||
#define profile_pc(regs) instruction_pointer(regs)
|
||||
|
||||
extern void die(const char *, struct pt_regs *) __noreturn;
|
||||
|
||||
static inline void die_if_kernel(const char *str, struct pt_regs *regs)
|
||||
{
|
||||
if (unlikely(!user_mode(regs)))
|
||||
die(str, regs);
|
||||
}
|
||||
|
||||
#define current_pt_regs() \
|
||||
({ \
|
||||
unsigned long sp = (unsigned long)__builtin_frame_address(0); \
|
||||
(struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1; \
|
||||
})
|
||||
|
||||
/* Helpers for working with the user stack pointer */
|
||||
|
||||
static inline unsigned long user_stack_pointer(struct pt_regs *regs)
|
||||
{
|
||||
return regs->regs[3];
|
||||
}
|
||||
|
||||
static inline void user_stack_pointer_set(struct pt_regs *regs,
|
||||
unsigned long val)
|
||||
{
|
||||
regs->regs[3] = val;
|
||||
}
|
||||
|
||||
#endif /* _ASM_PTRACE_H */
|
10
arch/loongarch/include/asm/reboot.h
Normal file
10
arch/loongarch/include/asm/reboot.h
Normal file
@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_REBOOT_H
|
||||
#define _ASM_REBOOT_H
|
||||
|
||||
extern void (*pm_restart)(void);
|
||||
|
||||
#endif /* _ASM_REBOOT_H */
|
41
arch/loongarch/include/asm/regdef.h
Normal file
41
arch/loongarch/include/asm/regdef.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_REGDEF_H
|
||||
#define _ASM_REGDEF_H
|
||||
|
||||
#define zero $r0 /* wired zero */
|
||||
#define ra $r1 /* return address */
|
||||
#define tp $r2
|
||||
#define sp $r3 /* stack pointer */
|
||||
#define a0 $r4 /* argument registers, a0/a1 reused as v0/v1 for return value */
|
||||
#define a1 $r5
|
||||
#define a2 $r6
|
||||
#define a3 $r7
|
||||
#define a4 $r8
|
||||
#define a5 $r9
|
||||
#define a6 $r10
|
||||
#define a7 $r11
|
||||
#define t0 $r12 /* caller saved */
|
||||
#define t1 $r13
|
||||
#define t2 $r14
|
||||
#define t3 $r15
|
||||
#define t4 $r16
|
||||
#define t5 $r17
|
||||
#define t6 $r18
|
||||
#define t7 $r19
|
||||
#define t8 $r20
|
||||
#define u0 $r21
|
||||
#define fp $r22 /* frame pointer */
|
||||
#define s0 $r23 /* callee saved */
|
||||
#define s1 $r24
|
||||
#define s2 $r25
|
||||
#define s3 $r26
|
||||
#define s4 $r27
|
||||
#define s5 $r28
|
||||
#define s6 $r29
|
||||
#define s7 $r30
|
||||
#define s8 $r31
|
||||
|
||||
#endif /* _ASM_REGDEF_H */
|
20
arch/loongarch/include/asm/seccomp.h
Normal file
20
arch/loongarch/include/asm/seccomp.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef _ASM_SECCOMP_H
|
||||
#define _ASM_SECCOMP_H
|
||||
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#include <asm-generic/seccomp.h>
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
# define SECCOMP_ARCH_NATIVE AUDIT_ARCH_LOONGARCH32
|
||||
# define SECCOMP_ARCH_NATIVE_NR NR_syscalls
|
||||
# define SECCOMP_ARCH_NATIVE_NAME "loongarch32"
|
||||
#else
|
||||
# define SECCOMP_ARCH_NATIVE AUDIT_ARCH_LOONGARCH64
|
||||
# define SECCOMP_ARCH_NATIVE_NR NR_syscalls
|
||||
# define SECCOMP_ARCH_NATIVE_NAME "loongarch64"
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_SECCOMP_H */
|
11
arch/loongarch/include/asm/serial.h
Normal file
11
arch/loongarch/include/asm/serial.h
Normal file
@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM__SERIAL_H
|
||||
#define __ASM__SERIAL_H
|
||||
|
||||
#define BASE_BAUD 0
|
||||
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
|
||||
|
||||
#endif /* __ASM__SERIAL_H */
|
21
arch/loongarch/include/asm/setup.h
Normal file
21
arch/loongarch/include/asm/setup.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _LOONGARCH_SETUP_H
|
||||
#define _LOONGARCH_SETUP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <uapi/asm/setup.h>
|
||||
|
||||
#define VECSIZE 0x200
|
||||
|
||||
extern unsigned long eentry;
|
||||
extern unsigned long tlbrentry;
|
||||
extern void cpu_cache_init(void);
|
||||
extern void per_cpu_trap_init(int cpu);
|
||||
extern void set_handler(unsigned long offset, void *addr, unsigned long len);
|
||||
extern void set_merr_handler(unsigned long offset, void *addr, unsigned long len);
|
||||
|
||||
#endif /* __SETUP_H */
|
12
arch/loongarch/include/asm/shmparam.h
Normal file
12
arch/loongarch/include/asm/shmparam.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_SHMPARAM_H
|
||||
#define _ASM_SHMPARAM_H
|
||||
|
||||
#define __ARCH_FORCE_SHMLBA 1
|
||||
|
||||
#define SHMLBA SZ_64K /* attach addr a multiple of this */
|
||||
|
||||
#endif /* _ASM_SHMPARAM_H */
|
124
arch/loongarch/include/asm/smp.h
Normal file
124
arch/loongarch/include/asm/smp.h
Normal file
@ -0,0 +1,124 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Author: Huacai Chen <chenhuacai@loongson.cn>
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef __ASM_SMP_H
|
||||
#define __ASM_SMP_H
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
void loongson3_smp_setup(void);
|
||||
void loongson3_prepare_cpus(unsigned int max_cpus);
|
||||
void loongson3_boot_secondary(int cpu, struct task_struct *idle);
|
||||
void loongson3_init_secondary(void);
|
||||
void loongson3_smp_finish(void);
|
||||
void loongson3_send_ipi_single(int cpu, unsigned int action);
|
||||
void loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action);
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
int loongson3_cpu_disable(void);
|
||||
void loongson3_cpu_die(unsigned int cpu);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
static inline void plat_smp_setup(void)
|
||||
{
|
||||
loongson3_smp_setup();
|
||||
}
|
||||
|
||||
#else /* !CONFIG_SMP */
|
||||
|
||||
static inline void plat_smp_setup(void) { }
|
||||
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
||||
extern int smp_num_siblings;
|
||||
extern int num_processors;
|
||||
extern int disabled_cpus;
|
||||
extern cpumask_t cpu_sibling_map[];
|
||||
extern cpumask_t cpu_core_map[];
|
||||
extern cpumask_t cpu_foreign_map[];
|
||||
|
||||
static inline int raw_smp_processor_id(void)
|
||||
{
|
||||
#if defined(__VDSO__)
|
||||
extern int vdso_smp_processor_id(void)
|
||||
__compiletime_error("VDSO should not call smp_processor_id()");
|
||||
return vdso_smp_processor_id();
|
||||
#else
|
||||
return current_thread_info()->cpu;
|
||||
#endif
|
||||
}
|
||||
#define raw_smp_processor_id raw_smp_processor_id
|
||||
|
||||
/* Map from cpu id to sequential logical cpu number. This will only
|
||||
* not be idempotent when cpus failed to come on-line. */
|
||||
extern int __cpu_number_map[NR_CPUS];
|
||||
#define cpu_number_map(cpu) __cpu_number_map[cpu]
|
||||
|
||||
/* The reverse map from sequential logical cpu number to cpu id. */
|
||||
extern int __cpu_logical_map[NR_CPUS];
|
||||
#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
|
||||
|
||||
#define cpu_physical_id(cpu) cpu_logical_map(cpu)
|
||||
|
||||
#define SMP_BOOT_CPU 0x1
|
||||
#define SMP_RESCHEDULE 0x2
|
||||
#define SMP_CALL_FUNCTION 0x4
|
||||
|
||||
struct secondary_data {
|
||||
unsigned long stack;
|
||||
unsigned long thread_info;
|
||||
};
|
||||
extern struct secondary_data cpuboot_data;
|
||||
|
||||
extern asmlinkage void smpboot_entry(void);
|
||||
|
||||
extern void calculate_cpu_foreign_map(void);
|
||||
|
||||
/*
|
||||
* Generate IPI list text
|
||||
*/
|
||||
extern void show_ipi_list(struct seq_file *p, int prec);
|
||||
|
||||
/*
|
||||
* This function sends a 'reschedule' IPI to another CPU.
|
||||
* it goes straight through and wastes no time serializing
|
||||
* anything. Worst case is that we lose a reschedule ...
|
||||
*/
|
||||
static inline void smp_send_reschedule(int cpu)
|
||||
{
|
||||
loongson3_send_ipi_single(cpu, SMP_RESCHEDULE);
|
||||
}
|
||||
|
||||
static inline void arch_send_call_function_single_ipi(int cpu)
|
||||
{
|
||||
loongson3_send_ipi_single(cpu, SMP_CALL_FUNCTION);
|
||||
}
|
||||
|
||||
static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
|
||||
{
|
||||
loongson3_send_ipi_mask(mask, SMP_CALL_FUNCTION);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static inline int __cpu_disable(void)
|
||||
{
|
||||
return loongson3_cpu_disable();
|
||||
}
|
||||
|
||||
static inline void __cpu_die(unsigned int cpu)
|
||||
{
|
||||
loongson3_cpu_die(cpu);
|
||||
}
|
||||
|
||||
extern void play_dead(void);
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_SMP_H */
|
23
arch/loongarch/include/asm/sparsemem.h
Normal file
23
arch/loongarch/include/asm/sparsemem.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LOONGARCH_SPARSEMEM_H
|
||||
#define _LOONGARCH_SPARSEMEM_H
|
||||
|
||||
#ifdef CONFIG_SPARSEMEM
|
||||
|
||||
/*
|
||||
* SECTION_SIZE_BITS 2^N: how big each section will be
|
||||
* MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
|
||||
*/
|
||||
#define SECTION_SIZE_BITS 29 /* 2^29 = Largest Huge Page Size */
|
||||
#define MAX_PHYSMEM_BITS 48
|
||||
|
||||
#endif /* CONFIG_SPARSEMEM */
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
int memory_add_physaddr_to_nid(u64 addr);
|
||||
#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
|
||||
#endif
|
||||
|
||||
#define INIT_MEMBLOCK_RESERVED_REGIONS (INIT_MEMBLOCK_REGIONS + NR_CPUS)
|
||||
|
||||
#endif /* _LOONGARCH_SPARSEMEM_H */
|
219
arch/loongarch/include/asm/stackframe.h
Normal file
219
arch/loongarch/include/asm/stackframe.h
Normal file
@ -0,0 +1,219 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_STACKFRAME_H
|
||||
#define _ASM_STACKFRAME_H
|
||||
|
||||
#include <linux/threads.h>
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/loongarch.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
/* Make the addition of cfi info a little easier. */
|
||||
.macro cfi_rel_offset reg offset=0 docfi=0
|
||||
.if \docfi
|
||||
.cfi_rel_offset \reg, \offset
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro cfi_st reg offset=0 docfi=0
|
||||
cfi_rel_offset \reg, \offset, \docfi
|
||||
LONG_S \reg, sp, \offset
|
||||
.endm
|
||||
|
||||
.macro cfi_restore reg offset=0 docfi=0
|
||||
.if \docfi
|
||||
.cfi_restore \reg
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro cfi_ld reg offset=0 docfi=0
|
||||
LONG_L \reg, sp, \offset
|
||||
cfi_restore \reg \offset \docfi
|
||||
.endm
|
||||
|
||||
.macro BACKUP_T0T1
|
||||
csrwr t0, EXCEPTION_KS0
|
||||
csrwr t1, EXCEPTION_KS1
|
||||
.endm
|
||||
|
||||
.macro RELOAD_T0T1
|
||||
csrrd t0, EXCEPTION_KS0
|
||||
csrrd t1, EXCEPTION_KS1
|
||||
.endm
|
||||
|
||||
.macro SAVE_TEMP docfi=0
|
||||
RELOAD_T0T1
|
||||
cfi_st t0, PT_R12, \docfi
|
||||
cfi_st t1, PT_R13, \docfi
|
||||
cfi_st t2, PT_R14, \docfi
|
||||
cfi_st t3, PT_R15, \docfi
|
||||
cfi_st t4, PT_R16, \docfi
|
||||
cfi_st t5, PT_R17, \docfi
|
||||
cfi_st t6, PT_R18, \docfi
|
||||
cfi_st t7, PT_R19, \docfi
|
||||
cfi_st t8, PT_R20, \docfi
|
||||
.endm
|
||||
|
||||
.macro SAVE_STATIC docfi=0
|
||||
cfi_st s0, PT_R23, \docfi
|
||||
cfi_st s1, PT_R24, \docfi
|
||||
cfi_st s2, PT_R25, \docfi
|
||||
cfi_st s3, PT_R26, \docfi
|
||||
cfi_st s4, PT_R27, \docfi
|
||||
cfi_st s5, PT_R28, \docfi
|
||||
cfi_st s6, PT_R29, \docfi
|
||||
cfi_st s7, PT_R30, \docfi
|
||||
cfi_st s8, PT_R31, \docfi
|
||||
.endm
|
||||
|
||||
/*
|
||||
* get_saved_sp returns the SP for the current CPU by looking in the
|
||||
* kernelsp array for it. It stores the current sp in t0 and loads the
|
||||
* new value in sp.
|
||||
*/
|
||||
.macro get_saved_sp docfi=0
|
||||
la.abs t1, kernelsp
|
||||
#ifdef CONFIG_SMP
|
||||
csrrd t0, PERCPU_BASE_KS
|
||||
LONG_ADD t1, t1, t0
|
||||
#endif
|
||||
move t0, sp
|
||||
.if \docfi
|
||||
.cfi_register sp, t0
|
||||
.endif
|
||||
LONG_L sp, t1, 0
|
||||
.endm
|
||||
|
||||
.macro set_saved_sp stackp temp temp2
|
||||
la.abs \temp, kernelsp
|
||||
#ifdef CONFIG_SMP
|
||||
LONG_ADD \temp, \temp, u0
|
||||
#endif
|
||||
LONG_S \stackp, \temp, 0
|
||||
.endm
|
||||
|
||||
.macro SAVE_SOME docfi=0
|
||||
csrrd t1, LOONGARCH_CSR_PRMD
|
||||
andi t1, t1, 0x3 /* extract pplv bit */
|
||||
move t0, sp
|
||||
beqz t1, 8f
|
||||
/* Called from user mode, new stack. */
|
||||
get_saved_sp docfi=\docfi
|
||||
8:
|
||||
PTR_ADDI sp, sp, -PT_SIZE
|
||||
.if \docfi
|
||||
.cfi_def_cfa sp, 0
|
||||
.endif
|
||||
cfi_st t0, PT_R3, \docfi
|
||||
cfi_rel_offset sp, PT_R3, \docfi
|
||||
LONG_S zero, sp, PT_R0
|
||||
csrrd t0, LOONGARCH_CSR_PRMD
|
||||
LONG_S t0, sp, PT_PRMD
|
||||
csrrd t0, LOONGARCH_CSR_CRMD
|
||||
LONG_S t0, sp, PT_CRMD
|
||||
csrrd t0, LOONGARCH_CSR_EUEN
|
||||
LONG_S t0, sp, PT_EUEN
|
||||
csrrd t0, LOONGARCH_CSR_ECFG
|
||||
LONG_S t0, sp, PT_ECFG
|
||||
csrrd t0, LOONGARCH_CSR_ESTAT
|
||||
PTR_S t0, sp, PT_ESTAT
|
||||
cfi_st ra, PT_R1, \docfi
|
||||
cfi_st a0, PT_R4, \docfi
|
||||
cfi_st a1, PT_R5, \docfi
|
||||
cfi_st a2, PT_R6, \docfi
|
||||
cfi_st a3, PT_R7, \docfi
|
||||
cfi_st a4, PT_R8, \docfi
|
||||
cfi_st a5, PT_R9, \docfi
|
||||
cfi_st a6, PT_R10, \docfi
|
||||
cfi_st a7, PT_R11, \docfi
|
||||
csrrd ra, LOONGARCH_CSR_ERA
|
||||
LONG_S ra, sp, PT_ERA
|
||||
.if \docfi
|
||||
.cfi_rel_offset ra, PT_ERA
|
||||
.endif
|
||||
cfi_st tp, PT_R2, \docfi
|
||||
cfi_st fp, PT_R22, \docfi
|
||||
|
||||
/* Set thread_info if we're coming from user mode */
|
||||
csrrd t0, LOONGARCH_CSR_PRMD
|
||||
andi t0, t0, 0x3 /* extract pplv bit */
|
||||
beqz t0, 9f
|
||||
|
||||
li.d tp, ~_THREAD_MASK
|
||||
and tp, tp, sp
|
||||
cfi_st u0, PT_R21, \docfi
|
||||
csrrd u0, PERCPU_BASE_KS
|
||||
9:
|
||||
.endm
|
||||
|
||||
.macro SAVE_ALL docfi=0
|
||||
SAVE_SOME \docfi
|
||||
SAVE_TEMP \docfi
|
||||
SAVE_STATIC \docfi
|
||||
.endm
|
||||
|
||||
.macro RESTORE_TEMP docfi=0
|
||||
cfi_ld t0, PT_R12, \docfi
|
||||
cfi_ld t1, PT_R13, \docfi
|
||||
cfi_ld t2, PT_R14, \docfi
|
||||
cfi_ld t3, PT_R15, \docfi
|
||||
cfi_ld t4, PT_R16, \docfi
|
||||
cfi_ld t5, PT_R17, \docfi
|
||||
cfi_ld t6, PT_R18, \docfi
|
||||
cfi_ld t7, PT_R19, \docfi
|
||||
cfi_ld t8, PT_R20, \docfi
|
||||
.endm
|
||||
|
||||
.macro RESTORE_STATIC docfi=0
|
||||
cfi_ld s0, PT_R23, \docfi
|
||||
cfi_ld s1, PT_R24, \docfi
|
||||
cfi_ld s2, PT_R25, \docfi
|
||||
cfi_ld s3, PT_R26, \docfi
|
||||
cfi_ld s4, PT_R27, \docfi
|
||||
cfi_ld s5, PT_R28, \docfi
|
||||
cfi_ld s6, PT_R29, \docfi
|
||||
cfi_ld s7, PT_R30, \docfi
|
||||
cfi_ld s8, PT_R31, \docfi
|
||||
.endm
|
||||
|
||||
.macro RESTORE_SOME docfi=0
|
||||
LONG_L a0, sp, PT_PRMD
|
||||
andi a0, a0, 0x3 /* extract pplv bit */
|
||||
beqz a0, 8f
|
||||
cfi_ld u0, PT_R21, \docfi
|
||||
8:
|
||||
LONG_L a0, sp, PT_ERA
|
||||
csrwr a0, LOONGARCH_CSR_ERA
|
||||
LONG_L a0, sp, PT_PRMD
|
||||
csrwr a0, LOONGARCH_CSR_PRMD
|
||||
cfi_ld ra, PT_R1, \docfi
|
||||
cfi_ld a0, PT_R4, \docfi
|
||||
cfi_ld a1, PT_R5, \docfi
|
||||
cfi_ld a2, PT_R6, \docfi
|
||||
cfi_ld a3, PT_R7, \docfi
|
||||
cfi_ld a4, PT_R8, \docfi
|
||||
cfi_ld a5, PT_R9, \docfi
|
||||
cfi_ld a6, PT_R10, \docfi
|
||||
cfi_ld a7, PT_R11, \docfi
|
||||
cfi_ld tp, PT_R2, \docfi
|
||||
cfi_ld fp, PT_R22, \docfi
|
||||
.endm
|
||||
|
||||
.macro RESTORE_SP_AND_RET docfi=0
|
||||
cfi_ld sp, PT_R3, \docfi
|
||||
ertn
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL_AND_RET docfi=0
|
||||
RESTORE_STATIC \docfi
|
||||
RESTORE_TEMP \docfi
|
||||
RESTORE_SOME \docfi
|
||||
RESTORE_SP_AND_RET \docfi
|
||||
.endm
|
||||
|
||||
#endif /* _ASM_STACKFRAME_H */
|
74
arch/loongarch/include/asm/stacktrace.h
Normal file
74
arch/loongarch/include/asm/stacktrace.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_STACKTRACE_H
|
||||
#define _ASM_STACKTRACE_H
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/loongarch.h>
|
||||
#include <linux/stringify.h>
|
||||
|
||||
#define STR_LONG_L __stringify(LONG_L)
|
||||
#define STR_LONG_S __stringify(LONG_S)
|
||||
#define STR_LONGSIZE __stringify(LONGSIZE)
|
||||
|
||||
#define STORE_ONE_REG(r) \
|
||||
STR_LONG_S " $r" __stringify(r)", %1, "STR_LONGSIZE"*"__stringify(r)"\n\t"
|
||||
|
||||
#define CSRRD_ONE_REG(reg) \
|
||||
__stringify(csrrd) " %0, "__stringify(reg)"\n\t"
|
||||
|
||||
static __always_inline void prepare_frametrace(struct pt_regs *regs)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
/* Save $r1 */
|
||||
STORE_ONE_REG(1)
|
||||
/* Use $r1 to save PC */
|
||||
"pcaddi $r1, 0\n\t"
|
||||
STR_LONG_S " $r1, %0\n\t"
|
||||
/* Restore $r1 */
|
||||
STR_LONG_L " $r1, %1, "STR_LONGSIZE"\n\t"
|
||||
STORE_ONE_REG(2)
|
||||
STORE_ONE_REG(3)
|
||||
STORE_ONE_REG(4)
|
||||
STORE_ONE_REG(5)
|
||||
STORE_ONE_REG(6)
|
||||
STORE_ONE_REG(7)
|
||||
STORE_ONE_REG(8)
|
||||
STORE_ONE_REG(9)
|
||||
STORE_ONE_REG(10)
|
||||
STORE_ONE_REG(11)
|
||||
STORE_ONE_REG(12)
|
||||
STORE_ONE_REG(13)
|
||||
STORE_ONE_REG(14)
|
||||
STORE_ONE_REG(15)
|
||||
STORE_ONE_REG(16)
|
||||
STORE_ONE_REG(17)
|
||||
STORE_ONE_REG(18)
|
||||
STORE_ONE_REG(19)
|
||||
STORE_ONE_REG(20)
|
||||
STORE_ONE_REG(21)
|
||||
STORE_ONE_REG(22)
|
||||
STORE_ONE_REG(23)
|
||||
STORE_ONE_REG(24)
|
||||
STORE_ONE_REG(25)
|
||||
STORE_ONE_REG(26)
|
||||
STORE_ONE_REG(27)
|
||||
STORE_ONE_REG(28)
|
||||
STORE_ONE_REG(29)
|
||||
STORE_ONE_REG(30)
|
||||
STORE_ONE_REG(31)
|
||||
: "=m" (regs->csr_era)
|
||||
: "r" (regs->regs)
|
||||
: "memory");
|
||||
__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_BADV) : "=r" (regs->csr_badvaddr));
|
||||
__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_CRMD) : "=r" (regs->csr_crmd));
|
||||
__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_PRMD) : "=r" (regs->csr_prmd));
|
||||
__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_EUEN) : "=r" (regs->csr_euen));
|
||||
__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_ECFG) : "=r" (regs->csr_ecfg));
|
||||
__asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_ESTAT) : "=r" (regs->csr_estat));
|
||||
}
|
||||
|
||||
#endif /* _ASM_STACKTRACE_H */
|
12
arch/loongarch/include/asm/string.h
Normal file
12
arch/loongarch/include/asm/string.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_STRING_H
|
||||
#define _ASM_STRING_H
|
||||
|
||||
extern void *memset(void *__s, int __c, size_t __count);
|
||||
extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
|
||||
extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
|
||||
|
||||
#endif /* _ASM_STRING_H */
|
37
arch/loongarch/include/asm/switch_to.h
Normal file
37
arch/loongarch/include/asm/switch_to.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_SWITCH_TO_H
|
||||
#define _ASM_SWITCH_TO_H
|
||||
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/fpu.h>
|
||||
|
||||
struct task_struct;
|
||||
|
||||
/**
|
||||
* __switch_to - switch execution of a task
|
||||
* @prev: The task previously executed.
|
||||
* @next: The task to begin executing.
|
||||
* @next_ti: task_thread_info(next).
|
||||
*
|
||||
* This function is used whilst scheduling to save the context of prev & load
|
||||
* the context of next. Returns prev.
|
||||
*/
|
||||
extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
|
||||
struct task_struct *next, struct thread_info *next_ti);
|
||||
|
||||
/*
|
||||
* For newly created kernel threads switch_to() will return to
|
||||
* ret_from_kernel_thread, newly created user threads to ret_from_fork.
|
||||
* That is, everything following __switch_to() will be skipped for new threads.
|
||||
* So everything that matters to new threads should be placed before __switch_to().
|
||||
*/
|
||||
#define switch_to(prev, next, last) \
|
||||
do { \
|
||||
lose_fpu_inatomic(1, prev); \
|
||||
(last) = __switch_to(prev, next, task_thread_info(next)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _ASM_SWITCH_TO_H */
|
74
arch/loongarch/include/asm/syscall.h
Normal file
74
arch/loongarch/include/asm/syscall.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Author: Hanlu Li <lihanlu@loongson.cn>
|
||||
* Huacai Chen <chenhuacai@loongson.cn>
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef __ASM_LOONGARCH_SYSCALL_H
|
||||
#define __ASM_LOONGARCH_SYSCALL_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <uapi/linux/audit.h>
|
||||
#include <linux/elf-em.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
extern void *sys_call_table[];
|
||||
|
||||
static inline long syscall_get_nr(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return regs->regs[11];
|
||||
}
|
||||
|
||||
static inline void syscall_rollback(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs->regs[4] = regs->orig_a0;
|
||||
}
|
||||
|
||||
static inline long syscall_get_error(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long error = regs->regs[4];
|
||||
|
||||
return IS_ERR_VALUE(error) ? error : 0;
|
||||
}
|
||||
|
||||
static inline long syscall_get_return_value(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return regs->regs[4];
|
||||
}
|
||||
|
||||
static inline void syscall_set_return_value(struct task_struct *task,
|
||||
struct pt_regs *regs,
|
||||
int error, long val)
|
||||
{
|
||||
regs->regs[4] = (long) error ? error : val;
|
||||
}
|
||||
|
||||
static inline void syscall_get_arguments(struct task_struct *task,
|
||||
struct pt_regs *regs,
|
||||
unsigned long *args)
|
||||
{
|
||||
args[0] = regs->orig_a0;
|
||||
memcpy(&args[1], ®s->regs[5], 5 * sizeof(long));
|
||||
}
|
||||
|
||||
static inline int syscall_get_arch(struct task_struct *task)
|
||||
{
|
||||
return AUDIT_ARCH_LOONGARCH64;
|
||||
}
|
||||
|
||||
static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* __ASM_LOONGARCH_SYSCALL_H */
|
106
arch/loongarch/include/asm/thread_info.h
Normal file
106
arch/loongarch/include/asm/thread_info.h
Normal file
@ -0,0 +1,106 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* thread_info.h: LoongArch low-level thread information
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _ASM_THREAD_INFO_H
|
||||
#define _ASM_THREAD_INFO_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
/*
|
||||
* low level task data that entry.S needs immediate access to
|
||||
* - this struct should fit entirely inside of one cache line
|
||||
* - this struct shares the supervisor stack pages
|
||||
* - if the contents of this structure are changed, the assembly constants
|
||||
* must also be changed
|
||||
*/
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
unsigned long tp_value; /* thread pointer */
|
||||
__u32 cpu; /* current CPU */
|
||||
int preempt_count; /* 0 => preemptible, <0 => BUG */
|
||||
struct pt_regs *regs;
|
||||
unsigned long syscall; /* syscall number */
|
||||
unsigned long syscall_work; /* SYSCALL_WORK_ flags */
|
||||
};
|
||||
|
||||
/*
|
||||
* macros/functions for gaining access to the thread information structure
|
||||
*/
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
}
|
||||
|
||||
/* How to get the thread information struct from C. */
|
||||
register struct thread_info *__current_thread_info __asm__("$r2");
|
||||
|
||||
static inline struct thread_info *current_thread_info(void)
|
||||
{
|
||||
return __current_thread_info;
|
||||
}
|
||||
|
||||
register unsigned long current_stack_pointer __asm__("$r3");
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
/* thread information allocation */
|
||||
#define THREAD_SIZE SZ_16K
|
||||
#define THREAD_MASK (THREAD_SIZE - 1UL)
|
||||
#define THREAD_SIZE_ORDER ilog2(THREAD_SIZE / PAGE_SIZE)
|
||||
/*
|
||||
* thread information flags
|
||||
* - these are process state flags that various assembly files may need to
|
||||
* access
|
||||
* - pending work-to-be-done flags are in LSW
|
||||
* - other flags in MSW
|
||||
*/
|
||||
#define TIF_SIGPENDING 1 /* signal pending */
|
||||
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
|
||||
#define TIF_NOTIFY_RESUME 3 /* callback before returning to user */
|
||||
#define TIF_NOTIFY_SIGNAL 4 /* signal notifications exist */
|
||||
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
|
||||
#define TIF_NOHZ 6 /* in adaptive nohz mode */
|
||||
#define TIF_UPROBE 7 /* breakpointed or singlestepping */
|
||||
#define TIF_USEDFPU 8 /* FPU was used by this task this quantum (SMP) */
|
||||
#define TIF_USEDSIMD 9 /* SIMD has been used this quantum */
|
||||
#define TIF_MEMDIE 10 /* is terminating due to OOM killer */
|
||||
#define TIF_FIXADE 11 /* Fix address errors in software */
|
||||
#define TIF_LOGADE 12 /* Log address errors to syslog */
|
||||
#define TIF_32BIT_REGS 13 /* 32-bit general purpose registers */
|
||||
#define TIF_32BIT_ADDR 14 /* 32-bit address space */
|
||||
#define TIF_LOAD_WATCH 15 /* If set, load watch registers */
|
||||
#define TIF_SINGLESTEP 16 /* Single Step */
|
||||
#define TIF_LSX_CTX_LIVE 17 /* LSX context must be preserved */
|
||||
#define TIF_LASX_CTX_LIVE 18 /* LASX context must be preserved */
|
||||
|
||||
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
|
||||
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
|
||||
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
|
||||
#define _TIF_NOTIFY_SIGNAL (1<<TIF_NOTIFY_SIGNAL)
|
||||
#define _TIF_NOHZ (1<<TIF_NOHZ)
|
||||
#define _TIF_UPROBE (1<<TIF_UPROBE)
|
||||
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
|
||||
#define _TIF_USEDSIMD (1<<TIF_USEDSIMD)
|
||||
#define _TIF_FIXADE (1<<TIF_FIXADE)
|
||||
#define _TIF_LOGADE (1<<TIF_LOGADE)
|
||||
#define _TIF_32BIT_REGS (1<<TIF_32BIT_REGS)
|
||||
#define _TIF_32BIT_ADDR (1<<TIF_32BIT_ADDR)
|
||||
#define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH)
|
||||
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
|
||||
#define _TIF_LSX_CTX_LIVE (1<<TIF_LSX_CTX_LIVE)
|
||||
#define _TIF_LASX_CTX_LIVE (1<<TIF_LASX_CTX_LIVE)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_THREAD_INFO_H */
|
50
arch/loongarch/include/asm/time.h
Normal file
50
arch/loongarch/include/asm/time.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_TIME_H
|
||||
#define _ASM_TIME_H
|
||||
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <asm/loongarch.h>
|
||||
|
||||
extern u64 cpu_clock_freq;
|
||||
extern u64 const_clock_freq;
|
||||
|
||||
extern void sync_counter(void);
|
||||
|
||||
static inline unsigned int calc_const_freq(void)
|
||||
{
|
||||
unsigned int res;
|
||||
unsigned int base_freq;
|
||||
unsigned int cfm, cfd;
|
||||
|
||||
res = read_cpucfg(LOONGARCH_CPUCFG2);
|
||||
if (!(res & CPUCFG2_LLFTP))
|
||||
return 0;
|
||||
|
||||
base_freq = read_cpucfg(LOONGARCH_CPUCFG4);
|
||||
res = read_cpucfg(LOONGARCH_CPUCFG5);
|
||||
cfm = res & 0xffff;
|
||||
cfd = (res >> 16) & 0xffff;
|
||||
|
||||
if (!base_freq || !cfm || !cfd)
|
||||
return 0;
|
||||
|
||||
return (base_freq * cfm / cfd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the calling CPU's timer interrupt as clockevent device
|
||||
*/
|
||||
extern int constant_clockevent_init(void);
|
||||
extern int constant_clocksource_init(void);
|
||||
|
||||
static inline void clockevent_set_clock(struct clock_event_device *cd,
|
||||
unsigned int clock)
|
||||
{
|
||||
clockevents_calc_mult_shift(cd, clock, 4);
|
||||
}
|
||||
|
||||
#endif /* _ASM_TIME_H */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user