mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
Merge c6f2f3e2c8 ("Merge tag 'loongarch-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic") into android-mainline
Steps on the way to 5.19-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I05ae19048cc94eff6829c07421b885713e0945f4
This commit is contained in:
@@ -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
@@ -11572,6 +11572,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
Reference in New Issue
Block a user