Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: "This is the main pull request for MIPS: - a number of fixes that didn't make the 3.19 release. - a number of cleanups. - preliminary support for Cavium's Octeon 3 SOCs which feature up to 48 MIPS64 R3 cores with FPU and hardware virtualization. - support for MIPS R6 processors. Revision 6 of the MIPS architecture is a major revision of the MIPS architecture which does away with many of original sins of the architecture such as branch delay slots. This and other changes in R6 require major changes throughout the entire MIPS core architecture code and make up for the lion share of this pull request. - finally some preparatory work for eXtendend Physical Address support, which allows support of up to 40 bit of physical address space on 32 bit processors" [ Ahh, MIPS can't leave the PAE brain damage alone. It's like every CPU architect has to make that mistake, but pee in the snow by changing the TLA. But whether it's called PAE, LPAE or XPA, it's horrid crud - Linus ] * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (114 commits) MIPS: sead3: Corrected get_c0_perfcount_int MIPS: mm: Remove dead macro definitions MIPS: OCTEON: irq: add CIB and other fixes MIPS: OCTEON: Don't do acknowledge operations for level triggered irqs. MIPS: OCTEON: More OCTEONIII support MIPS: OCTEON: Remove setting of processor specific CVMCTL icache bits. MIPS: OCTEON: Core-15169 Workaround and general CVMSEG cleanup. MIPS: OCTEON: Update octeon-model.h code for new SoCs. MIPS: OCTEON: Implement DCache errata workaround for all CN6XXX MIPS: OCTEON: Add little-endian support to asm/octeon/octeon.h MIPS: OCTEON: Implement the core-16057 workaround MIPS: OCTEON: Delete unused COP2 saving code MIPS: OCTEON: Use correct instruction to read 64-bit COP0 register MIPS: OCTEON: Save and restore CP2 SHA3 state MIPS: OCTEON: Fix FP context save. MIPS: OCTEON: Save/Restore wider multiply registers in OCTEON III CPUs MIPS: boot: Provide more uImage options MIPS: Remove unneeded #ifdef __KERNEL__ from asm/processor.h MIPS: ip22-gio: Remove legacy suspend/resume support mips: pci: Add ifdef around pci_proc_domain ...
This commit is contained in:
commit
a135c717d5
|
@ -0,0 +1,43 @@
|
||||||
|
* Cavium Interrupt Bus widget
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
- compatible: "cavium,octeon-7130-cib"
|
||||||
|
|
||||||
|
Compatibility with cn70XX SoCs.
|
||||||
|
|
||||||
|
- interrupt-controller: This is an interrupt controller.
|
||||||
|
|
||||||
|
- reg: Two elements consisting of the addresses of the RAW and EN
|
||||||
|
registers of the CIB block
|
||||||
|
|
||||||
|
- cavium,max-bits: The index (zero based) of the highest numbered bit
|
||||||
|
in the CIB block.
|
||||||
|
|
||||||
|
- interrupt-parent: Always the CIU on the SoC.
|
||||||
|
|
||||||
|
- interrupts: The CIU line to which the CIB block is connected.
|
||||||
|
|
||||||
|
- #interrupt-cells: Must be <2>. The first cell is the bit within the
|
||||||
|
CIB. The second cell specifies the triggering semantics of the
|
||||||
|
line.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
interrupt-controller@107000000e000 {
|
||||||
|
compatible = "cavium,octeon-7130-cib";
|
||||||
|
reg = <0x10700 0x0000e000 0x0 0x8>, /* RAW */
|
||||||
|
<0x10700 0x0000e100 0x0 0x8>; /* EN */
|
||||||
|
cavium,max-bits = <23>;
|
||||||
|
|
||||||
|
interrupt-controller;
|
||||||
|
interrupt-parent = <&ciu>;
|
||||||
|
interrupts = <1 24>;
|
||||||
|
/* Interrupts are specified by two parts:
|
||||||
|
* 1) Bit number in the CIB* registers
|
||||||
|
* 2) Triggering (1 - edge rising
|
||||||
|
* 2 - edge falling
|
||||||
|
* 4 - level active high
|
||||||
|
* 8 - level active low)
|
||||||
|
*/
|
||||||
|
#interrupt-cells = <2>;
|
||||||
|
};
|
|
@ -54,6 +54,7 @@ config MIPS
|
||||||
select CPU_PM if CPU_IDLE
|
select CPU_PM if CPU_IDLE
|
||||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
select ARCH_BINFMT_ELF_STATE
|
select ARCH_BINFMT_ELF_STATE
|
||||||
|
select SYSCTL_EXCEPTION_TRACE
|
||||||
|
|
||||||
menu "Machine selection"
|
menu "Machine selection"
|
||||||
|
|
||||||
|
@ -376,8 +377,10 @@ config MIPS_MALTA
|
||||||
select SYS_HAS_CPU_MIPS32_R1
|
select SYS_HAS_CPU_MIPS32_R1
|
||||||
select SYS_HAS_CPU_MIPS32_R2
|
select SYS_HAS_CPU_MIPS32_R2
|
||||||
select SYS_HAS_CPU_MIPS32_R3_5
|
select SYS_HAS_CPU_MIPS32_R3_5
|
||||||
|
select SYS_HAS_CPU_MIPS32_R6
|
||||||
select SYS_HAS_CPU_MIPS64_R1
|
select SYS_HAS_CPU_MIPS64_R1
|
||||||
select SYS_HAS_CPU_MIPS64_R2
|
select SYS_HAS_CPU_MIPS64_R2
|
||||||
|
select SYS_HAS_CPU_MIPS64_R6
|
||||||
select SYS_HAS_CPU_NEVADA
|
select SYS_HAS_CPU_NEVADA
|
||||||
select SYS_HAS_CPU_RM7000
|
select SYS_HAS_CPU_RM7000
|
||||||
select SYS_SUPPORTS_32BIT_KERNEL
|
select SYS_SUPPORTS_32BIT_KERNEL
|
||||||
|
@ -1033,6 +1036,9 @@ config MIPS_MACHINE
|
||||||
config NO_IOPORT_MAP
|
config NO_IOPORT_MAP
|
||||||
def_bool n
|
def_bool n
|
||||||
|
|
||||||
|
config GENERIC_CSUM
|
||||||
|
bool
|
||||||
|
|
||||||
config GENERIC_ISA_DMA
|
config GENERIC_ISA_DMA
|
||||||
bool
|
bool
|
||||||
select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n
|
select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n
|
||||||
|
@ -1146,6 +1152,9 @@ config SOC_PNX8335
|
||||||
bool
|
bool
|
||||||
select SOC_PNX833X
|
select SOC_PNX833X
|
||||||
|
|
||||||
|
config MIPS_SPRAM
|
||||||
|
bool
|
||||||
|
|
||||||
config SWAP_IO_SPACE
|
config SWAP_IO_SPACE
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -1304,6 +1313,22 @@ config CPU_MIPS32_R2
|
||||||
specific type of processor in your system, choose those that one
|
specific type of processor in your system, choose those that one
|
||||||
otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
|
otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
|
||||||
|
|
||||||
|
config CPU_MIPS32_R6
|
||||||
|
bool "MIPS32 Release 6 (EXPERIMENTAL)"
|
||||||
|
depends on SYS_HAS_CPU_MIPS32_R6
|
||||||
|
select CPU_HAS_PREFETCH
|
||||||
|
select CPU_SUPPORTS_32BIT_KERNEL
|
||||||
|
select CPU_SUPPORTS_HIGHMEM
|
||||||
|
select CPU_SUPPORTS_MSA
|
||||||
|
select GENERIC_CSUM
|
||||||
|
select HAVE_KVM
|
||||||
|
select MIPS_O32_FP64_SUPPORT
|
||||||
|
help
|
||||||
|
Choose this option to build a kernel for release 6 or later of the
|
||||||
|
MIPS32 architecture. New MIPS processors, starting with the Warrior
|
||||||
|
family, are based on a MIPS32r6 processor. If you own an older
|
||||||
|
processor, you probably need to select MIPS32r1 or MIPS32r2 instead.
|
||||||
|
|
||||||
config CPU_MIPS64_R1
|
config CPU_MIPS64_R1
|
||||||
bool "MIPS64 Release 1"
|
bool "MIPS64 Release 1"
|
||||||
depends on SYS_HAS_CPU_MIPS64_R1
|
depends on SYS_HAS_CPU_MIPS64_R1
|
||||||
|
@ -1339,6 +1364,21 @@ config CPU_MIPS64_R2
|
||||||
specific type of processor in your system, choose those that one
|
specific type of processor in your system, choose those that one
|
||||||
otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
|
otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
|
||||||
|
|
||||||
|
config CPU_MIPS64_R6
|
||||||
|
bool "MIPS64 Release 6 (EXPERIMENTAL)"
|
||||||
|
depends on SYS_HAS_CPU_MIPS64_R6
|
||||||
|
select CPU_HAS_PREFETCH
|
||||||
|
select CPU_SUPPORTS_32BIT_KERNEL
|
||||||
|
select CPU_SUPPORTS_64BIT_KERNEL
|
||||||
|
select CPU_SUPPORTS_HIGHMEM
|
||||||
|
select CPU_SUPPORTS_MSA
|
||||||
|
select GENERIC_CSUM
|
||||||
|
help
|
||||||
|
Choose this option to build a kernel for release 6 or later of the
|
||||||
|
MIPS64 architecture. New MIPS processors, starting with the Warrior
|
||||||
|
family, are based on a MIPS64r6 processor. If you own an older
|
||||||
|
processor, you probably need to select MIPS64r1 or MIPS64r2 instead.
|
||||||
|
|
||||||
config CPU_R3000
|
config CPU_R3000
|
||||||
bool "R3000"
|
bool "R3000"
|
||||||
depends on SYS_HAS_CPU_R3000
|
depends on SYS_HAS_CPU_R3000
|
||||||
|
@ -1539,7 +1579,7 @@ endchoice
|
||||||
config CPU_MIPS32_3_5_FEATURES
|
config CPU_MIPS32_3_5_FEATURES
|
||||||
bool "MIPS32 Release 3.5 Features"
|
bool "MIPS32 Release 3.5 Features"
|
||||||
depends on SYS_HAS_CPU_MIPS32_R3_5
|
depends on SYS_HAS_CPU_MIPS32_R3_5
|
||||||
depends on CPU_MIPS32_R2
|
depends on CPU_MIPS32_R2 || CPU_MIPS32_R6
|
||||||
help
|
help
|
||||||
Choose this option to build a kernel for release 2 or later of the
|
Choose this option to build a kernel for release 2 or later of the
|
||||||
MIPS32 architecture including features from the 3.5 release such as
|
MIPS32 architecture including features from the 3.5 release such as
|
||||||
|
@ -1659,12 +1699,18 @@ config SYS_HAS_CPU_MIPS32_R2
|
||||||
config SYS_HAS_CPU_MIPS32_R3_5
|
config SYS_HAS_CPU_MIPS32_R3_5
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config SYS_HAS_CPU_MIPS32_R6
|
||||||
|
bool
|
||||||
|
|
||||||
config SYS_HAS_CPU_MIPS64_R1
|
config SYS_HAS_CPU_MIPS64_R1
|
||||||
bool
|
bool
|
||||||
|
|
||||||
config SYS_HAS_CPU_MIPS64_R2
|
config SYS_HAS_CPU_MIPS64_R2
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config SYS_HAS_CPU_MIPS64_R6
|
||||||
|
bool
|
||||||
|
|
||||||
config SYS_HAS_CPU_R3000
|
config SYS_HAS_CPU_R3000
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -1764,11 +1810,11 @@ endmenu
|
||||||
#
|
#
|
||||||
config CPU_MIPS32
|
config CPU_MIPS32
|
||||||
bool
|
bool
|
||||||
default y if CPU_MIPS32_R1 || CPU_MIPS32_R2
|
default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 || CPU_MIPS32_R6
|
||||||
|
|
||||||
config CPU_MIPS64
|
config CPU_MIPS64
|
||||||
bool
|
bool
|
||||||
default y if CPU_MIPS64_R1 || CPU_MIPS64_R2
|
default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R6
|
||||||
|
|
||||||
#
|
#
|
||||||
# These two indicate the revision of the architecture, either Release 1 or Release 2
|
# These two indicate the revision of the architecture, either Release 1 or Release 2
|
||||||
|
@ -1780,6 +1826,12 @@ config CPU_MIPSR1
|
||||||
config CPU_MIPSR2
|
config CPU_MIPSR2
|
||||||
bool
|
bool
|
||||||
default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
|
default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
|
||||||
|
select MIPS_SPRAM
|
||||||
|
|
||||||
|
config CPU_MIPSR6
|
||||||
|
bool
|
||||||
|
default y if CPU_MIPS32_R6 || CPU_MIPS64_R6
|
||||||
|
select MIPS_SPRAM
|
||||||
|
|
||||||
config EVA
|
config EVA
|
||||||
bool
|
bool
|
||||||
|
@ -2013,6 +2065,19 @@ config MIPS_MT_FPAFF
|
||||||
default y
|
default y
|
||||||
depends on MIPS_MT_SMP
|
depends on MIPS_MT_SMP
|
||||||
|
|
||||||
|
config MIPSR2_TO_R6_EMULATOR
|
||||||
|
bool "MIPS R2-to-R6 emulator"
|
||||||
|
depends on CPU_MIPSR6 && !SMP
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Choose this option if you want to run non-R6 MIPS userland code.
|
||||||
|
Even if you say 'Y' here, the emulator will still be disabled by
|
||||||
|
default. You can enable it using the 'mipsr2emul' kernel option.
|
||||||
|
The only reason this is a build-time option is to save ~14K from the
|
||||||
|
final kernel image.
|
||||||
|
comment "MIPS R2-to-R6 emulator is only available for UP kernels"
|
||||||
|
depends on SMP && CPU_MIPSR6
|
||||||
|
|
||||||
config MIPS_VPE_LOADER
|
config MIPS_VPE_LOADER
|
||||||
bool "VPE loader support."
|
bool "VPE loader support."
|
||||||
depends on SYS_SUPPORTS_MULTITHREADING && MODULES
|
depends on SYS_SUPPORTS_MULTITHREADING && MODULES
|
||||||
|
@ -2148,7 +2213,7 @@ config CPU_HAS_SMARTMIPS
|
||||||
here.
|
here.
|
||||||
|
|
||||||
config CPU_MICROMIPS
|
config CPU_MICROMIPS
|
||||||
depends on 32BIT && SYS_SUPPORTS_MICROMIPS
|
depends on 32BIT && SYS_SUPPORTS_MICROMIPS && !CPU_MIPSR6
|
||||||
bool "microMIPS"
|
bool "microMIPS"
|
||||||
help
|
help
|
||||||
When this option is enabled the kernel will be built using the
|
When this option is enabled the kernel will be built using the
|
||||||
|
|
|
@ -122,17 +122,4 @@ config SPINLOCK_TEST
|
||||||
help
|
help
|
||||||
Add several files to the debugfs to test spinlock speed.
|
Add several files to the debugfs to test spinlock speed.
|
||||||
|
|
||||||
config FP32XX_HYBRID_FPRS
|
|
||||||
bool "Run FP32 & FPXX code with hybrid FPRs"
|
|
||||||
depends on MIPS_O32_FP64_SUPPORT
|
|
||||||
help
|
|
||||||
The hybrid FPR scheme is normally used only when a program needs to
|
|
||||||
execute a mix of FP32 & FP64A code, since the trapping & emulation
|
|
||||||
that it entails is expensive. When enabled, this option will lead
|
|
||||||
to the kernel running programs which use the FP32 & FPXX FP ABIs
|
|
||||||
using the hybrid FPR scheme, which can be useful for debugging
|
|
||||||
purposes.
|
|
||||||
|
|
||||||
If unsure, say N.
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -122,26 +122,8 @@ predef-le += -DMIPSEL -D_MIPSEL -D__MIPSEL -D__MIPSEL__
|
||||||
cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be))
|
cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be))
|
||||||
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le))
|
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le))
|
||||||
|
|
||||||
# For smartmips configurations, there are hundreds of warnings due to ISA overrides
|
|
||||||
# in assembly and header files. smartmips is only supported for MIPS32r1 onwards
|
|
||||||
# and there is no support for 64-bit. Various '.set mips2' or '.set mips3' or
|
|
||||||
# similar directives in the kernel will spam the build logs with the following warnings:
|
|
||||||
# Warning: the `smartmips' extension requires MIPS32 revision 1 or greater
|
|
||||||
# or
|
|
||||||
# Warning: the 64-bit MIPS architecture does not support the `smartmips' extension
|
|
||||||
# Pass -Wa,--no-warn to disable all assembler warnings until the kernel code has
|
|
||||||
# been fixed properly.
|
|
||||||
cflags-$(CONFIG_CPU_HAS_SMARTMIPS) += $(call cc-option,-msmartmips) -Wa,--no-warn
|
|
||||||
cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips)
|
|
||||||
|
|
||||||
cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \
|
cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \
|
||||||
-fno-omit-frame-pointer
|
-fno-omit-frame-pointer
|
||||||
|
|
||||||
ifeq ($(CONFIG_CPU_HAS_MSA),y)
|
|
||||||
toolchain-msa := $(call cc-option-yn,-mhard-float -mfp64 -Wa$(comma)-mmsa)
|
|
||||||
cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA
|
|
||||||
endif
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# CPU-dependent compiler/assembler options for optimization.
|
# CPU-dependent compiler/assembler options for optimization.
|
||||||
#
|
#
|
||||||
|
@ -156,10 +138,12 @@ cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS
|
||||||
-Wa,-mips32 -Wa,--trap
|
-Wa,-mips32 -Wa,--trap
|
||||||
cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
|
cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
|
||||||
-Wa,-mips32r2 -Wa,--trap
|
-Wa,-mips32r2 -Wa,--trap
|
||||||
|
cflags-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,--trap
|
||||||
cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
|
cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
|
||||||
-Wa,-mips64 -Wa,--trap
|
-Wa,-mips64 -Wa,--trap
|
||||||
cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
|
cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
|
||||||
-Wa,-mips64r2 -Wa,--trap
|
-Wa,-mips64r2 -Wa,--trap
|
||||||
|
cflags-$(CONFIG_CPU_MIPS64_R6) += -march=mips64r6 -Wa,--trap
|
||||||
cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap
|
cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap
|
||||||
cflags-$(CONFIG_CPU_R5432) += $(call cc-option,-march=r5400,-march=r5000) \
|
cflags-$(CONFIG_CPU_R5432) += $(call cc-option,-march=r5400,-march=r5000) \
|
||||||
-Wa,--trap
|
-Wa,--trap
|
||||||
|
@ -182,6 +166,16 @@ cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
|
||||||
endif
|
endif
|
||||||
cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1
|
cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1
|
||||||
cflags-$(CONFIG_CPU_BMIPS) += -march=mips32 -Wa,-mips32 -Wa,--trap
|
cflags-$(CONFIG_CPU_BMIPS) += -march=mips32 -Wa,-mips32 -Wa,--trap
|
||||||
|
#
|
||||||
|
# binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a
|
||||||
|
# as MIPS64 R1; older versions as just R1. This leaves the possibility open
|
||||||
|
# that GCC might generate R2 code for -march=loongson3a which then is rejected
|
||||||
|
# by GAS. The cc-option can't probe for this behaviour so -march=loongson3a
|
||||||
|
# can't easily be used safely within the kbuild framework.
|
||||||
|
#
|
||||||
|
cflags-$(CONFIG_CPU_LOONGSON3) += \
|
||||||
|
$(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
|
||||||
|
-Wa,-mips64r2 -Wa,--trap
|
||||||
|
|
||||||
cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
|
cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
|
||||||
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
|
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
|
||||||
|
@ -194,6 +188,23 @@ KBUILD_CFLAGS_MODULE += -msb1-pass1-workarounds
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# For smartmips configurations, there are hundreds of warnings due to ISA overrides
|
||||||
|
# in assembly and header files. smartmips is only supported for MIPS32r1 onwards
|
||||||
|
# and there is no support for 64-bit. Various '.set mips2' or '.set mips3' or
|
||||||
|
# similar directives in the kernel will spam the build logs with the following warnings:
|
||||||
|
# Warning: the `smartmips' extension requires MIPS32 revision 1 or greater
|
||||||
|
# or
|
||||||
|
# Warning: the 64-bit MIPS architecture does not support the `smartmips' extension
|
||||||
|
# Pass -Wa,--no-warn to disable all assembler warnings until the kernel code has
|
||||||
|
# been fixed properly.
|
||||||
|
mips-cflags := "$(cflags-y)"
|
||||||
|
cflags-$(CONFIG_CPU_HAS_SMARTMIPS) += $(call cc-option,$(mips-cflags),-msmartmips) -Wa,--no-warn
|
||||||
|
cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,$(mips-cflags),-mmicromips)
|
||||||
|
ifeq ($(CONFIG_CPU_HAS_MSA),y)
|
||||||
|
toolchain-msa := $(call cc-option-yn,-$(mips-cflags),mhard-float -mfp64 -Wa$(comma)-mmsa)
|
||||||
|
cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA
|
||||||
|
endif
|
||||||
|
|
||||||
#
|
#
|
||||||
# Firmware support
|
# Firmware support
|
||||||
#
|
#
|
||||||
|
@ -287,7 +298,11 @@ boot-y += vmlinux.ecoff
|
||||||
boot-y += vmlinux.srec
|
boot-y += vmlinux.srec
|
||||||
ifeq ($(shell expr $(load-y) \< 0xffffffff80000000 2> /dev/null), 0)
|
ifeq ($(shell expr $(load-y) \< 0xffffffff80000000 2> /dev/null), 0)
|
||||||
boot-y += uImage
|
boot-y += uImage
|
||||||
|
boot-y += uImage.bin
|
||||||
|
boot-y += uImage.bz2
|
||||||
boot-y += uImage.gz
|
boot-y += uImage.gz
|
||||||
|
boot-y += uImage.lzma
|
||||||
|
boot-y += uImage.lzo
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# compressed boot image targets (arch/mips/boot/compressed/)
|
# compressed boot image targets (arch/mips/boot/compressed/)
|
||||||
|
@ -386,7 +401,11 @@ define archhelp
|
||||||
echo ' vmlinuz.bin - Raw binary zboot image'
|
echo ' vmlinuz.bin - Raw binary zboot image'
|
||||||
echo ' vmlinuz.srec - SREC zboot image'
|
echo ' vmlinuz.srec - SREC zboot image'
|
||||||
echo ' uImage - U-Boot image'
|
echo ' uImage - U-Boot image'
|
||||||
|
echo ' uImage.bin - U-Boot image (uncompressed)'
|
||||||
|
echo ' uImage.bz2 - U-Boot image (bz2)'
|
||||||
echo ' uImage.gz - U-Boot image (gzip)'
|
echo ' uImage.gz - U-Boot image (gzip)'
|
||||||
|
echo ' uImage.lzma - U-Boot image (lzma)'
|
||||||
|
echo ' uImage.lzo - U-Boot image (lzo)'
|
||||||
echo ' dtbs - Device-tree blobs for enabled boards'
|
echo ' dtbs - Device-tree blobs for enabled boards'
|
||||||
echo
|
echo
|
||||||
echo ' These will be default as appropriate for a configured platform.'
|
echo ' These will be default as appropriate for a configured platform.'
|
||||||
|
|
|
@ -127,12 +127,20 @@ static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
|
||||||
t = 396000000;
|
t = 396000000;
|
||||||
else {
|
else {
|
||||||
t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
|
t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
|
||||||
|
if (alchemy_get_cputype() < ALCHEMY_CPU_AU1300)
|
||||||
|
t &= 0x3f;
|
||||||
t *= parent_rate;
|
t *= parent_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init alchemy_set_lpj(void)
|
||||||
|
{
|
||||||
|
preset_lpj = alchemy_clk_cpu_recalc(NULL, ALCHEMY_ROOTCLK_RATE);
|
||||||
|
preset_lpj /= 2 * HZ;
|
||||||
|
}
|
||||||
|
|
||||||
static struct clk_ops alchemy_clkops_cpu = {
|
static struct clk_ops alchemy_clkops_cpu = {
|
||||||
.recalc_rate = alchemy_clk_cpu_recalc,
|
.recalc_rate = alchemy_clk_cpu_recalc,
|
||||||
};
|
};
|
||||||
|
@ -315,17 +323,26 @@ static struct clk __init *alchemy_clk_setup_mem(const char *pn, int ct)
|
||||||
|
|
||||||
/* lrclk: external synchronous static bus clock ***********************/
|
/* lrclk: external synchronous static bus clock ***********************/
|
||||||
|
|
||||||
static struct clk __init *alchemy_clk_setup_lrclk(const char *pn)
|
static struct clk __init *alchemy_clk_setup_lrclk(const char *pn, int t)
|
||||||
{
|
{
|
||||||
/* MEM_STCFG0[15:13] = divisor.
|
/* Au1000, Au1500: MEM_STCFG0[11]: If bit is set, lrclk=pclk/5,
|
||||||
|
* otherwise lrclk=pclk/4.
|
||||||
|
* All other variants: MEM_STCFG0[15:13] = divisor.
|
||||||
* L/RCLK = periph_clk / (divisor + 1)
|
* L/RCLK = periph_clk / (divisor + 1)
|
||||||
* On Au1000, Au1500, Au1100 it's called LCLK,
|
* On Au1000, Au1500, Au1100 it's called LCLK,
|
||||||
* on later models it's called RCLK, but it's the same thing.
|
* on later models it's called RCLK, but it's the same thing.
|
||||||
*/
|
*/
|
||||||
struct clk *c;
|
struct clk *c;
|
||||||
unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0) >> 13;
|
unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0);
|
||||||
|
|
||||||
v = (v & 7) + 1;
|
switch (t) {
|
||||||
|
case ALCHEMY_CPU_AU1000:
|
||||||
|
case ALCHEMY_CPU_AU1500:
|
||||||
|
v = 4 + ((v >> 11) & 1);
|
||||||
|
break;
|
||||||
|
default: /* all other models */
|
||||||
|
v = ((v >> 13) & 7) + 1;
|
||||||
|
}
|
||||||
c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
|
c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
|
||||||
pn, 0, 1, v);
|
pn, 0, 1, v);
|
||||||
if (!IS_ERR(c))
|
if (!IS_ERR(c))
|
||||||
|
@ -1066,7 +1083,7 @@ static int __init alchemy_clk_init(void)
|
||||||
ERRCK(c)
|
ERRCK(c)
|
||||||
|
|
||||||
/* L/RCLK: external static bus clock for synchronous mode */
|
/* L/RCLK: external static bus clock for synchronous mode */
|
||||||
c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK);
|
c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK, ctype);
|
||||||
ERRCK(c)
|
ERRCK(c)
|
||||||
|
|
||||||
/* Frequency dividers 0-5 */
|
/* Frequency dividers 0-5 */
|
||||||
|
|
|
@ -34,10 +34,12 @@
|
||||||
#include <au1000.h>
|
#include <au1000.h>
|
||||||
|
|
||||||
extern void __init board_setup(void);
|
extern void __init board_setup(void);
|
||||||
extern void set_cpuspec(void);
|
extern void __init alchemy_set_lpj(void);
|
||||||
|
|
||||||
void __init plat_mem_setup(void)
|
void __init plat_mem_setup(void)
|
||||||
{
|
{
|
||||||
|
alchemy_set_lpj();
|
||||||
|
|
||||||
if (au1xxx_cpu_needs_config_od())
|
if (au1xxx_cpu_needs_config_od())
|
||||||
/* Various early Au1xx0 errata corrected by this */
|
/* Various early Au1xx0 errata corrected by this */
|
||||||
set_c0_config(1 << 19); /* Set Config[OD] */
|
set_c0_config(1 << 19); /* Set Config[OD] */
|
||||||
|
|
|
@ -180,7 +180,7 @@ static int __init intc_of_init(struct device_node *node,
|
||||||
|
|
||||||
static struct of_device_id of_irq_ids[] __initdata = {
|
static struct of_device_id of_irq_ids[] __initdata = {
|
||||||
{ .compatible = "mti,cpu-interrupt-controller",
|
{ .compatible = "mti,cpu-interrupt-controller",
|
||||||
.data = mips_cpu_intc_init },
|
.data = mips_cpu_irq_of_init },
|
||||||
{ .compatible = "brcm,bcm3384-intc",
|
{ .compatible = "brcm,bcm3384-intc",
|
||||||
.data = intc_of_init },
|
.data = intc_of_init },
|
||||||
{},
|
{},
|
||||||
|
|
|
@ -23,6 +23,12 @@ strip-flags := $(addprefix --remove-section=,$(drop-sections))
|
||||||
|
|
||||||
hostprogs-y := elf2ecoff
|
hostprogs-y := elf2ecoff
|
||||||
|
|
||||||
|
suffix-y := bin
|
||||||
|
suffix-$(CONFIG_KERNEL_BZIP2) := bz2
|
||||||
|
suffix-$(CONFIG_KERNEL_GZIP) := gz
|
||||||
|
suffix-$(CONFIG_KERNEL_LZMA) := lzma
|
||||||
|
suffix-$(CONFIG_KERNEL_LZO) := lzo
|
||||||
|
|
||||||
targets := vmlinux.ecoff
|
targets := vmlinux.ecoff
|
||||||
quiet_cmd_ecoff = ECOFF $@
|
quiet_cmd_ecoff = ECOFF $@
|
||||||
cmd_ecoff = $(obj)/elf2ecoff $(VMLINUX) $@ $(e2eflag)
|
cmd_ecoff = $(obj)/elf2ecoff $(VMLINUX) $@ $(e2eflag)
|
||||||
|
@ -44,14 +50,53 @@ $(obj)/vmlinux.srec: $(VMLINUX) FORCE
|
||||||
UIMAGE_LOADADDR = $(VMLINUX_LOAD_ADDRESS)
|
UIMAGE_LOADADDR = $(VMLINUX_LOAD_ADDRESS)
|
||||||
UIMAGE_ENTRYADDR = $(VMLINUX_ENTRY_ADDRESS)
|
UIMAGE_ENTRYADDR = $(VMLINUX_ENTRY_ADDRESS)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Compressed vmlinux images
|
||||||
|
#
|
||||||
|
|
||||||
|
extra-y += vmlinux.bin.bz2
|
||||||
|
extra-y += vmlinux.bin.gz
|
||||||
|
extra-y += vmlinux.bin.lzma
|
||||||
|
extra-y += vmlinux.bin.lzo
|
||||||
|
|
||||||
|
$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
|
||||||
|
$(call if_changed,bzip2)
|
||||||
|
|
||||||
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
|
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
|
||||||
$(call if_changed,gzip)
|
$(call if_changed,gzip)
|
||||||
|
|
||||||
|
$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
|
||||||
|
$(call if_changed,lzma)
|
||||||
|
|
||||||
|
$(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.bin FORCE
|
||||||
|
$(call if_changed,lzo)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Compressed u-boot images
|
||||||
|
#
|
||||||
|
|
||||||
|
targets += uImage
|
||||||
|
targets += uImage.bin
|
||||||
|
targets += uImage.bz2
|
||||||
targets += uImage.gz
|
targets += uImage.gz
|
||||||
|
targets += uImage.lzma
|
||||||
|
targets += uImage.lzo
|
||||||
|
|
||||||
|
$(obj)/uImage.bin: $(obj)/vmlinux.bin FORCE
|
||||||
|
$(call if_changed,uimage,none)
|
||||||
|
|
||||||
|
$(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2 FORCE
|
||||||
|
$(call if_changed,uimage,bzip2)
|
||||||
|
|
||||||
$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz FORCE
|
$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz FORCE
|
||||||
$(call if_changed,uimage,gzip)
|
$(call if_changed,uimage,gzip)
|
||||||
|
|
||||||
targets += uImage
|
$(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma FORCE
|
||||||
$(obj)/uImage: $(obj)/uImage.gz FORCE
|
$(call if_changed,uimage,lzma)
|
||||||
|
|
||||||
|
$(obj)/uImage.lzo: $(obj)/vmlinux.bin.lzo FORCE
|
||||||
|
$(call if_changed,uimage,lzo)
|
||||||
|
|
||||||
|
$(obj)/uImage: $(obj)/uImage.$(suffix-y)
|
||||||
@ln -sf $(notdir $<) $@
|
@ln -sf $(notdir $<) $@
|
||||||
@echo ' Image $@ is ready'
|
@echo ' Image $@ is ready'
|
||||||
|
|
|
@ -268,7 +268,6 @@ int main(int argc, char *argv[])
|
||||||
Elf32_Ehdr ex;
|
Elf32_Ehdr ex;
|
||||||
Elf32_Phdr *ph;
|
Elf32_Phdr *ph;
|
||||||
Elf32_Shdr *sh;
|
Elf32_Shdr *sh;
|
||||||
char *shstrtab;
|
|
||||||
int i, pad;
|
int i, pad;
|
||||||
struct sect text, data, bss;
|
struct sect text, data, bss;
|
||||||
struct filehdr efh;
|
struct filehdr efh;
|
||||||
|
@ -336,9 +335,6 @@ int main(int argc, char *argv[])
|
||||||
"sh");
|
"sh");
|
||||||
if (must_convert_endian)
|
if (must_convert_endian)
|
||||||
convert_elf_shdrs(sh, ex.e_shnum);
|
convert_elf_shdrs(sh, ex.e_shnum);
|
||||||
/* Read in the section string table. */
|
|
||||||
shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset,
|
|
||||||
sh[ex.e_shstrndx].sh_size, "shstrtab");
|
|
||||||
|
|
||||||
/* Figure out if we can cram the program header into an ECOFF
|
/* Figure out if we can cram the program header into an ECOFF
|
||||||
header... Basically, we can't handle anything but loadable
|
header... Basically, we can't handle anything but loadable
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include <asm/octeon/octeon.h>
|
#include <asm/octeon/octeon.h>
|
||||||
#include <asm/octeon/cvmx-ipd-defs.h>
|
#include <asm/octeon/cvmx-ipd-defs.h>
|
||||||
#include <asm/octeon/cvmx-mio-defs.h>
|
#include <asm/octeon/cvmx-mio-defs.h>
|
||||||
|
#include <asm/octeon/cvmx-rst-defs.h>
|
||||||
|
|
||||||
static u64 f;
|
static u64 f;
|
||||||
static u64 rdiv;
|
static u64 rdiv;
|
||||||
|
@ -39,11 +39,20 @@ void __init octeon_setup_delays(void)
|
||||||
|
|
||||||
if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
|
if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
|
||||||
union cvmx_mio_rst_boot rst_boot;
|
union cvmx_mio_rst_boot rst_boot;
|
||||||
|
|
||||||
rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
|
rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
|
||||||
rdiv = rst_boot.s.c_mul; /* CPU clock */
|
rdiv = rst_boot.s.c_mul; /* CPU clock */
|
||||||
sdiv = rst_boot.s.pnr_mul; /* I/O clock */
|
sdiv = rst_boot.s.pnr_mul; /* I/O clock */
|
||||||
f = (0x8000000000000000ull / sdiv) * 2;
|
f = (0x8000000000000000ull / sdiv) * 2;
|
||||||
|
} else if (current_cpu_type() == CPU_CAVIUM_OCTEON3) {
|
||||||
|
union cvmx_rst_boot rst_boot;
|
||||||
|
|
||||||
|
rst_boot.u64 = cvmx_read_csr(CVMX_RST_BOOT);
|
||||||
|
rdiv = rst_boot.s.c_mul; /* CPU clock */
|
||||||
|
sdiv = rst_boot.s.pnr_mul; /* I/O clock */
|
||||||
|
f = (0x8000000000000000ull / sdiv) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -276,7 +276,7 @@ void __init plat_swiotlb_setup(void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* These addresses map low for PCI. */
|
/* These addresses map low for PCI. */
|
||||||
if (e->addr > 0x410000000ull && !OCTEON_IS_MODEL(OCTEON_CN6XXX))
|
if (e->addr > 0x410000000ull && !OCTEON_IS_OCTEON2())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
addr_size += e->size;
|
addr_size += e->size;
|
||||||
|
@ -308,7 +308,7 @@ void __init plat_swiotlb_setup(void)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_USB_OCTEON_OHCI
|
#ifdef CONFIG_USB_OCTEON_OHCI
|
||||||
/* OCTEON II ohci is only 32-bit. */
|
/* OCTEON II ohci is only 32-bit. */
|
||||||
if (OCTEON_IS_MODEL(OCTEON_CN6XXX) && max_addr >= 0x100000000ul)
|
if (OCTEON_IS_OCTEON2() && max_addr >= 0x100000000ul)
|
||||||
swiotlbsize = 64 * (1<<20);
|
swiotlbsize = 64 * (1<<20);
|
||||||
#endif
|
#endif
|
||||||
swiotlb_nslabs = swiotlbsize >> IO_TLB_SHIFT;
|
swiotlb_nslabs = swiotlbsize >> IO_TLB_SHIFT;
|
||||||
|
|
|
@ -767,7 +767,7 @@ enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(vo
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Most boards except NIC10e use a 12MHz crystal */
|
/* Most boards except NIC10e use a 12MHz crystal */
|
||||||
if (OCTEON_IS_MODEL(OCTEON_FAM_2))
|
if (OCTEON_IS_OCTEON2())
|
||||||
return USB_CLOCK_TYPE_CRYSTAL_12;
|
return USB_CLOCK_TYPE_CRYSTAL_12;
|
||||||
return USB_CLOCK_TYPE_REF_48;
|
return USB_CLOCK_TYPE_REF_48;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -41,6 +41,7 @@
|
||||||
#include <asm/octeon/octeon.h>
|
#include <asm/octeon/octeon.h>
|
||||||
#include <asm/octeon/pci-octeon.h>
|
#include <asm/octeon/pci-octeon.h>
|
||||||
#include <asm/octeon/cvmx-mio-defs.h>
|
#include <asm/octeon/cvmx-mio-defs.h>
|
||||||
|
#include <asm/octeon/cvmx-rst-defs.h>
|
||||||
|
|
||||||
extern struct plat_smp_ops octeon_smp_ops;
|
extern struct plat_smp_ops octeon_smp_ops;
|
||||||
|
|
||||||
|
@ -579,12 +580,10 @@ void octeon_user_io_init(void)
|
||||||
/* R/W If set, CVMSEG is available for loads/stores in user
|
/* R/W If set, CVMSEG is available for loads/stores in user
|
||||||
* mode. */
|
* mode. */
|
||||||
cvmmemctl.s.cvmsegenau = 0;
|
cvmmemctl.s.cvmsegenau = 0;
|
||||||
/* R/W Size of local memory in cache blocks, 54 (6912 bytes)
|
|
||||||
* is max legal value. */
|
|
||||||
cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE;
|
|
||||||
|
|
||||||
write_c0_cvmmemctl(cvmmemctl.u64);
|
write_c0_cvmmemctl(cvmmemctl.u64);
|
||||||
|
|
||||||
|
/* Setup of CVMSEG is done in kernel-entry-init.h */
|
||||||
if (smp_processor_id() == 0)
|
if (smp_processor_id() == 0)
|
||||||
pr_notice("CVMSEG size: %d cache lines (%d bytes)\n",
|
pr_notice("CVMSEG size: %d cache lines (%d bytes)\n",
|
||||||
CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
|
CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
|
||||||
|
@ -615,6 +614,7 @@ void __init prom_init(void)
|
||||||
const char *arg;
|
const char *arg;
|
||||||
char *p;
|
char *p;
|
||||||
int i;
|
int i;
|
||||||
|
u64 t;
|
||||||
int argc;
|
int argc;
|
||||||
#ifdef CONFIG_CAVIUM_RESERVE32
|
#ifdef CONFIG_CAVIUM_RESERVE32
|
||||||
int64_t addr = -1;
|
int64_t addr = -1;
|
||||||
|
@ -654,15 +654,56 @@ void __init prom_init(void)
|
||||||
sysinfo->dfa_ref_clock_hz = octeon_bootinfo->dfa_ref_clock_hz;
|
sysinfo->dfa_ref_clock_hz = octeon_bootinfo->dfa_ref_clock_hz;
|
||||||
sysinfo->bootloader_config_flags = octeon_bootinfo->config_flags;
|
sysinfo->bootloader_config_flags = octeon_bootinfo->config_flags;
|
||||||
|
|
||||||
if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
|
if (OCTEON_IS_OCTEON2()) {
|
||||||
/* I/O clock runs at a different rate than the CPU. */
|
/* I/O clock runs at a different rate than the CPU. */
|
||||||
union cvmx_mio_rst_boot rst_boot;
|
union cvmx_mio_rst_boot rst_boot;
|
||||||
rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
|
rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
|
||||||
octeon_io_clock_rate = 50000000 * rst_boot.s.pnr_mul;
|
octeon_io_clock_rate = 50000000 * rst_boot.s.pnr_mul;
|
||||||
|
} else if (OCTEON_IS_OCTEON3()) {
|
||||||
|
/* I/O clock runs at a different rate than the CPU. */
|
||||||
|
union cvmx_rst_boot rst_boot;
|
||||||
|
rst_boot.u64 = cvmx_read_csr(CVMX_RST_BOOT);
|
||||||
|
octeon_io_clock_rate = 50000000 * rst_boot.s.pnr_mul;
|
||||||
} else {
|
} else {
|
||||||
octeon_io_clock_rate = sysinfo->cpu_clock_hz;
|
octeon_io_clock_rate = sysinfo->cpu_clock_hz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t = read_c0_cvmctl();
|
||||||
|
if ((t & (1ull << 27)) == 0) {
|
||||||
|
/*
|
||||||
|
* Setup the multiplier save/restore code if
|
||||||
|
* CvmCtl[NOMUL] clear.
|
||||||
|
*/
|
||||||
|
void *save;
|
||||||
|
void *save_end;
|
||||||
|
void *restore;
|
||||||
|
void *restore_end;
|
||||||
|
int save_len;
|
||||||
|
int restore_len;
|
||||||
|
int save_max = (char *)octeon_mult_save_end -
|
||||||
|
(char *)octeon_mult_save;
|
||||||
|
int restore_max = (char *)octeon_mult_restore_end -
|
||||||
|
(char *)octeon_mult_restore;
|
||||||
|
if (current_cpu_data.cputype == CPU_CAVIUM_OCTEON3) {
|
||||||
|
save = octeon_mult_save3;
|
||||||
|
save_end = octeon_mult_save3_end;
|
||||||
|
restore = octeon_mult_restore3;
|
||||||
|
restore_end = octeon_mult_restore3_end;
|
||||||
|
} else {
|
||||||
|
save = octeon_mult_save2;
|
||||||
|
save_end = octeon_mult_save2_end;
|
||||||
|
restore = octeon_mult_restore2;
|
||||||
|
restore_end = octeon_mult_restore2_end;
|
||||||
|
}
|
||||||
|
save_len = (char *)save_end - (char *)save;
|
||||||
|
restore_len = (char *)restore_end - (char *)restore;
|
||||||
|
if (!WARN_ON(save_len > save_max ||
|
||||||
|
restore_len > restore_max)) {
|
||||||
|
memcpy(octeon_mult_save, save, save_len);
|
||||||
|
memcpy(octeon_mult_restore, restore, restore_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only enable the LED controller if we're running on a CN38XX, CN58XX,
|
* Only enable the LED controller if we're running on a CN38XX, CN58XX,
|
||||||
* or CN56XX. The CN30XX and CN31XX don't have an LED controller.
|
* or CN56XX. The CN30XX and CN31XX don't have an LED controller.
|
||||||
|
@ -1004,7 +1045,7 @@ EXPORT_SYMBOL(prom_putchar);
|
||||||
|
|
||||||
void prom_free_prom_memory(void)
|
void prom_free_prom_memory(void)
|
||||||
{
|
{
|
||||||
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) {
|
if (CAVIUM_OCTEON_DCACHE_PREFETCH_WAR) {
|
||||||
/* Check for presence of Core-14449 fix. */
|
/* Check for presence of Core-14449 fix. */
|
||||||
u32 insn;
|
u32 insn;
|
||||||
u32 *foo;
|
u32 *foo;
|
||||||
|
@ -1026,8 +1067,9 @@ void prom_free_prom_memory(void)
|
||||||
panic("No PREF instruction at Core-14449 probe point.");
|
panic("No PREF instruction at Core-14449 probe point.");
|
||||||
|
|
||||||
if (((insn >> 16) & 0x1f) != 28)
|
if (((insn >> 16) & 0x1f) != 28)
|
||||||
panic("Core-14449 WAR not in place (%04x).\n"
|
panic("OCTEON II DCache prefetch workaround not in place (%04x).\n"
|
||||||
"Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).", insn);
|
"Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).",
|
||||||
|
insn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
CONFIG_MIPS_MALTA=y
|
||||||
|
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||||
|
CONFIG_CPU_MIPS32_R6=y
|
||||||
|
CONFIG_PAGE_SIZE_16KB=y
|
||||||
|
CONFIG_HZ_100=y
|
||||||
|
CONFIG_SYSVIPC=y
|
||||||
|
CONFIG_POSIX_MQUEUE=y
|
||||||
|
CONFIG_AUDIT=y
|
||||||
|
CONFIG_NO_HZ=y
|
||||||
|
CONFIG_IKCONFIG=y
|
||||||
|
CONFIG_IKCONFIG_PROC=y
|
||||||
|
CONFIG_LOG_BUF_SHIFT=15
|
||||||
|
CONFIG_SYSCTL_SYSCALL=y
|
||||||
|
CONFIG_EMBEDDED=y
|
||||||
|
CONFIG_SLAB=y
|
||||||
|
CONFIG_MODULES=y
|
||||||
|
CONFIG_MODULE_UNLOAD=y
|
||||||
|
CONFIG_MODVERSIONS=y
|
||||||
|
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||||
|
# CONFIG_BLK_DEV_BSG is not set
|
||||||
|
CONFIG_PCI=y
|
||||||
|
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||||
|
CONFIG_NET=y
|
||||||
|
CONFIG_PACKET=y
|
||||||
|
CONFIG_UNIX=y
|
||||||
|
CONFIG_XFRM_USER=m
|
||||||
|
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_NET_IPIP=m
|
||||||
|
CONFIG_IP_MROUTE=y
|
||||||
|
CONFIG_IP_PIMSM_V1=y
|
||||||
|
CONFIG_IP_PIMSM_V2=y
|
||||||
|
CONFIG_SYN_COOKIES=y
|
||||||
|
CONFIG_INET_AH=m
|
||||||
|
CONFIG_INET_ESP=m
|
||||||
|
CONFIG_INET_IPCOMP=m
|
||||||
|
# CONFIG_INET_LRO is not set
|
||||||
|
CONFIG_INET6_AH=m
|
||||||
|
CONFIG_INET6_ESP=m
|
||||||
|
CONFIG_INET6_IPCOMP=m
|
||||||
|
CONFIG_IPV6_TUNNEL=m
|
||||||
|
CONFIG_BRIDGE=m
|
||||||
|
CONFIG_VLAN_8021Q=m
|
||||||
|
CONFIG_ATALK=m
|
||||||
|
CONFIG_DEV_APPLETALK=m
|
||||||
|
CONFIG_IPDDP=m
|
||||||
|
CONFIG_IPDDP_ENCAP=y
|
||||||
|
CONFIG_NET_SCHED=y
|
||||||
|
CONFIG_NET_SCH_CBQ=m
|
||||||
|
CONFIG_NET_SCH_HTB=m
|
||||||
|
CONFIG_NET_SCH_HFSC=m
|
||||||
|
CONFIG_NET_SCH_PRIO=m
|
||||||
|
CONFIG_NET_SCH_RED=m
|
||||||
|
CONFIG_NET_SCH_SFQ=m
|
||||||
|
CONFIG_NET_SCH_TEQL=m
|
||||||
|
CONFIG_NET_SCH_TBF=m
|
||||||
|
CONFIG_NET_SCH_GRED=m
|
||||||
|
CONFIG_NET_SCH_DSMARK=m
|
||||||
|
CONFIG_NET_SCH_NETEM=m
|
||||||
|
CONFIG_NET_SCH_INGRESS=m
|
||||||
|
CONFIG_NET_CLS_BASIC=m
|
||||||
|
CONFIG_NET_CLS_TCINDEX=m
|
||||||
|
CONFIG_NET_CLS_ROUTE4=m
|
||||||
|
CONFIG_NET_CLS_FW=m
|
||||||
|
CONFIG_NET_CLS_U32=m
|
||||||
|
CONFIG_NET_CLS_RSVP=m
|
||||||
|
CONFIG_NET_CLS_RSVP6=m
|
||||||
|
CONFIG_NET_CLS_ACT=y
|
||||||
|
CONFIG_NET_ACT_POLICE=y
|
||||||
|
CONFIG_NET_CLS_IND=y
|
||||||
|
# CONFIG_WIRELESS is not set
|
||||||
|
CONFIG_DEVTMPFS=y
|
||||||
|
CONFIG_BLK_DEV_LOOP=y
|
||||||
|
CONFIG_BLK_DEV_CRYPTOLOOP=m
|
||||||
|
CONFIG_IDE=y
|
||||||
|
# CONFIG_IDE_PROC_FS is not set
|
||||||
|
# CONFIG_IDEPCI_PCIBUS_ORDER is not set
|
||||||
|
CONFIG_BLK_DEV_GENERIC=y
|
||||||
|
CONFIG_BLK_DEV_PIIX=y
|
||||||
|
CONFIG_SCSI=y
|
||||||
|
CONFIG_BLK_DEV_SD=y
|
||||||
|
CONFIG_CHR_DEV_SG=y
|
||||||
|
# CONFIG_SCSI_LOWLEVEL is not set
|
||||||
|
CONFIG_NETDEVICES=y
|
||||||
|
# CONFIG_NET_VENDOR_3COM is not set
|
||||||
|
# CONFIG_NET_VENDOR_ADAPTEC is not set
|
||||||
|
# CONFIG_NET_VENDOR_ALTEON is not set
|
||||||
|
CONFIG_PCNET32=y
|
||||||
|
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||||
|
# CONFIG_NET_VENDOR_BROADCOM is not set
|
||||||
|
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||||
|
# CONFIG_NET_VENDOR_CHELSIO 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_EXAR is not set
|
||||||
|
# CONFIG_NET_VENDOR_HP is not set
|
||||||
|
# CONFIG_NET_VENDOR_INTEL is not set
|
||||||
|
# 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_NVIDIA is not set
|
||||||
|
# CONFIG_NET_VENDOR_OKI is not set
|
||||||
|
# CONFIG_NET_PACKET_ENGINE is not set
|
||||||
|
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||||
|
# CONFIG_NET_VENDOR_REALTEK is not set
|
||||||
|
# CONFIG_NET_VENDOR_RDC is not set
|
||||||
|
# CONFIG_NET_VENDOR_SEEQ 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_NET_VENDOR_STMICRO is not set
|
||||||
|
# CONFIG_NET_VENDOR_SUN is not set
|
||||||
|
# CONFIG_NET_VENDOR_TEHUTI is not set
|
||||||
|
# CONFIG_NET_VENDOR_TI is not set
|
||||||
|
# CONFIG_NET_VENDOR_TOSHIBA is not set
|
||||||
|
# CONFIG_NET_VENDOR_VIA is not set
|
||||||
|
# CONFIG_NET_VENDOR_WIZNET is not set
|
||||||
|
# CONFIG_WLAN is not set
|
||||||
|
# CONFIG_VT is not set
|
||||||
|
CONFIG_LEGACY_PTY_COUNT=4
|
||||||
|
CONFIG_SERIAL_8250=y
|
||||||
|
CONFIG_SERIAL_8250_CONSOLE=y
|
||||||
|
CONFIG_HW_RANDOM=y
|
||||||
|
# CONFIG_HWMON is not set
|
||||||
|
CONFIG_FB=y
|
||||||
|
CONFIG_FIRMWARE_EDID=y
|
||||||
|
CONFIG_FB_MATROX=y
|
||||||
|
CONFIG_FB_MATROX_G=y
|
||||||
|
CONFIG_USB=y
|
||||||
|
CONFIG_USB_EHCI_HCD=y
|
||||||
|
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
|
||||||
|
CONFIG_USB_UHCI_HCD=y
|
||||||
|
CONFIG_USB_STORAGE=y
|
||||||
|
CONFIG_NEW_LEDS=y
|
||||||
|
CONFIG_LEDS_CLASS=y
|
||||||
|
CONFIG_LEDS_TRIGGERS=y
|
||||||
|
CONFIG_LEDS_TRIGGER_TIMER=y
|
||||||
|
CONFIG_LEDS_TRIGGER_IDE_DISK=y
|
||||||
|
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
|
||||||
|
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
|
||||||
|
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
|
||||||
|
CONFIG_RTC_CLASS=y
|
||||||
|
CONFIG_RTC_DRV_CMOS=y
|
||||||
|
CONFIG_EXT2_FS=y
|
||||||
|
CONFIG_EXT3_FS=y
|
||||||
|
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
|
||||||
|
CONFIG_XFS_FS=y
|
||||||
|
CONFIG_XFS_QUOTA=y
|
||||||
|
CONFIG_XFS_POSIX_ACL=y
|
||||||
|
CONFIG_QUOTA=y
|
||||||
|
CONFIG_QFMT_V2=y
|
||||||
|
CONFIG_MSDOS_FS=m
|
||||||
|
CONFIG_VFAT_FS=m
|
||||||
|
CONFIG_PROC_KCORE=y
|
||||||
|
CONFIG_TMPFS=y
|
||||||
|
CONFIG_NFS_FS=y
|
||||||
|
CONFIG_ROOT_NFS=y
|
||||||
|
CONFIG_CIFS=m
|
||||||
|
CONFIG_CIFS_WEAK_PW_HASH=y
|
||||||
|
CONFIG_CIFS_XATTR=y
|
||||||
|
CONFIG_CIFS_POSIX=y
|
||||||
|
CONFIG_NLS_CODEPAGE_437=m
|
||||||
|
CONFIG_NLS_ISO8859_1=m
|
||||||
|
# CONFIG_FTRACE is not set
|
||||||
|
CONFIG_CRYPTO_NULL=m
|
||||||
|
CONFIG_CRYPTO_PCBC=m
|
||||||
|
CONFIG_CRYPTO_HMAC=y
|
||||||
|
CONFIG_CRYPTO_MICHAEL_MIC=m
|
||||||
|
CONFIG_CRYPTO_SHA512=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_SERPENT=m
|
||||||
|
CONFIG_CRYPTO_TEA=m
|
||||||
|
CONFIG_CRYPTO_TWOFISH=m
|
||||||
|
# CONFIG_CRYPTO_ANSI_CPRNG is not set
|
||||||
|
# CONFIG_CRYPTO_HW is not set
|
|
@ -9,6 +9,7 @@
|
||||||
* Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
|
* Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
|
||||||
* Copyright (C) 1999 Silicon Graphics, Inc.
|
* Copyright (C) 1999 Silicon Graphics, Inc.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/compiler.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/irqflags.h>
|
#include <linux/irqflags.h>
|
||||||
|
@ -19,50 +20,55 @@
|
||||||
#include <asm/sgialib.h>
|
#include <asm/sgialib.h>
|
||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
|
|
||||||
VOID
|
VOID __noreturn
|
||||||
ArcHalt(VOID)
|
ArcHalt(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
ARC_CALL0(halt);
|
ARC_CALL0(halt);
|
||||||
never: goto never;
|
|
||||||
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID __noreturn
|
||||||
ArcPowerDown(VOID)
|
ArcPowerDown(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
ARC_CALL0(pdown);
|
ARC_CALL0(pdown);
|
||||||
never: goto never;
|
|
||||||
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX is this a soft reset basically? XXX */
|
/* XXX is this a soft reset basically? XXX */
|
||||||
VOID
|
VOID __noreturn
|
||||||
ArcRestart(VOID)
|
ArcRestart(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
ARC_CALL0(restart);
|
ARC_CALL0(restart);
|
||||||
never: goto never;
|
|
||||||
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID __noreturn
|
||||||
ArcReboot(VOID)
|
ArcReboot(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
ARC_CALL0(reboot);
|
ARC_CALL0(reboot);
|
||||||
never: goto never;
|
|
||||||
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID __noreturn
|
||||||
ArcEnterInteractiveMode(VOID)
|
ArcEnterInteractiveMode(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
ARC_CALL0(imode);
|
ARC_CALL0(imode);
|
||||||
never: goto never;
|
|
||||||
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
LONG
|
LONG
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# MIPS headers
|
# MIPS headers
|
||||||
|
generic-(CONFIG_GENERIC_CSUM) += checksum.h
|
||||||
generic-y += cputime.h
|
generic-y += cputime.h
|
||||||
generic-y += current.h
|
generic-y += current.h
|
||||||
generic-y += dma-contiguous.h
|
generic-y += dma-contiguous.h
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include <asm/asmmacro-64.h>
|
#include <asm/asmmacro-64.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||||
.macro local_irq_enable reg=t0
|
.macro local_irq_enable reg=t0
|
||||||
ei
|
ei
|
||||||
irq_enable_hazard
|
irq_enable_hazard
|
||||||
|
@ -104,7 +104,8 @@
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro fpu_save_double thread status tmp
|
.macro fpu_save_double thread status tmp
|
||||||
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
|
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
|
||||||
|
defined(CONFIG_CPU_MIPS32_R6)
|
||||||
sll \tmp, \status, 5
|
sll \tmp, \status, 5
|
||||||
bgez \tmp, 10f
|
bgez \tmp, 10f
|
||||||
fpu_save_16odd \thread
|
fpu_save_16odd \thread
|
||||||
|
@ -160,7 +161,8 @@
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro fpu_restore_double thread status tmp
|
.macro fpu_restore_double thread status tmp
|
||||||
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
|
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
|
||||||
|
defined(CONFIG_CPU_MIPS32_R6)
|
||||||
sll \tmp, \status, 5
|
sll \tmp, \status, 5
|
||||||
bgez \tmp, 10f # 16 register mode?
|
bgez \tmp, 10f # 16 register mode?
|
||||||
|
|
||||||
|
@ -170,16 +172,16 @@
|
||||||
fpu_restore_16even \thread \tmp
|
fpu_restore_16even \thread \tmp
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||||
.macro _EXT rd, rs, p, s
|
.macro _EXT rd, rs, p, s
|
||||||
ext \rd, \rs, \p, \s
|
ext \rd, \rs, \p, \s
|
||||||
.endm
|
.endm
|
||||||
#else /* !CONFIG_CPU_MIPSR2 */
|
#else /* !CONFIG_CPU_MIPSR2 || !CONFIG_CPU_MIPSR6 */
|
||||||
.macro _EXT rd, rs, p, s
|
.macro _EXT rd, rs, p, s
|
||||||
srl \rd, \rs, \p
|
srl \rd, \rs, \p
|
||||||
andi \rd, \rd, (1 << \s) - 1
|
andi \rd, \rd, (1 << \s) - 1
|
||||||
.endm
|
.endm
|
||||||
#endif /* !CONFIG_CPU_MIPSR2 */
|
#endif /* !CONFIG_CPU_MIPSR2 || !CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Temporary until all gas have MT ASE support
|
* Temporary until all gas have MT ASE support
|
||||||
|
@ -304,7 +306,7 @@
|
||||||
.set push
|
.set push
|
||||||
.set noat
|
.set noat
|
||||||
SET_HARDFLOAT
|
SET_HARDFLOAT
|
||||||
add $1, \base, \off
|
addu $1, \base, \off
|
||||||
.word LDD_MSA_INSN | (\wd << 6)
|
.word LDD_MSA_INSN | (\wd << 6)
|
||||||
.set pop
|
.set pop
|
||||||
.endm
|
.endm
|
||||||
|
@ -313,7 +315,7 @@
|
||||||
.set push
|
.set push
|
||||||
.set noat
|
.set noat
|
||||||
SET_HARDFLOAT
|
SET_HARDFLOAT
|
||||||
add $1, \base, \off
|
addu $1, \base, \off
|
||||||
.word STD_MSA_INSN | (\wd << 6)
|
.word STD_MSA_INSN | (\wd << 6)
|
||||||
.set pop
|
.set pop
|
||||||
.endm
|
.endm
|
||||||
|
|
|
@ -54,19 +54,19 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \
|
||||||
" sc %0, %1 \n" \
|
" sc %0, %1 \n" \
|
||||||
" beqzl %0, 1b \n" \
|
" beqzl %0, 1b \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "Ir" (i)); \
|
: "Ir" (i)); \
|
||||||
} else if (kernel_uses_llsc) { \
|
} else if (kernel_uses_llsc) { \
|
||||||
int temp; \
|
int temp; \
|
||||||
\
|
\
|
||||||
do { \
|
do { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_LEVEL" \n" \
|
||||||
" ll %0, %1 # atomic_" #op "\n" \
|
" ll %0, %1 # atomic_" #op "\n" \
|
||||||
" " #asm_op " %0, %2 \n" \
|
" " #asm_op " %0, %2 \n" \
|
||||||
" sc %0, %1 \n" \
|
" sc %0, %1 \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "Ir" (i)); \
|
: "Ir" (i)); \
|
||||||
} while (unlikely(!temp)); \
|
} while (unlikely(!temp)); \
|
||||||
} else { \
|
} else { \
|
||||||
|
@ -97,20 +97,20 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v) \
|
||||||
" " #asm_op " %0, %1, %3 \n" \
|
" " #asm_op " %0, %1, %3 \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
: "=&r" (result), "=&r" (temp), \
|
: "=&r" (result), "=&r" (temp), \
|
||||||
"+" GCC_OFF12_ASM() (v->counter) \
|
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "Ir" (i)); \
|
: "Ir" (i)); \
|
||||||
} else if (kernel_uses_llsc) { \
|
} else if (kernel_uses_llsc) { \
|
||||||
int temp; \
|
int temp; \
|
||||||
\
|
\
|
||||||
do { \
|
do { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_LEVEL" \n" \
|
||||||
" ll %1, %2 # atomic_" #op "_return \n" \
|
" ll %1, %2 # atomic_" #op "_return \n" \
|
||||||
" " #asm_op " %0, %1, %3 \n" \
|
" " #asm_op " %0, %1, %3 \n" \
|
||||||
" sc %0, %2 \n" \
|
" sc %0, %2 \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
: "=&r" (result), "=&r" (temp), \
|
: "=&r" (result), "=&r" (temp), \
|
||||||
"+" GCC_OFF12_ASM() (v->counter) \
|
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "Ir" (i)); \
|
: "Ir" (i)); \
|
||||||
} while (unlikely(!result)); \
|
} while (unlikely(!result)); \
|
||||||
\
|
\
|
||||||
|
@ -171,14 +171,14 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
|
||||||
"1: \n"
|
"1: \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (result), "=&r" (temp),
|
: "=&r" (result), "=&r" (temp),
|
||||||
"+" GCC_OFF12_ASM() (v->counter)
|
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||||
: "Ir" (i), GCC_OFF12_ASM() (v->counter)
|
: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
int temp;
|
int temp;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_LEVEL" \n"
|
||||||
"1: ll %1, %2 # atomic_sub_if_positive\n"
|
"1: ll %1, %2 # atomic_sub_if_positive\n"
|
||||||
" subu %0, %1, %3 \n"
|
" subu %0, %1, %3 \n"
|
||||||
" bltz %0, 1f \n"
|
" bltz %0, 1f \n"
|
||||||
|
@ -190,7 +190,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
|
||||||
"1: \n"
|
"1: \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (result), "=&r" (temp),
|
: "=&r" (result), "=&r" (temp),
|
||||||
"+" GCC_OFF12_ASM() (v->counter)
|
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||||
: "Ir" (i));
|
: "Ir" (i));
|
||||||
} else {
|
} else {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -333,19 +333,19 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v) \
|
||||||
" scd %0, %1 \n" \
|
" scd %0, %1 \n" \
|
||||||
" beqzl %0, 1b \n" \
|
" beqzl %0, 1b \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "Ir" (i)); \
|
: "Ir" (i)); \
|
||||||
} else if (kernel_uses_llsc) { \
|
} else if (kernel_uses_llsc) { \
|
||||||
long temp; \
|
long temp; \
|
||||||
\
|
\
|
||||||
do { \
|
do { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_LEVEL" \n" \
|
||||||
" lld %0, %1 # atomic64_" #op "\n" \
|
" lld %0, %1 # atomic64_" #op "\n" \
|
||||||
" " #asm_op " %0, %2 \n" \
|
" " #asm_op " %0, %2 \n" \
|
||||||
" scd %0, %1 \n" \
|
" scd %0, %1 \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "Ir" (i)); \
|
: "Ir" (i)); \
|
||||||
} while (unlikely(!temp)); \
|
} while (unlikely(!temp)); \
|
||||||
} else { \
|
} else { \
|
||||||
|
@ -376,21 +376,21 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \
|
||||||
" " #asm_op " %0, %1, %3 \n" \
|
" " #asm_op " %0, %1, %3 \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
: "=&r" (result), "=&r" (temp), \
|
: "=&r" (result), "=&r" (temp), \
|
||||||
"+" GCC_OFF12_ASM() (v->counter) \
|
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "Ir" (i)); \
|
: "Ir" (i)); \
|
||||||
} else if (kernel_uses_llsc) { \
|
} else if (kernel_uses_llsc) { \
|
||||||
long temp; \
|
long temp; \
|
||||||
\
|
\
|
||||||
do { \
|
do { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_LEVEL" \n" \
|
||||||
" lld %1, %2 # atomic64_" #op "_return\n" \
|
" lld %1, %2 # atomic64_" #op "_return\n" \
|
||||||
" " #asm_op " %0, %1, %3 \n" \
|
" " #asm_op " %0, %1, %3 \n" \
|
||||||
" scd %0, %2 \n" \
|
" scd %0, %2 \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
: "=&r" (result), "=&r" (temp), \
|
: "=&r" (result), "=&r" (temp), \
|
||||||
"=" GCC_OFF12_ASM() (v->counter) \
|
"=" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "Ir" (i), GCC_OFF12_ASM() (v->counter) \
|
: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
} while (unlikely(!result)); \
|
} while (unlikely(!result)); \
|
||||||
\
|
\
|
||||||
|
@ -452,14 +452,14 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
|
||||||
"1: \n"
|
"1: \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (result), "=&r" (temp),
|
: "=&r" (result), "=&r" (temp),
|
||||||
"=" GCC_OFF12_ASM() (v->counter)
|
"=" GCC_OFF_SMALL_ASM() (v->counter)
|
||||||
: "Ir" (i), GCC_OFF12_ASM() (v->counter)
|
: "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
long temp;
|
long temp;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_LEVEL" \n"
|
||||||
"1: lld %1, %2 # atomic64_sub_if_positive\n"
|
"1: lld %1, %2 # atomic64_sub_if_positive\n"
|
||||||
" dsubu %0, %1, %3 \n"
|
" dsubu %0, %1, %3 \n"
|
||||||
" bltz %0, 1f \n"
|
" bltz %0, 1f \n"
|
||||||
|
@ -471,7 +471,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
|
||||||
"1: \n"
|
"1: \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (result), "=&r" (temp),
|
: "=&r" (result), "=&r" (temp),
|
||||||
"+" GCC_OFF12_ASM() (v->counter)
|
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||||
: "Ir" (i));
|
: "Ir" (i));
|
||||||
} else {
|
} else {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
|
@ -79,28 +79,28 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
" beqzl %0, 1b \n"
|
" beqzl %0, 1b \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "=" GCC_OFF12_ASM() (*m)
|
: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*m)
|
||||||
: "ir" (1UL << bit), GCC_OFF12_ASM() (*m));
|
: "ir" (1UL << bit), GCC_OFF_SMALL_ASM() (*m));
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||||
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
|
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" " __LL "%0, %1 # set_bit \n"
|
" " __LL "%0, %1 # set_bit \n"
|
||||||
" " __INS "%0, %3, %2, 1 \n"
|
" " __INS "%0, %3, %2, 1 \n"
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||||
: "ir" (bit), "r" (~0));
|
: "ir" (bit), "r" (~0));
|
||||||
} while (unlikely(!temp));
|
} while (unlikely(!temp));
|
||||||
#endif /* CONFIG_CPU_MIPSR2 */
|
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" " __LL "%0, %1 # set_bit \n"
|
" " __LL "%0, %1 # set_bit \n"
|
||||||
" or %0, %2 \n"
|
" or %0, %2 \n"
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||||
: "ir" (1UL << bit));
|
: "ir" (1UL << bit));
|
||||||
} while (unlikely(!temp));
|
} while (unlikely(!temp));
|
||||||
} else
|
} else
|
||||||
|
@ -131,28 +131,28 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
" beqzl %0, 1b \n"
|
" beqzl %0, 1b \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||||
: "ir" (~(1UL << bit)));
|
: "ir" (~(1UL << bit)));
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||||
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
|
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" " __LL "%0, %1 # clear_bit \n"
|
" " __LL "%0, %1 # clear_bit \n"
|
||||||
" " __INS "%0, $0, %2, 1 \n"
|
" " __INS "%0, $0, %2, 1 \n"
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||||
: "ir" (bit));
|
: "ir" (bit));
|
||||||
} while (unlikely(!temp));
|
} while (unlikely(!temp));
|
||||||
#endif /* CONFIG_CPU_MIPSR2 */
|
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" " __LL "%0, %1 # clear_bit \n"
|
" " __LL "%0, %1 # clear_bit \n"
|
||||||
" and %0, %2 \n"
|
" and %0, %2 \n"
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||||
: "ir" (~(1UL << bit)));
|
: "ir" (~(1UL << bit)));
|
||||||
} while (unlikely(!temp));
|
} while (unlikely(!temp));
|
||||||
} else
|
} else
|
||||||
|
@ -197,7 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
" beqzl %0, 1b \n"
|
" beqzl %0, 1b \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||||
: "ir" (1UL << bit));
|
: "ir" (1UL << bit));
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||||
|
@ -205,12 +205,12 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" " __LL "%0, %1 # change_bit \n"
|
" " __LL "%0, %1 # change_bit \n"
|
||||||
" xor %0, %2 \n"
|
" xor %0, %2 \n"
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||||
: "ir" (1UL << bit));
|
: "ir" (1UL << bit));
|
||||||
} while (unlikely(!temp));
|
} while (unlikely(!temp));
|
||||||
} else
|
} else
|
||||||
|
@ -245,7 +245,7 @@ static inline int test_and_set_bit(unsigned long nr,
|
||||||
" beqzl %2, 1b \n"
|
" beqzl %2, 1b \n"
|
||||||
" and %2, %0, %3 \n"
|
" and %2, %0, %3 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||||
: "r" (1UL << bit)
|
: "r" (1UL << bit)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
|
@ -254,12 +254,12 @@ static inline int test_and_set_bit(unsigned long nr,
|
||||||
|
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" " __LL "%0, %1 # test_and_set_bit \n"
|
" " __LL "%0, %1 # test_and_set_bit \n"
|
||||||
" or %2, %0, %3 \n"
|
" or %2, %0, %3 \n"
|
||||||
" " __SC "%2, %1 \n"
|
" " __SC "%2, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||||
: "r" (1UL << bit)
|
: "r" (1UL << bit)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!res));
|
} while (unlikely(!res));
|
||||||
|
@ -308,12 +308,12 @@ static inline int test_and_set_bit_lock(unsigned long nr,
|
||||||
|
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" " __LL "%0, %1 # test_and_set_bit \n"
|
" " __LL "%0, %1 # test_and_set_bit \n"
|
||||||
" or %2, %0, %3 \n"
|
" or %2, %0, %3 \n"
|
||||||
" " __SC "%2, %1 \n"
|
" " __SC "%2, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||||
: "r" (1UL << bit)
|
: "r" (1UL << bit)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!res));
|
} while (unlikely(!res));
|
||||||
|
@ -355,10 +355,10 @@ static inline int test_and_clear_bit(unsigned long nr,
|
||||||
" beqzl %2, 1b \n"
|
" beqzl %2, 1b \n"
|
||||||
" and %2, %0, %3 \n"
|
" and %2, %0, %3 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||||
: "r" (1UL << bit)
|
: "r" (1UL << bit)
|
||||||
: "memory");
|
: "memory");
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||||
} else if (kernel_uses_llsc && __builtin_constant_p(nr)) {
|
} else if (kernel_uses_llsc && __builtin_constant_p(nr)) {
|
||||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||||
unsigned long temp;
|
unsigned long temp;
|
||||||
|
@ -369,7 +369,7 @@ static inline int test_and_clear_bit(unsigned long nr,
|
||||||
" " __EXT "%2, %0, %3, 1 \n"
|
" " __EXT "%2, %0, %3, 1 \n"
|
||||||
" " __INS "%0, $0, %3, 1 \n"
|
" " __INS "%0, $0, %3, 1 \n"
|
||||||
" " __SC "%0, %1 \n"
|
" " __SC "%0, %1 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||||
: "ir" (bit)
|
: "ir" (bit)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!temp));
|
} while (unlikely(!temp));
|
||||||
|
@ -380,13 +380,13 @@ static inline int test_and_clear_bit(unsigned long nr,
|
||||||
|
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" " __LL "%0, %1 # test_and_clear_bit \n"
|
" " __LL "%0, %1 # test_and_clear_bit \n"
|
||||||
" or %2, %0, %3 \n"
|
" or %2, %0, %3 \n"
|
||||||
" xor %2, %3 \n"
|
" xor %2, %3 \n"
|
||||||
" " __SC "%2, %1 \n"
|
" " __SC "%2, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||||
: "r" (1UL << bit)
|
: "r" (1UL << bit)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!res));
|
} while (unlikely(!res));
|
||||||
|
@ -428,7 +428,7 @@ static inline int test_and_change_bit(unsigned long nr,
|
||||||
" beqzl %2, 1b \n"
|
" beqzl %2, 1b \n"
|
||||||
" and %2, %0, %3 \n"
|
" and %2, %0, %3 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||||
: "r" (1UL << bit)
|
: "r" (1UL << bit)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
|
@ -437,12 +437,12 @@ static inline int test_and_change_bit(unsigned long nr,
|
||||||
|
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" " __LL "%0, %1 # test_and_change_bit \n"
|
" " __LL "%0, %1 # test_and_change_bit \n"
|
||||||
" xor %2, %0, %3 \n"
|
" xor %2, %0, %3 \n"
|
||||||
" " __SC "\t%2, %1 \n"
|
" " __SC "\t%2, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
|
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||||
: "r" (1UL << bit)
|
: "r" (1UL << bit)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!res));
|
} while (unlikely(!res));
|
||||||
|
@ -485,7 +485,7 @@ static inline unsigned long __fls(unsigned long word)
|
||||||
__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
|
__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
|
||||||
__asm__(
|
__asm__(
|
||||||
" .set push \n"
|
" .set push \n"
|
||||||
" .set mips32 \n"
|
" .set "MIPS_ISA_LEVEL" \n"
|
||||||
" clz %0, %1 \n"
|
" clz %0, %1 \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: "=r" (num)
|
: "=r" (num)
|
||||||
|
@ -498,7 +498,7 @@ static inline unsigned long __fls(unsigned long word)
|
||||||
__builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) {
|
__builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) {
|
||||||
__asm__(
|
__asm__(
|
||||||
" .set push \n"
|
" .set push \n"
|
||||||
" .set mips64 \n"
|
" .set "MIPS_ISA_LEVEL" \n"
|
||||||
" dclz %0, %1 \n"
|
" dclz %0, %1 \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: "=r" (num)
|
: "=r" (num)
|
||||||
|
@ -562,7 +562,7 @@ static inline int fls(int x)
|
||||||
if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
|
if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
|
||||||
__asm__(
|
__asm__(
|
||||||
" .set push \n"
|
" .set push \n"
|
||||||
" .set mips32 \n"
|
" .set "MIPS_ISA_LEVEL" \n"
|
||||||
" clz %0, %1 \n"
|
" clz %0, %1 \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: "=r" (x)
|
: "=r" (x)
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
#ifndef _ASM_CHECKSUM_H
|
#ifndef _ASM_CHECKSUM_H
|
||||||
#define _ASM_CHECKSUM_H
|
#define _ASM_CHECKSUM_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_GENERIC_CSUM
|
||||||
|
#include <asm-generic/checksum.h>
|
||||||
|
#else
|
||||||
|
|
||||||
#include <linux/in6.h>
|
#include <linux/in6.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
@ -99,27 +103,23 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
|
||||||
*/
|
*/
|
||||||
__wsum csum_partial_copy_nocheck(const void *src, void *dst,
|
__wsum csum_partial_copy_nocheck(const void *src, void *dst,
|
||||||
int len, __wsum sum);
|
int len, __wsum sum);
|
||||||
|
#define csum_partial_copy_nocheck csum_partial_copy_nocheck
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fold a partial checksum without adding pseudo headers
|
* Fold a partial checksum without adding pseudo headers
|
||||||
*/
|
*/
|
||||||
static inline __sum16 csum_fold(__wsum sum)
|
static inline __sum16 csum_fold(__wsum csum)
|
||||||
{
|
{
|
||||||
__asm__(
|
u32 sum = (__force u32)csum;;
|
||||||
" .set push # csum_fold\n"
|
|
||||||
" .set noat \n"
|
|
||||||
" sll $1, %0, 16 \n"
|
|
||||||
" addu %0, $1 \n"
|
|
||||||
" sltu $1, %0, $1 \n"
|
|
||||||
" srl %0, %0, 16 \n"
|
|
||||||
" addu %0, $1 \n"
|
|
||||||
" xori %0, 0xffff \n"
|
|
||||||
" .set pop"
|
|
||||||
: "=r" (sum)
|
|
||||||
: "0" (sum));
|
|
||||||
|
|
||||||
return (__force __sum16)sum;
|
sum += (sum << 16);
|
||||||
|
csum = (sum < csum);
|
||||||
|
sum >>= 16;
|
||||||
|
sum += csum;
|
||||||
|
|
||||||
|
return (__force __sum16)~sum;
|
||||||
}
|
}
|
||||||
|
#define csum_fold csum_fold
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a version of ip_compute_csum() optimized for IP headers,
|
* This is a version of ip_compute_csum() optimized for IP headers,
|
||||||
|
@ -158,6 +158,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
||||||
|
|
||||||
return csum_fold(csum);
|
return csum_fold(csum);
|
||||||
}
|
}
|
||||||
|
#define ip_fast_csum ip_fast_csum
|
||||||
|
|
||||||
static inline __wsum csum_tcpudp_nofold(__be32 saddr,
|
static inline __wsum csum_tcpudp_nofold(__be32 saddr,
|
||||||
__be32 daddr, unsigned short len, unsigned short proto,
|
__be32 daddr, unsigned short len, unsigned short proto,
|
||||||
|
@ -200,18 +201,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr,
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
#define csum_tcpudp_nofold csum_tcpudp_nofold
|
||||||
/*
|
|
||||||
* computes the checksum of the TCP/UDP pseudo-header
|
|
||||||
* returns a 16-bit checksum, already complemented
|
|
||||||
*/
|
|
||||||
static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
|
|
||||||
unsigned short len,
|
|
||||||
unsigned short proto,
|
|
||||||
__wsum sum)
|
|
||||||
{
|
|
||||||
return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this routine is used for miscellaneous IP-like checksums, mainly
|
* this routine is used for miscellaneous IP-like checksums, mainly
|
||||||
|
@ -287,4 +277,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
|
||||||
return csum_fold(sum);
|
return csum_fold(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <asm-generic/checksum.h>
|
||||||
|
#endif /* CONFIG_GENERIC_CSUM */
|
||||||
|
|
||||||
#endif /* _ASM_CHECKSUM_H */
|
#endif /* _ASM_CHECKSUM_H */
|
||||||
|
|
|
@ -31,24 +31,24 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
|
||||||
" sc %2, %1 \n"
|
" sc %2, %1 \n"
|
||||||
" beqzl %2, 1b \n"
|
" beqzl %2, 1b \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
|
: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m), "=&r" (dummy)
|
||||||
: GCC_OFF12_ASM() (*m), "Jr" (val)
|
: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
unsigned long dummy;
|
unsigned long dummy;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" ll %0, %3 # xchg_u32 \n"
|
" ll %0, %3 # xchg_u32 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
" move %2, %z4 \n"
|
" move %2, %z4 \n"
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" sc %2, %1 \n"
|
" sc %2, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
|
: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m),
|
||||||
"=&r" (dummy)
|
"=&r" (dummy)
|
||||||
: GCC_OFF12_ASM() (*m), "Jr" (val)
|
: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!dummy));
|
} while (unlikely(!dummy));
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,22 +82,22 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
|
||||||
" scd %2, %1 \n"
|
" scd %2, %1 \n"
|
||||||
" beqzl %2, 1b \n"
|
" beqzl %2, 1b \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
|
: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m), "=&r" (dummy)
|
||||||
: GCC_OFF12_ASM() (*m), "Jr" (val)
|
: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else if (kernel_uses_llsc) {
|
} else if (kernel_uses_llsc) {
|
||||||
unsigned long dummy;
|
unsigned long dummy;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" lld %0, %3 # xchg_u64 \n"
|
" lld %0, %3 # xchg_u64 \n"
|
||||||
" move %2, %z4 \n"
|
" move %2, %z4 \n"
|
||||||
" scd %2, %1 \n"
|
" scd %2, %1 \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
|
: "=&r" (retval), "=" GCC_OFF_SMALL_ASM() (*m),
|
||||||
"=&r" (dummy)
|
"=&r" (dummy)
|
||||||
: GCC_OFF12_ASM() (*m), "Jr" (val)
|
: GCC_OFF_SMALL_ASM() (*m), "Jr" (val)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!dummy));
|
} while (unlikely(!dummy));
|
||||||
} else {
|
} else {
|
||||||
|
@ -158,25 +158,25 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
|
||||||
" beqzl $1, 1b \n" \
|
" beqzl $1, 1b \n" \
|
||||||
"2: \n" \
|
"2: \n" \
|
||||||
" .set pop \n" \
|
" .set pop \n" \
|
||||||
: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m) \
|
: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m) \
|
||||||
: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new) \
|
: GCC_OFF_SMALL_ASM() (*m), "Jr" (old), "Jr" (new) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
} else if (kernel_uses_llsc) { \
|
} else if (kernel_uses_llsc) { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set push \n" \
|
" .set push \n" \
|
||||||
" .set noat \n" \
|
" .set noat \n" \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||||
"1: " ld " %0, %2 # __cmpxchg_asm \n" \
|
"1: " ld " %0, %2 # __cmpxchg_asm \n" \
|
||||||
" bne %0, %z3, 2f \n" \
|
" bne %0, %z3, 2f \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
" move $1, %z4 \n" \
|
" move $1, %z4 \n" \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||||
" " st " $1, %1 \n" \
|
" " st " $1, %1 \n" \
|
||||||
" beqz $1, 1b \n" \
|
" beqz $1, 1b \n" \
|
||||||
" .set pop \n" \
|
" .set pop \n" \
|
||||||
"2: \n" \
|
"2: \n" \
|
||||||
: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m) \
|
: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m) \
|
||||||
: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new) \
|
: GCC_OFF_SMALL_ASM() (*m), "Jr" (old), "Jr" (new) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
} else { \
|
} else { \
|
||||||
unsigned long __flags; \
|
unsigned long __flags; \
|
||||||
|
|
|
@ -16,12 +16,30 @@
|
||||||
#define GCC_REG_ACCUM "accum"
|
#define GCC_REG_ACCUM "accum"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_MIPSR6
|
||||||
|
/* All MIPS R6 toolchains support the ZC constrain */
|
||||||
|
#define GCC_OFF_SMALL_ASM() "ZC"
|
||||||
|
#else
|
||||||
#ifndef CONFIG_CPU_MICROMIPS
|
#ifndef CONFIG_CPU_MICROMIPS
|
||||||
#define GCC_OFF12_ASM() "R"
|
#define GCC_OFF_SMALL_ASM() "R"
|
||||||
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
#define GCC_OFF12_ASM() "ZC"
|
#define GCC_OFF_SMALL_ASM() "ZC"
|
||||||
#else
|
#else
|
||||||
#error "microMIPS compilation unsupported with GCC older than 4.9"
|
#error "microMIPS compilation unsupported with GCC older than 4.9"
|
||||||
#endif
|
#endif /* CONFIG_CPU_MICROMIPS */
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_MIPSR6
|
||||||
|
#define MIPS_ISA_LEVEL "mips64r6"
|
||||||
|
#define MIPS_ISA_ARCH_LEVEL MIPS_ISA_LEVEL
|
||||||
|
#define MIPS_ISA_LEVEL_RAW mips64r6
|
||||||
|
#define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW
|
||||||
|
#else
|
||||||
|
/* MIPS64 is a superset of MIPS32 */
|
||||||
|
#define MIPS_ISA_LEVEL "mips64r2"
|
||||||
|
#define MIPS_ISA_ARCH_LEVEL "arch=r4000"
|
||||||
|
#define MIPS_ISA_LEVEL_RAW mips64r2
|
||||||
|
#define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
#endif /* _ASM_COMPILER_H */
|
#endif /* _ASM_COMPILER_H */
|
||||||
|
|
|
@ -38,6 +38,9 @@
|
||||||
#ifndef cpu_has_maar
|
#ifndef cpu_has_maar
|
||||||
#define cpu_has_maar (cpu_data[0].options & MIPS_CPU_MAAR)
|
#define cpu_has_maar (cpu_data[0].options & MIPS_CPU_MAAR)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef cpu_has_rw_llb
|
||||||
|
#define cpu_has_rw_llb (cpu_data[0].options & MIPS_CPU_RW_LLB)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the moment we don't consider R6000 and R8000 so we can assume that
|
* For the moment we don't consider R6000 and R8000 so we can assume that
|
||||||
|
@ -171,6 +174,9 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef cpu_has_mips_1
|
||||||
|
# define cpu_has_mips_1 (!cpu_has_mips_r6)
|
||||||
|
#endif
|
||||||
#ifndef cpu_has_mips_2
|
#ifndef cpu_has_mips_2
|
||||||
# define cpu_has_mips_2 (cpu_data[0].isa_level & MIPS_CPU_ISA_II)
|
# define cpu_has_mips_2 (cpu_data[0].isa_level & MIPS_CPU_ISA_II)
|
||||||
#endif
|
#endif
|
||||||
|
@ -189,12 +195,18 @@
|
||||||
#ifndef cpu_has_mips32r2
|
#ifndef cpu_has_mips32r2
|
||||||
# define cpu_has_mips32r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R2)
|
# define cpu_has_mips32r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R2)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef cpu_has_mips32r6
|
||||||
|
# define cpu_has_mips32r6 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R6)
|
||||||
|
#endif
|
||||||
#ifndef cpu_has_mips64r1
|
#ifndef cpu_has_mips64r1
|
||||||
# define cpu_has_mips64r1 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R1)
|
# define cpu_has_mips64r1 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R1)
|
||||||
#endif
|
#endif
|
||||||
#ifndef cpu_has_mips64r2
|
#ifndef cpu_has_mips64r2
|
||||||
# define cpu_has_mips64r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R2)
|
# define cpu_has_mips64r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R2)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef cpu_has_mips64r6
|
||||||
|
# define cpu_has_mips64r6 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R6)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shortcuts ...
|
* Shortcuts ...
|
||||||
|
@ -208,17 +220,23 @@
|
||||||
#define cpu_has_mips_4_5_r (cpu_has_mips_4 | cpu_has_mips_5_r)
|
#define cpu_has_mips_4_5_r (cpu_has_mips_4 | cpu_has_mips_5_r)
|
||||||
#define cpu_has_mips_5_r (cpu_has_mips_5 | cpu_has_mips_r)
|
#define cpu_has_mips_5_r (cpu_has_mips_5 | cpu_has_mips_r)
|
||||||
|
|
||||||
#define cpu_has_mips_4_5_r2 (cpu_has_mips_4_5 | cpu_has_mips_r2)
|
#define cpu_has_mips_4_5_r2_r6 (cpu_has_mips_4_5 | cpu_has_mips_r2 | \
|
||||||
|
cpu_has_mips_r6)
|
||||||
|
|
||||||
#define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2)
|
#define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
|
||||||
#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2)
|
#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
|
||||||
#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
|
#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
|
||||||
#define cpu_has_mips_r2 (cpu_has_mips32r2 | cpu_has_mips64r2)
|
#define cpu_has_mips_r2 (cpu_has_mips32r2 | cpu_has_mips64r2)
|
||||||
|
#define cpu_has_mips_r6 (cpu_has_mips32r6 | cpu_has_mips64r6)
|
||||||
#define cpu_has_mips_r (cpu_has_mips32r1 | cpu_has_mips32r2 | \
|
#define cpu_has_mips_r (cpu_has_mips32r1 | cpu_has_mips32r2 | \
|
||||||
cpu_has_mips64r1 | cpu_has_mips64r2)
|
cpu_has_mips32r6 | cpu_has_mips64r1 | \
|
||||||
|
cpu_has_mips64r2 | cpu_has_mips64r6)
|
||||||
|
|
||||||
|
/* MIPSR2 and MIPSR6 have a lot of similarities */
|
||||||
|
#define cpu_has_mips_r2_r6 (cpu_has_mips_r2 | cpu_has_mips_r6)
|
||||||
|
|
||||||
#ifndef cpu_has_mips_r2_exec_hazard
|
#ifndef cpu_has_mips_r2_exec_hazard
|
||||||
#define cpu_has_mips_r2_exec_hazard cpu_has_mips_r2
|
#define cpu_has_mips_r2_exec_hazard (cpu_has_mips_r2 | cpu_has_mips_r6)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -84,6 +84,11 @@ struct cpuinfo_mips {
|
||||||
* (shifted by _CACHE_SHIFT)
|
* (shifted by _CACHE_SHIFT)
|
||||||
*/
|
*/
|
||||||
unsigned int writecombine;
|
unsigned int writecombine;
|
||||||
|
/*
|
||||||
|
* Simple counter to prevent enabling HTW in nested
|
||||||
|
* htw_start/htw_stop calls
|
||||||
|
*/
|
||||||
|
unsigned int htw_seq;
|
||||||
} __attribute__((aligned(SMP_CACHE_BYTES)));
|
} __attribute__((aligned(SMP_CACHE_BYTES)));
|
||||||
|
|
||||||
extern struct cpuinfo_mips cpu_data[];
|
extern struct cpuinfo_mips cpu_data[];
|
||||||
|
|
|
@ -54,6 +54,13 @@ static inline int __pure __get_cpu_type(const int cpu_type)
|
||||||
case CPU_M5150:
|
case CPU_M5150:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_SYS_HAS_CPU_MIPS32_R2) || \
|
||||||
|
defined(CONFIG_SYS_HAS_CPU_MIPS32_R6) || \
|
||||||
|
defined(CONFIG_SYS_HAS_CPU_MIPS64_R2) || \
|
||||||
|
defined(CONFIG_SYS_HAS_CPU_MIPS64_R6)
|
||||||
|
case CPU_QEMU_GENERIC:
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R1
|
#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R1
|
||||||
case CPU_5KC:
|
case CPU_5KC:
|
||||||
case CPU_5KE:
|
case CPU_5KE:
|
||||||
|
|
|
@ -93,6 +93,7 @@
|
||||||
* These are the PRID's for when 23:16 == PRID_COMP_MIPS
|
* These are the PRID's for when 23:16 == PRID_COMP_MIPS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define PRID_IMP_QEMU_GENERIC 0x0000
|
||||||
#define PRID_IMP_4KC 0x8000
|
#define PRID_IMP_4KC 0x8000
|
||||||
#define PRID_IMP_5KC 0x8100
|
#define PRID_IMP_5KC 0x8100
|
||||||
#define PRID_IMP_20KC 0x8200
|
#define PRID_IMP_20KC 0x8200
|
||||||
|
@ -312,6 +313,8 @@ enum cpu_type_enum {
|
||||||
CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
|
CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
|
||||||
CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
|
CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
|
||||||
|
|
||||||
|
CPU_QEMU_GENERIC,
|
||||||
|
|
||||||
CPU_LAST
|
CPU_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -329,11 +332,14 @@ enum cpu_type_enum {
|
||||||
#define MIPS_CPU_ISA_M32R2 0x00000020
|
#define MIPS_CPU_ISA_M32R2 0x00000020
|
||||||
#define MIPS_CPU_ISA_M64R1 0x00000040
|
#define MIPS_CPU_ISA_M64R1 0x00000040
|
||||||
#define MIPS_CPU_ISA_M64R2 0x00000080
|
#define MIPS_CPU_ISA_M64R2 0x00000080
|
||||||
|
#define MIPS_CPU_ISA_M32R6 0x00000100
|
||||||
|
#define MIPS_CPU_ISA_M64R6 0x00000200
|
||||||
|
|
||||||
#define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_II | MIPS_CPU_ISA_M32R1 | \
|
#define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_II | MIPS_CPU_ISA_M32R1 | \
|
||||||
MIPS_CPU_ISA_M32R2)
|
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M32R6)
|
||||||
#define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \
|
#define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \
|
||||||
MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)
|
MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2 | \
|
||||||
|
MIPS_CPU_ISA_M64R6)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CPU Option encodings
|
* CPU Option encodings
|
||||||
|
@ -370,6 +376,7 @@ enum cpu_type_enum {
|
||||||
#define MIPS_CPU_RIXIEX 0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
|
#define MIPS_CPU_RIXIEX 0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
|
||||||
#define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */
|
#define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */
|
||||||
#define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */
|
#define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */
|
||||||
|
#define MIPS_CPU_RW_LLB 0x1000000000ull /* LLADDR/LLB writes are allowed */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CPU ASE encodings
|
* CPU ASE encodings
|
||||||
|
|
|
@ -26,8 +26,8 @@ static inline void atomic_scrub(void *va, u32 size)
|
||||||
" sc %0, %1 \n"
|
" sc %0, %1 \n"
|
||||||
" beqz %0, 1b \n"
|
" beqz %0, 1b \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
: "=&r" (temp), "=" GCC_OFF12_ASM() (*virt_addr)
|
: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*virt_addr)
|
||||||
: GCC_OFF12_ASM() (*virt_addr));
|
: GCC_OFF_SMALL_ASM() (*virt_addr));
|
||||||
|
|
||||||
virt_addr++;
|
virt_addr++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,13 +417,15 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
|
||||||
struct arch_elf_state {
|
struct arch_elf_state {
|
||||||
int fp_abi;
|
int fp_abi;
|
||||||
int interp_fp_abi;
|
int interp_fp_abi;
|
||||||
int overall_abi;
|
int overall_fp_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MIPS_ABI_FP_UNKNOWN (-1) /* Unknown FP ABI (kernel internal) */
|
||||||
|
|
||||||
#define INIT_ARCH_ELF_STATE { \
|
#define INIT_ARCH_ELF_STATE { \
|
||||||
.fp_abi = -1, \
|
.fp_abi = MIPS_ABI_FP_UNKNOWN, \
|
||||||
.interp_fp_abi = -1, \
|
.interp_fp_abi = MIPS_ABI_FP_UNKNOWN, \
|
||||||
.overall_abi = -1, \
|
.overall_fp_mode = -1, \
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
|
extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
|
||||||
|
|
|
@ -68,7 +68,8 @@ static inline int __enable_fpu(enum fpu_mode mode)
|
||||||
goto fr_common;
|
goto fr_common;
|
||||||
|
|
||||||
case FPU_64BIT:
|
case FPU_64BIT:
|
||||||
#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
|
#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6) \
|
||||||
|
|| defined(CONFIG_64BIT))
|
||||||
/* we only have a 32-bit FPU */
|
/* we only have a 32-bit FPU */
|
||||||
return SIGFPE;
|
return SIGFPE;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,19 +45,19 @@
|
||||||
" "__UA_ADDR "\t2b, 4b \n" \
|
" "__UA_ADDR "\t2b, 4b \n" \
|
||||||
" .previous \n" \
|
" .previous \n" \
|
||||||
: "=r" (ret), "=&r" (oldval), \
|
: "=r" (ret), "=&r" (oldval), \
|
||||||
"=" GCC_OFF12_ASM() (*uaddr) \
|
"=" GCC_OFF_SMALL_ASM() (*uaddr) \
|
||||||
: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg), \
|
: "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg), \
|
||||||
"i" (-EFAULT) \
|
"i" (-EFAULT) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
} else if (cpu_has_llsc) { \
|
} else if (cpu_has_llsc) { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set push \n" \
|
" .set push \n" \
|
||||||
" .set noat \n" \
|
" .set noat \n" \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||||
"1: "user_ll("%1", "%4")" # __futex_atomic_op\n" \
|
"1: "user_ll("%1", "%4")" # __futex_atomic_op\n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
" " insn " \n" \
|
" " insn " \n" \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||||
"2: "user_sc("$1", "%2")" \n" \
|
"2: "user_sc("$1", "%2")" \n" \
|
||||||
" beqz $1, 1b \n" \
|
" beqz $1, 1b \n" \
|
||||||
__WEAK_LLSC_MB \
|
__WEAK_LLSC_MB \
|
||||||
|
@ -74,8 +74,8 @@
|
||||||
" "__UA_ADDR "\t2b, 4b \n" \
|
" "__UA_ADDR "\t2b, 4b \n" \
|
||||||
" .previous \n" \
|
" .previous \n" \
|
||||||
: "=r" (ret), "=&r" (oldval), \
|
: "=r" (ret), "=&r" (oldval), \
|
||||||
"=" GCC_OFF12_ASM() (*uaddr) \
|
"=" GCC_OFF_SMALL_ASM() (*uaddr) \
|
||||||
: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg), \
|
: "0" (0), GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oparg), \
|
||||||
"i" (-EFAULT) \
|
"i" (-EFAULT) \
|
||||||
: "memory"); \
|
: "memory"); \
|
||||||
} else \
|
} else \
|
||||||
|
@ -174,8 +174,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||||
" "__UA_ADDR "\t1b, 4b \n"
|
" "__UA_ADDR "\t1b, 4b \n"
|
||||||
" "__UA_ADDR "\t2b, 4b \n"
|
" "__UA_ADDR "\t2b, 4b \n"
|
||||||
" .previous \n"
|
" .previous \n"
|
||||||
: "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr)
|
: "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
|
||||||
: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
|
: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
|
||||||
"i" (-EFAULT)
|
"i" (-EFAULT)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else if (cpu_has_llsc) {
|
} else if (cpu_has_llsc) {
|
||||||
|
@ -183,12 +183,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||||
"# futex_atomic_cmpxchg_inatomic \n"
|
"# futex_atomic_cmpxchg_inatomic \n"
|
||||||
" .set push \n"
|
" .set push \n"
|
||||||
" .set noat \n"
|
" .set noat \n"
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
"1: "user_ll("%1", "%3")" \n"
|
"1: "user_ll("%1", "%3")" \n"
|
||||||
" bne %1, %z4, 3f \n"
|
" bne %1, %z4, 3f \n"
|
||||||
" .set mips0 \n"
|
" .set mips0 \n"
|
||||||
" move $1, %z5 \n"
|
" move $1, %z5 \n"
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
"2: "user_sc("$1", "%2")" \n"
|
"2: "user_sc("$1", "%2")" \n"
|
||||||
" beqz $1, 1b \n"
|
" beqz $1, 1b \n"
|
||||||
__WEAK_LLSC_MB
|
__WEAK_LLSC_MB
|
||||||
|
@ -203,8 +203,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||||
" "__UA_ADDR "\t1b, 4b \n"
|
" "__UA_ADDR "\t1b, 4b \n"
|
||||||
" "__UA_ADDR "\t2b, 4b \n"
|
" "__UA_ADDR "\t2b, 4b \n"
|
||||||
" .previous \n"
|
" .previous \n"
|
||||||
: "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr)
|
: "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr)
|
||||||
: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
|
: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
|
||||||
"i" (-EFAULT)
|
"i" (-EFAULT)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -25,8 +25,6 @@ struct gio_driver {
|
||||||
|
|
||||||
int (*probe)(struct gio_device *, const struct gio_device_id *);
|
int (*probe)(struct gio_device *, const struct gio_device_id *);
|
||||||
void (*remove)(struct gio_device *);
|
void (*remove)(struct gio_device *);
|
||||||
int (*suspend)(struct gio_device *, pm_message_t);
|
|
||||||
int (*resume)(struct gio_device *);
|
|
||||||
void (*shutdown)(struct gio_device *);
|
void (*shutdown)(struct gio_device *);
|
||||||
|
|
||||||
struct device_driver driver;
|
struct device_driver driver;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define _ASM_HAZARDS_H
|
#define _ASM_HAZARDS_H
|
||||||
|
|
||||||
#include <linux/stringify.h>
|
#include <linux/stringify.h>
|
||||||
|
#include <asm/compiler.h>
|
||||||
|
|
||||||
#define ___ssnop \
|
#define ___ssnop \
|
||||||
sll $0, $0, 1
|
sll $0, $0, 1
|
||||||
|
@ -21,7 +22,7 @@
|
||||||
/*
|
/*
|
||||||
* TLB hazards
|
* TLB hazards
|
||||||
*/
|
*/
|
||||||
#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MIPSR2 defines ehb for hazard avoidance
|
* MIPSR2 defines ehb for hazard avoidance
|
||||||
|
@ -58,7 +59,7 @@ do { \
|
||||||
unsigned long tmp; \
|
unsigned long tmp; \
|
||||||
\
|
\
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set mips64r2 \n" \
|
" .set "MIPS_ISA_LEVEL" \n" \
|
||||||
" dla %0, 1f \n" \
|
" dla %0, 1f \n" \
|
||||||
" jr.hb %0 \n" \
|
" jr.hb %0 \n" \
|
||||||
" .set mips0 \n" \
|
" .set mips0 \n" \
|
||||||
|
@ -132,7 +133,7 @@ do { \
|
||||||
|
|
||||||
#define instruction_hazard() \
|
#define instruction_hazard() \
|
||||||
do { \
|
do { \
|
||||||
if (cpu_has_mips_r2) \
|
if (cpu_has_mips_r2_r6) \
|
||||||
__instruction_hazard(); \
|
__instruction_hazard(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -240,7 +241,7 @@ do { \
|
||||||
|
|
||||||
#define __disable_fpu_hazard
|
#define __disable_fpu_hazard
|
||||||
|
|
||||||
#elif defined(CONFIG_CPU_MIPSR2)
|
#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||||
|
|
||||||
#define __enable_fpu_hazard \
|
#define __enable_fpu_hazard \
|
||||||
___ehb
|
___ehb
|
||||||
|
|
|
@ -15,9 +15,10 @@
|
||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/stringify.h>
|
#include <linux/stringify.h>
|
||||||
|
#include <asm/compiler.h>
|
||||||
#include <asm/hazards.h>
|
#include <asm/hazards.h>
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#if defined(CONFIG_CPU_MIPSR2) || defined (CONFIG_CPU_MIPSR6)
|
||||||
|
|
||||||
static inline void arch_local_irq_disable(void)
|
static inline void arch_local_irq_disable(void)
|
||||||
{
|
{
|
||||||
|
@ -118,7 +119,7 @@ void arch_local_irq_disable(void);
|
||||||
unsigned long arch_local_irq_save(void);
|
unsigned long arch_local_irq_save(void);
|
||||||
void arch_local_irq_restore(unsigned long flags);
|
void arch_local_irq_restore(unsigned long flags);
|
||||||
void __arch_local_irq_restore(unsigned long flags);
|
void __arch_local_irq_restore(unsigned long flags);
|
||||||
#endif /* CONFIG_CPU_MIPSR2 */
|
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
static inline void arch_local_irq_enable(void)
|
static inline void arch_local_irq_enable(void)
|
||||||
{
|
{
|
||||||
|
@ -126,7 +127,7 @@ static inline void arch_local_irq_enable(void)
|
||||||
" .set push \n"
|
" .set push \n"
|
||||||
" .set reorder \n"
|
" .set reorder \n"
|
||||||
" .set noat \n"
|
" .set noat \n"
|
||||||
#if defined(CONFIG_CPU_MIPSR2)
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||||
" ei \n"
|
" ei \n"
|
||||||
#else
|
#else
|
||||||
" mfc0 $1,$12 \n"
|
" mfc0 $1,$12 \n"
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <asm/cmpxchg.h>
|
#include <asm/cmpxchg.h>
|
||||||
|
#include <asm/compiler.h>
|
||||||
#include <asm/war.h>
|
#include <asm/war.h>
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -47,7 +48,7 @@ static __inline__ long local_add_return(long i, local_t * l)
|
||||||
unsigned long temp;
|
unsigned long temp;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
"1:" __LL "%1, %2 # local_add_return \n"
|
"1:" __LL "%1, %2 # local_add_return \n"
|
||||||
" addu %0, %1, %3 \n"
|
" addu %0, %1, %3 \n"
|
||||||
__SC "%0, %2 \n"
|
__SC "%0, %2 \n"
|
||||||
|
@ -92,7 +93,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
|
||||||
unsigned long temp;
|
unsigned long temp;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
"1:" __LL "%1, %2 # local_sub_return \n"
|
"1:" __LL "%1, %2 # local_sub_return \n"
|
||||||
" subu %0, %1, %3 \n"
|
" subu %0, %1, %3 \n"
|
||||||
__SC "%0, %2 \n"
|
__SC "%0, %2 \n"
|
||||||
|
|
|
@ -8,11 +8,10 @@
|
||||||
#ifndef __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
|
#ifndef __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
|
||||||
#define __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
|
#define __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
|
||||||
|
|
||||||
|
|
||||||
#define CP0_CYCLE_COUNTER $9, 6
|
|
||||||
#define CP0_CVMCTL_REG $9, 7
|
#define CP0_CVMCTL_REG $9, 7
|
||||||
#define CP0_CVMMEMCTL_REG $11,7
|
#define CP0_CVMMEMCTL_REG $11,7
|
||||||
#define CP0_PRID_REG $15, 0
|
#define CP0_PRID_REG $15, 0
|
||||||
|
#define CP0_DCACHE_ERR_REG $27, 1
|
||||||
#define CP0_PRID_OCTEON_PASS1 0x000d0000
|
#define CP0_PRID_OCTEON_PASS1 0x000d0000
|
||||||
#define CP0_PRID_OCTEON_CN30XX 0x000d0200
|
#define CP0_PRID_OCTEON_CN30XX 0x000d0200
|
||||||
|
|
||||||
|
@ -38,36 +37,55 @@
|
||||||
# Needed for octeon specific memcpy
|
# Needed for octeon specific memcpy
|
||||||
or v0, v0, 0x5001
|
or v0, v0, 0x5001
|
||||||
xor v0, v0, 0x1001
|
xor v0, v0, 0x1001
|
||||||
# Read the processor ID register
|
|
||||||
mfc0 v1, CP0_PRID_REG
|
|
||||||
# Disable instruction prefetching (Octeon Pass1 errata)
|
|
||||||
or v0, v0, 0x2000
|
|
||||||
# Skip reenable of prefetching for Octeon Pass1
|
|
||||||
beq v1, CP0_PRID_OCTEON_PASS1, skip
|
|
||||||
nop
|
|
||||||
# Reenable instruction prefetching, not on Pass1
|
|
||||||
xor v0, v0, 0x2000
|
|
||||||
# Strip off pass number off of processor id
|
|
||||||
srl v1, 8
|
|
||||||
sll v1, 8
|
|
||||||
# CN30XX needs some extra stuff turned off for better performance
|
|
||||||
bne v1, CP0_PRID_OCTEON_CN30XX, skip
|
|
||||||
nop
|
|
||||||
# CN30XX Use random Icache replacement
|
|
||||||
or v0, v0, 0x400
|
|
||||||
# CN30XX Disable instruction prefetching
|
|
||||||
or v0, v0, 0x2000
|
|
||||||
skip:
|
|
||||||
# First clear off CvmCtl[IPPCI] bit and move the performance
|
# First clear off CvmCtl[IPPCI] bit and move the performance
|
||||||
# counters interrupt to IRQ 6
|
# counters interrupt to IRQ 6
|
||||||
li v1, ~(7 << 7)
|
dli v1, ~(7 << 7)
|
||||||
and v0, v0, v1
|
and v0, v0, v1
|
||||||
ori v0, v0, (6 << 7)
|
ori v0, v0, (6 << 7)
|
||||||
|
|
||||||
|
mfc0 v1, CP0_PRID_REG
|
||||||
|
and t1, v1, 0xfff8
|
||||||
|
xor t1, t1, 0x9000 # 63-P1
|
||||||
|
beqz t1, 4f
|
||||||
|
and t1, v1, 0xfff8
|
||||||
|
xor t1, t1, 0x9008 # 63-P2
|
||||||
|
beqz t1, 4f
|
||||||
|
and t1, v1, 0xfff8
|
||||||
|
xor t1, t1, 0x9100 # 68-P1
|
||||||
|
beqz t1, 4f
|
||||||
|
and t1, v1, 0xff00
|
||||||
|
xor t1, t1, 0x9200 # 66-PX
|
||||||
|
bnez t1, 5f # Skip WAR for others.
|
||||||
|
and t1, v1, 0x00ff
|
||||||
|
slti t1, t1, 2 # 66-P1.2 and later good.
|
||||||
|
beqz t1, 5f
|
||||||
|
|
||||||
|
4: # core-16057 work around
|
||||||
|
or v0, v0, 0x2000 # Set IPREF bit.
|
||||||
|
|
||||||
|
5: # No core-16057 work around
|
||||||
# Write the cavium control register
|
# Write the cavium control register
|
||||||
dmtc0 v0, CP0_CVMCTL_REG
|
dmtc0 v0, CP0_CVMCTL_REG
|
||||||
sync
|
sync
|
||||||
# Flush dcache after config change
|
# Flush dcache after config change
|
||||||
cache 9, 0($0)
|
cache 9, 0($0)
|
||||||
|
# Zero all of CVMSEG to make sure parity is correct
|
||||||
|
dli v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE
|
||||||
|
dsll v0, 7
|
||||||
|
beqz v0, 2f
|
||||||
|
1: dsubu v0, 8
|
||||||
|
sd $0, -32768(v0)
|
||||||
|
bnez v0, 1b
|
||||||
|
2:
|
||||||
|
mfc0 v0, CP0_PRID_REG
|
||||||
|
bbit0 v0, 15, 1f
|
||||||
|
# OCTEON II or better have bit 15 set. Clear the error bits.
|
||||||
|
and t1, v0, 0xff00
|
||||||
|
dli v0, 0x9500
|
||||||
|
bge t1, v0, 1f # OCTEON III has no DCACHE_ERR_REG COP0
|
||||||
|
dli v0, 0x27
|
||||||
|
dmtc0 v0, CP0_DCACHE_ERR_REG
|
||||||
|
1:
|
||||||
# Get my core id
|
# Get my core id
|
||||||
rdhwr v0, $0
|
rdhwr v0, $0
|
||||||
# Jump the master to kernel_entry
|
# Jump the master to kernel_entry
|
||||||
|
|
|
@ -22,4 +22,7 @@
|
||||||
#define R10000_LLSC_WAR 0
|
#define R10000_LLSC_WAR 0
|
||||||
#define MIPS34K_MISSED_ITLB_WAR 0
|
#define MIPS34K_MISSED_ITLB_WAR 0
|
||||||
|
|
||||||
|
#define CAVIUM_OCTEON_DCACHE_PREFETCH_WAR \
|
||||||
|
OCTEON_IS_MODEL(OCTEON_CN6XXX)
|
||||||
|
|
||||||
#endif /* __ASM_MIPS_MACH_CAVIUM_OCTEON_WAR_H */
|
#endif /* __ASM_MIPS_MACH_CAVIUM_OCTEON_WAR_H */
|
||||||
|
|
|
@ -85,8 +85,8 @@ static inline void set_value_reg32(volatile u32 *const addr,
|
||||||
" "__beqz"%0, 1b \n"
|
" "__beqz"%0, 1b \n"
|
||||||
" nop \n"
|
" nop \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
|
: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
|
||||||
: "ir" (~mask), "ir" (value), GCC_OFF12_ASM() (*addr));
|
: "ir" (~mask), "ir" (value), GCC_OFF_SMALL_ASM() (*addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,8 +106,8 @@ static inline void set_reg32(volatile u32 *const addr,
|
||||||
" "__beqz"%0, 1b \n"
|
" "__beqz"%0, 1b \n"
|
||||||
" nop \n"
|
" nop \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
|
: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
|
||||||
: "ir" (mask), GCC_OFF12_ASM() (*addr));
|
: "ir" (mask), GCC_OFF_SMALL_ASM() (*addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -127,8 +127,8 @@ static inline void clear_reg32(volatile u32 *const addr,
|
||||||
" "__beqz"%0, 1b \n"
|
" "__beqz"%0, 1b \n"
|
||||||
" nop \n"
|
" nop \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
|
: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
|
||||||
: "ir" (~mask), GCC_OFF12_ASM() (*addr));
|
: "ir" (~mask), GCC_OFF_SMALL_ASM() (*addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -148,8 +148,8 @@ static inline void toggle_reg32(volatile u32 *const addr,
|
||||||
" "__beqz"%0, 1b \n"
|
" "__beqz"%0, 1b \n"
|
||||||
" nop \n"
|
" nop \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
|
: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
|
||||||
: "ir" (mask), GCC_OFF12_ASM() (*addr));
|
: "ir" (mask), GCC_OFF_SMALL_ASM() (*addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -220,8 +220,8 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
|
||||||
" .set arch=r4000 \n" \
|
" .set arch=r4000 \n" \
|
||||||
"1: ll %0, %1 #custom_read_reg32 \n" \
|
"1: ll %0, %1 #custom_read_reg32 \n" \
|
||||||
" .set pop \n" \
|
" .set pop \n" \
|
||||||
: "=r" (tmp), "=" GCC_OFF12_ASM() (*address) \
|
: "=r" (tmp), "=" GCC_OFF_SMALL_ASM() (*address) \
|
||||||
: GCC_OFF12_ASM() (*address))
|
: GCC_OFF_SMALL_ASM() (*address))
|
||||||
|
|
||||||
#define custom_write_reg32(address, tmp) \
|
#define custom_write_reg32(address, tmp) \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
|
@ -231,7 +231,7 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
|
||||||
" "__beqz"%0, 1b \n" \
|
" "__beqz"%0, 1b \n" \
|
||||||
" nop \n" \
|
" nop \n" \
|
||||||
" .set pop \n" \
|
" .set pop \n" \
|
||||||
: "=&r" (tmp), "=" GCC_OFF12_ASM() (*address) \
|
: "=&r" (tmp), "=" GCC_OFF_SMALL_ASM() (*address) \
|
||||||
: "0" (tmp), GCC_OFF12_ASM() (*address))
|
: "0" (tmp), GCC_OFF_SMALL_ASM() (*address))
|
||||||
|
|
||||||
#endif /* __ASM_REGOPS_H__ */
|
#endif /* __ASM_REGOPS_H__ */
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Imagination Technologies Ltd.
|
||||||
|
* Author: Markos Chandras <markos.chandras@imgtec.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASM_MIPS_R2_TO_R6_EMUL_H
|
||||||
|
#define __ASM_MIPS_R2_TO_R6_EMUL_H
|
||||||
|
|
||||||
|
struct mips_r2_emulator_stats {
|
||||||
|
u64 movs;
|
||||||
|
u64 hilo;
|
||||||
|
u64 muls;
|
||||||
|
u64 divs;
|
||||||
|
u64 dsps;
|
||||||
|
u64 bops;
|
||||||
|
u64 traps;
|
||||||
|
u64 fpus;
|
||||||
|
u64 loads;
|
||||||
|
u64 stores;
|
||||||
|
u64 llsc;
|
||||||
|
u64 dsemul;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mips_r2br_emulator_stats {
|
||||||
|
u64 jrs;
|
||||||
|
u64 bltzl;
|
||||||
|
u64 bgezl;
|
||||||
|
u64 bltzll;
|
||||||
|
u64 bgezll;
|
||||||
|
u64 bltzall;
|
||||||
|
u64 bgezall;
|
||||||
|
u64 bltzal;
|
||||||
|
u64 bgezal;
|
||||||
|
u64 beql;
|
||||||
|
u64 bnel;
|
||||||
|
u64 blezl;
|
||||||
|
u64 bgtzl;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
||||||
|
#define MIPS_R2_STATS(M) \
|
||||||
|
do { \
|
||||||
|
u32 nir; \
|
||||||
|
int err; \
|
||||||
|
\
|
||||||
|
preempt_disable(); \
|
||||||
|
__this_cpu_inc(mipsr2emustats.M); \
|
||||||
|
err = __get_user(nir, (u32 __user *)regs->cp0_epc); \
|
||||||
|
if (!err) { \
|
||||||
|
if (nir == BREAK_MATH) \
|
||||||
|
__this_cpu_inc(mipsr2bdemustats.M); \
|
||||||
|
} \
|
||||||
|
preempt_enable(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define MIPS_R2BR_STATS(M) \
|
||||||
|
do { \
|
||||||
|
preempt_disable(); \
|
||||||
|
__this_cpu_inc(mipsr2bremustats.M); \
|
||||||
|
preempt_enable(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define MIPS_R2_STATS(M) do { } while (0)
|
||||||
|
#define MIPS_R2BR_STATS(M) do { } while (0)
|
||||||
|
|
||||||
|
#endif /* CONFIG_DEBUG_FS */
|
||||||
|
|
||||||
|
struct r2_decoder_table {
|
||||||
|
u32 mask;
|
||||||
|
u32 code;
|
||||||
|
int (*func)(struct pt_regs *regs, u32 inst);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
||||||
|
const char *str);
|
||||||
|
|
||||||
|
#ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
|
||||||
|
static int mipsr2_emulation;
|
||||||
|
static __maybe_unused int mipsr2_decoder(struct pt_regs *regs, u32 inst) { return 0; };
|
||||||
|
#else
|
||||||
|
/* MIPS R2 Emulator ON/OFF */
|
||||||
|
extern int mipsr2_emulation;
|
||||||
|
extern int mipsr2_decoder(struct pt_regs *regs, u32 inst);
|
||||||
|
#endif /* CONFIG_MIPSR2_TO_R6_EMULATOR */
|
||||||
|
|
||||||
|
#define NO_R6EMU (cpu_has_mips_r6 && !mipsr2_emulation)
|
||||||
|
|
||||||
|
#endif /* __ASM_MIPS_R2_TO_R6_EMUL_H */
|
|
@ -653,6 +653,7 @@
|
||||||
#define MIPS_CONF5_NF (_ULCAST_(1) << 0)
|
#define MIPS_CONF5_NF (_ULCAST_(1) << 0)
|
||||||
#define MIPS_CONF5_UFR (_ULCAST_(1) << 2)
|
#define MIPS_CONF5_UFR (_ULCAST_(1) << 2)
|
||||||
#define MIPS_CONF5_MRP (_ULCAST_(1) << 3)
|
#define MIPS_CONF5_MRP (_ULCAST_(1) << 3)
|
||||||
|
#define MIPS_CONF5_LLB (_ULCAST_(1) << 4)
|
||||||
#define MIPS_CONF5_MVH (_ULCAST_(1) << 5)
|
#define MIPS_CONF5_MVH (_ULCAST_(1) << 5)
|
||||||
#define MIPS_CONF5_FRE (_ULCAST_(1) << 8)
|
#define MIPS_CONF5_FRE (_ULCAST_(1) << 8)
|
||||||
#define MIPS_CONF5_UFE (_ULCAST_(1) << 9)
|
#define MIPS_CONF5_UFE (_ULCAST_(1) << 9)
|
||||||
|
@ -1127,6 +1128,8 @@ do { \
|
||||||
#define write_c0_config6(val) __write_32bit_c0_register($16, 6, val)
|
#define write_c0_config6(val) __write_32bit_c0_register($16, 6, val)
|
||||||
#define write_c0_config7(val) __write_32bit_c0_register($16, 7, val)
|
#define write_c0_config7(val) __write_32bit_c0_register($16, 7, val)
|
||||||
|
|
||||||
|
#define read_c0_lladdr() __read_ulong_c0_register($17, 0)
|
||||||
|
#define write_c0_lladdr(val) __write_ulong_c0_register($17, 0, val)
|
||||||
#define read_c0_maar() __read_ulong_c0_register($17, 1)
|
#define read_c0_maar() __read_ulong_c0_register($17, 1)
|
||||||
#define write_c0_maar(val) __write_ulong_c0_register($17, 1, val)
|
#define write_c0_maar(val) __write_ulong_c0_register($17, 1, val)
|
||||||
#define read_c0_maari() __read_32bit_c0_register($17, 2)
|
#define read_c0_maari() __read_32bit_c0_register($17, 2)
|
||||||
|
@ -1909,6 +1912,7 @@ __BUILD_SET_C0(config5)
|
||||||
__BUILD_SET_C0(intcontrol)
|
__BUILD_SET_C0(intcontrol)
|
||||||
__BUILD_SET_C0(intctl)
|
__BUILD_SET_C0(intctl)
|
||||||
__BUILD_SET_C0(srsmap)
|
__BUILD_SET_C0(srsmap)
|
||||||
|
__BUILD_SET_C0(pagegrain)
|
||||||
__BUILD_SET_C0(brcm_config_0)
|
__BUILD_SET_C0(brcm_config_0)
|
||||||
__BUILD_SET_C0(brcm_bus_pll)
|
__BUILD_SET_C0(brcm_bus_pll)
|
||||||
__BUILD_SET_C0(brcm_reset)
|
__BUILD_SET_C0(brcm_reset)
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
#ifndef __ASM_MMU_H
|
#ifndef __ASM_MMU_H
|
||||||
#define __ASM_MMU_H
|
#define __ASM_MMU_H
|
||||||
|
|
||||||
|
#include <linux/atomic.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned long asid[NR_CPUS];
|
unsigned long asid[NR_CPUS];
|
||||||
void *vdso;
|
void *vdso;
|
||||||
|
atomic_t fp_mode_switching;
|
||||||
} mm_context_t;
|
} mm_context_t;
|
||||||
|
|
||||||
#endif /* __ASM_MMU_H */
|
#endif /* __ASM_MMU_H */
|
||||||
|
|
|
@ -25,7 +25,6 @@ do { \
|
||||||
if (cpu_has_htw) { \
|
if (cpu_has_htw) { \
|
||||||
write_c0_pwbase(pgd); \
|
write_c0_pwbase(pgd); \
|
||||||
back_to_back_c0_hazard(); \
|
back_to_back_c0_hazard(); \
|
||||||
htw_reset(); \
|
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -132,6 +131,8 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
||||||
for_each_possible_cpu(i)
|
for_each_possible_cpu(i)
|
||||||
cpu_context(i, mm) = 0;
|
cpu_context(i, mm) = 0;
|
||||||
|
|
||||||
|
atomic_set(&mm->context.fp_mode_switching, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +143,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
|
htw_stop();
|
||||||
/* Check if our ASID is of an older version and thus invalid */
|
/* Check if our ASID is of an older version and thus invalid */
|
||||||
if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
|
if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
|
||||||
get_new_mmu_context(next, cpu);
|
get_new_mmu_context(next, cpu);
|
||||||
|
@ -154,6 +156,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||||
*/
|
*/
|
||||||
cpumask_clear_cpu(cpu, mm_cpumask(prev));
|
cpumask_clear_cpu(cpu, mm_cpumask(prev));
|
||||||
cpumask_set_cpu(cpu, mm_cpumask(next));
|
cpumask_set_cpu(cpu, mm_cpumask(next));
|
||||||
|
htw_start();
|
||||||
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
@ -180,6 +183,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
|
htw_stop();
|
||||||
/* Unconditionally get a new ASID. */
|
/* Unconditionally get a new ASID. */
|
||||||
get_new_mmu_context(next, cpu);
|
get_new_mmu_context(next, cpu);
|
||||||
|
|
||||||
|
@ -189,6 +193,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
|
||||||
/* mark mmu ownership change */
|
/* mark mmu ownership change */
|
||||||
cpumask_clear_cpu(cpu, mm_cpumask(prev));
|
cpumask_clear_cpu(cpu, mm_cpumask(prev));
|
||||||
cpumask_set_cpu(cpu, mm_cpumask(next));
|
cpumask_set_cpu(cpu, mm_cpumask(next));
|
||||||
|
htw_start();
|
||||||
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
@ -203,6 +208,7 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
htw_stop();
|
||||||
|
|
||||||
if (cpumask_test_cpu(cpu, mm_cpumask(mm))) {
|
if (cpumask_test_cpu(cpu, mm_cpumask(mm))) {
|
||||||
get_new_mmu_context(mm, cpu);
|
get_new_mmu_context(mm, cpu);
|
||||||
|
@ -211,6 +217,7 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
|
||||||
/* will get a new context next time */
|
/* will get a new context next time */
|
||||||
cpu_context(cpu, mm) = 0;
|
cpu_context(cpu, mm) = 0;
|
||||||
}
|
}
|
||||||
|
htw_start();
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,10 +88,14 @@ search_module_dbetables(unsigned long addr)
|
||||||
#define MODULE_PROC_FAMILY "MIPS32_R1 "
|
#define MODULE_PROC_FAMILY "MIPS32_R1 "
|
||||||
#elif defined CONFIG_CPU_MIPS32_R2
|
#elif defined CONFIG_CPU_MIPS32_R2
|
||||||
#define MODULE_PROC_FAMILY "MIPS32_R2 "
|
#define MODULE_PROC_FAMILY "MIPS32_R2 "
|
||||||
|
#elif defined CONFIG_CPU_MIPS32_R6
|
||||||
|
#define MODULE_PROC_FAMILY "MIPS32_R6 "
|
||||||
#elif defined CONFIG_CPU_MIPS64_R1
|
#elif defined CONFIG_CPU_MIPS64_R1
|
||||||
#define MODULE_PROC_FAMILY "MIPS64_R1 "
|
#define MODULE_PROC_FAMILY "MIPS64_R1 "
|
||||||
#elif defined CONFIG_CPU_MIPS64_R2
|
#elif defined CONFIG_CPU_MIPS64_R2
|
||||||
#define MODULE_PROC_FAMILY "MIPS64_R2 "
|
#define MODULE_PROC_FAMILY "MIPS64_R2 "
|
||||||
|
#elif defined CONFIG_CPU_MIPS64_R6
|
||||||
|
#define MODULE_PROC_FAMILY "MIPS64_R6 "
|
||||||
#elif defined CONFIG_CPU_R3000
|
#elif defined CONFIG_CPU_R3000
|
||||||
#define MODULE_PROC_FAMILY "R3000 "
|
#define MODULE_PROC_FAMILY "R3000 "
|
||||||
#elif defined CONFIG_CPU_TX39XX
|
#elif defined CONFIG_CPU_TX39XX
|
||||||
|
|
|
@ -275,7 +275,7 @@ static inline void __cvmx_cmd_queue_lock(cvmx_cmd_queue_id_t queue_id,
|
||||||
" lbu %[ticket], %[now_serving]\n"
|
" lbu %[ticket], %[now_serving]\n"
|
||||||
"4:\n"
|
"4:\n"
|
||||||
".set pop\n" :
|
".set pop\n" :
|
||||||
[ticket_ptr] "=" GCC_OFF12_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
|
[ticket_ptr] "=" GCC_OFF_SMALL_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
|
||||||
[now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp),
|
[now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp),
|
||||||
[my_ticket] "=r"(my_ticket)
|
[my_ticket] "=r"(my_ticket)
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,306 @@
|
||||||
|
/***********************license start***************
|
||||||
|
* Author: Cavium Inc.
|
||||||
|
*
|
||||||
|
* Contact: support@cavium.com
|
||||||
|
* This file is part of the OCTEON SDK
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003-2014 Cavium Inc.
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, Version 2, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful, but
|
||||||
|
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
|
||||||
|
* NONINFRINGEMENT. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this file; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
* or visit http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* This file may also be available under a different license from Cavium.
|
||||||
|
* Contact Cavium Inc. for more information
|
||||||
|
***********************license end**************************************/
|
||||||
|
|
||||||
|
#ifndef __CVMX_RST_DEFS_H__
|
||||||
|
#define __CVMX_RST_DEFS_H__
|
||||||
|
|
||||||
|
#define CVMX_RST_BOOT (CVMX_ADD_IO_SEG(0x0001180006001600ull))
|
||||||
|
#define CVMX_RST_CFG (CVMX_ADD_IO_SEG(0x0001180006001610ull))
|
||||||
|
#define CVMX_RST_CKILL (CVMX_ADD_IO_SEG(0x0001180006001638ull))
|
||||||
|
#define CVMX_RST_CTLX(offset) (CVMX_ADD_IO_SEG(0x0001180006001640ull) + ((offset) & 3) * 8)
|
||||||
|
#define CVMX_RST_DELAY (CVMX_ADD_IO_SEG(0x0001180006001608ull))
|
||||||
|
#define CVMX_RST_ECO (CVMX_ADD_IO_SEG(0x00011800060017B8ull))
|
||||||
|
#define CVMX_RST_INT (CVMX_ADD_IO_SEG(0x0001180006001628ull))
|
||||||
|
#define CVMX_RST_OCX (CVMX_ADD_IO_SEG(0x0001180006001618ull))
|
||||||
|
#define CVMX_RST_POWER_DBG (CVMX_ADD_IO_SEG(0x0001180006001708ull))
|
||||||
|
#define CVMX_RST_PP_POWER (CVMX_ADD_IO_SEG(0x0001180006001700ull))
|
||||||
|
#define CVMX_RST_SOFT_PRSTX(offset) (CVMX_ADD_IO_SEG(0x00011800060016C0ull) + ((offset) & 3) * 8)
|
||||||
|
#define CVMX_RST_SOFT_RST (CVMX_ADD_IO_SEG(0x0001180006001680ull))
|
||||||
|
|
||||||
|
union cvmx_rst_boot {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_boot_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t chipkill:1;
|
||||||
|
uint64_t jtcsrdis:1;
|
||||||
|
uint64_t ejtagdis:1;
|
||||||
|
uint64_t romen:1;
|
||||||
|
uint64_t ckill_ppdis:1;
|
||||||
|
uint64_t jt_tstmode:1;
|
||||||
|
uint64_t vrm_err:1;
|
||||||
|
uint64_t reserved_37_56:20;
|
||||||
|
uint64_t c_mul:7;
|
||||||
|
uint64_t pnr_mul:6;
|
||||||
|
uint64_t reserved_21_23:3;
|
||||||
|
uint64_t lboot_oci:3;
|
||||||
|
uint64_t lboot_ext:6;
|
||||||
|
uint64_t lboot:10;
|
||||||
|
uint64_t rboot:1;
|
||||||
|
uint64_t rboot_pin:1;
|
||||||
|
#else
|
||||||
|
uint64_t rboot_pin:1;
|
||||||
|
uint64_t rboot:1;
|
||||||
|
uint64_t lboot:10;
|
||||||
|
uint64_t lboot_ext:6;
|
||||||
|
uint64_t lboot_oci:3;
|
||||||
|
uint64_t reserved_21_23:3;
|
||||||
|
uint64_t pnr_mul:6;
|
||||||
|
uint64_t c_mul:7;
|
||||||
|
uint64_t reserved_37_56:20;
|
||||||
|
uint64_t vrm_err:1;
|
||||||
|
uint64_t jt_tstmode:1;
|
||||||
|
uint64_t ckill_ppdis:1;
|
||||||
|
uint64_t romen:1;
|
||||||
|
uint64_t ejtagdis:1;
|
||||||
|
uint64_t jtcsrdis:1;
|
||||||
|
uint64_t chipkill:1;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_boot_s cn70xx;
|
||||||
|
struct cvmx_rst_boot_s cn70xxp1;
|
||||||
|
struct cvmx_rst_boot_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_cfg {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_cfg_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t bist_delay:58;
|
||||||
|
uint64_t reserved_3_5:3;
|
||||||
|
uint64_t cntl_clr_bist:1;
|
||||||
|
uint64_t warm_clr_bist:1;
|
||||||
|
uint64_t soft_clr_bist:1;
|
||||||
|
#else
|
||||||
|
uint64_t soft_clr_bist:1;
|
||||||
|
uint64_t warm_clr_bist:1;
|
||||||
|
uint64_t cntl_clr_bist:1;
|
||||||
|
uint64_t reserved_3_5:3;
|
||||||
|
uint64_t bist_delay:58;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_cfg_s cn70xx;
|
||||||
|
struct cvmx_rst_cfg_s cn70xxp1;
|
||||||
|
struct cvmx_rst_cfg_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_ckill {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_ckill_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_47_63:17;
|
||||||
|
uint64_t timer:47;
|
||||||
|
#else
|
||||||
|
uint64_t timer:47;
|
||||||
|
uint64_t reserved_47_63:17;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_ckill_s cn70xx;
|
||||||
|
struct cvmx_rst_ckill_s cn70xxp1;
|
||||||
|
struct cvmx_rst_ckill_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_ctlx {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_ctlx_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_10_63:54;
|
||||||
|
uint64_t prst_link:1;
|
||||||
|
uint64_t rst_done:1;
|
||||||
|
uint64_t rst_link:1;
|
||||||
|
uint64_t host_mode:1;
|
||||||
|
uint64_t reserved_4_5:2;
|
||||||
|
uint64_t rst_drv:1;
|
||||||
|
uint64_t rst_rcv:1;
|
||||||
|
uint64_t rst_chip:1;
|
||||||
|
uint64_t rst_val:1;
|
||||||
|
#else
|
||||||
|
uint64_t rst_val:1;
|
||||||
|
uint64_t rst_chip:1;
|
||||||
|
uint64_t rst_rcv:1;
|
||||||
|
uint64_t rst_drv:1;
|
||||||
|
uint64_t reserved_4_5:2;
|
||||||
|
uint64_t host_mode:1;
|
||||||
|
uint64_t rst_link:1;
|
||||||
|
uint64_t rst_done:1;
|
||||||
|
uint64_t prst_link:1;
|
||||||
|
uint64_t reserved_10_63:54;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_ctlx_s cn70xx;
|
||||||
|
struct cvmx_rst_ctlx_s cn70xxp1;
|
||||||
|
struct cvmx_rst_ctlx_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_delay {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_delay_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_32_63:32;
|
||||||
|
uint64_t warm_rst_dly:16;
|
||||||
|
uint64_t soft_rst_dly:16;
|
||||||
|
#else
|
||||||
|
uint64_t soft_rst_dly:16;
|
||||||
|
uint64_t warm_rst_dly:16;
|
||||||
|
uint64_t reserved_32_63:32;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_delay_s cn70xx;
|
||||||
|
struct cvmx_rst_delay_s cn70xxp1;
|
||||||
|
struct cvmx_rst_delay_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_eco {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_eco_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_32_63:32;
|
||||||
|
uint64_t eco_rw:32;
|
||||||
|
#else
|
||||||
|
uint64_t eco_rw:32;
|
||||||
|
uint64_t reserved_32_63:32;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_eco_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_int {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_int_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_12_63:52;
|
||||||
|
uint64_t perst:4;
|
||||||
|
uint64_t reserved_4_7:4;
|
||||||
|
uint64_t rst_link:4;
|
||||||
|
#else
|
||||||
|
uint64_t rst_link:4;
|
||||||
|
uint64_t reserved_4_7:4;
|
||||||
|
uint64_t perst:4;
|
||||||
|
uint64_t reserved_12_63:52;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_int_cn70xx {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_11_63:53;
|
||||||
|
uint64_t perst:3;
|
||||||
|
uint64_t reserved_3_7:5;
|
||||||
|
uint64_t rst_link:3;
|
||||||
|
#else
|
||||||
|
uint64_t rst_link:3;
|
||||||
|
uint64_t reserved_3_7:5;
|
||||||
|
uint64_t perst:3;
|
||||||
|
uint64_t reserved_11_63:53;
|
||||||
|
#endif
|
||||||
|
} cn70xx;
|
||||||
|
struct cvmx_rst_int_cn70xx cn70xxp1;
|
||||||
|
struct cvmx_rst_int_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_ocx {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_ocx_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_3_63:61;
|
||||||
|
uint64_t rst_link:3;
|
||||||
|
#else
|
||||||
|
uint64_t rst_link:3;
|
||||||
|
uint64_t reserved_3_63:61;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_ocx_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_power_dbg {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_power_dbg_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_3_63:61;
|
||||||
|
uint64_t str:3;
|
||||||
|
#else
|
||||||
|
uint64_t str:3;
|
||||||
|
uint64_t reserved_3_63:61;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_power_dbg_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_pp_power {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_pp_power_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_48_63:16;
|
||||||
|
uint64_t gate:48;
|
||||||
|
#else
|
||||||
|
uint64_t gate:48;
|
||||||
|
uint64_t reserved_48_63:16;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_pp_power_cn70xx {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_4_63:60;
|
||||||
|
uint64_t gate:4;
|
||||||
|
#else
|
||||||
|
uint64_t gate:4;
|
||||||
|
uint64_t reserved_4_63:60;
|
||||||
|
#endif
|
||||||
|
} cn70xx;
|
||||||
|
struct cvmx_rst_pp_power_cn70xx cn70xxp1;
|
||||||
|
struct cvmx_rst_pp_power_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_soft_prstx {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_soft_prstx_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_1_63:63;
|
||||||
|
uint64_t soft_prst:1;
|
||||||
|
#else
|
||||||
|
uint64_t soft_prst:1;
|
||||||
|
uint64_t reserved_1_63:63;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_soft_prstx_s cn70xx;
|
||||||
|
struct cvmx_rst_soft_prstx_s cn70xxp1;
|
||||||
|
struct cvmx_rst_soft_prstx_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
union cvmx_rst_soft_rst {
|
||||||
|
uint64_t u64;
|
||||||
|
struct cvmx_rst_soft_rst_s {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
|
uint64_t reserved_1_63:63;
|
||||||
|
uint64_t soft_rst:1;
|
||||||
|
#else
|
||||||
|
uint64_t soft_rst:1;
|
||||||
|
uint64_t reserved_1_63:63;
|
||||||
|
#endif
|
||||||
|
} s;
|
||||||
|
struct cvmx_rst_soft_rst_s cn70xx;
|
||||||
|
struct cvmx_rst_soft_rst_s cn70xxp1;
|
||||||
|
struct cvmx_rst_soft_rst_s cn78xx;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -45,6 +45,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define OCTEON_FAMILY_MASK 0x00ffff00
|
#define OCTEON_FAMILY_MASK 0x00ffff00
|
||||||
|
#define OCTEON_PRID_MASK 0x00ffffff
|
||||||
|
|
||||||
/* Flag bits in top byte */
|
/* Flag bits in top byte */
|
||||||
/* Ignores revision in model checks */
|
/* Ignores revision in model checks */
|
||||||
|
@ -63,11 +64,52 @@
|
||||||
#define OM_MATCH_6XXX_FAMILY_MODELS 0x40000000
|
#define OM_MATCH_6XXX_FAMILY_MODELS 0x40000000
|
||||||
/* Match all cnf7XXX Octeon models. */
|
/* Match all cnf7XXX Octeon models. */
|
||||||
#define OM_MATCH_F7XXX_FAMILY_MODELS 0x80000000
|
#define OM_MATCH_F7XXX_FAMILY_MODELS 0x80000000
|
||||||
|
/* Match all cn7XXX Octeon models. */
|
||||||
|
#define OM_MATCH_7XXX_FAMILY_MODELS 0x10000000
|
||||||
|
#define OM_MATCH_FAMILY_MODELS (OM_MATCH_5XXX_FAMILY_MODELS | \
|
||||||
|
OM_MATCH_6XXX_FAMILY_MODELS | \
|
||||||
|
OM_MATCH_F7XXX_FAMILY_MODELS | \
|
||||||
|
OM_MATCH_7XXX_FAMILY_MODELS)
|
||||||
|
/*
|
||||||
|
* CN7XXX models with new revision encoding
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OCTEON_CN73XX_PASS1_0 0x000d9700
|
||||||
|
#define OCTEON_CN73XX (OCTEON_CN73XX_PASS1_0 | OM_IGNORE_REVISION)
|
||||||
|
#define OCTEON_CN73XX_PASS1_X (OCTEON_CN73XX_PASS1_0 | \
|
||||||
|
OM_IGNORE_MINOR_REVISION)
|
||||||
|
|
||||||
|
#define OCTEON_CN70XX_PASS1_0 0x000d9600
|
||||||
|
#define OCTEON_CN70XX_PASS1_1 0x000d9601
|
||||||
|
#define OCTEON_CN70XX_PASS1_2 0x000d9602
|
||||||
|
|
||||||
|
#define OCTEON_CN70XX_PASS2_0 0x000d9608
|
||||||
|
|
||||||
|
#define OCTEON_CN70XX (OCTEON_CN70XX_PASS1_0 | OM_IGNORE_REVISION)
|
||||||
|
#define OCTEON_CN70XX_PASS1_X (OCTEON_CN70XX_PASS1_0 | \
|
||||||
|
OM_IGNORE_MINOR_REVISION)
|
||||||
|
#define OCTEON_CN70XX_PASS2_X (OCTEON_CN70XX_PASS2_0 | \
|
||||||
|
OM_IGNORE_MINOR_REVISION)
|
||||||
|
|
||||||
|
#define OCTEON_CN71XX OCTEON_CN70XX
|
||||||
|
|
||||||
|
#define OCTEON_CN78XX_PASS1_0 0x000d9500
|
||||||
|
#define OCTEON_CN78XX_PASS1_1 0x000d9501
|
||||||
|
#define OCTEON_CN78XX_PASS2_0 0x000d9508
|
||||||
|
|
||||||
|
#define OCTEON_CN78XX (OCTEON_CN78XX_PASS1_0 | OM_IGNORE_REVISION)
|
||||||
|
#define OCTEON_CN78XX_PASS1_X (OCTEON_CN78XX_PASS1_0 | \
|
||||||
|
OM_IGNORE_MINOR_REVISION)
|
||||||
|
#define OCTEON_CN78XX_PASS2_X (OCTEON_CN78XX_PASS2_0 | \
|
||||||
|
OM_IGNORE_MINOR_REVISION)
|
||||||
|
|
||||||
|
#define OCTEON_CN76XX (0x000d9540 | OM_CHECK_SUBMODEL)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CNF7XXX models with new revision encoding
|
* CNF7XXX models with new revision encoding
|
||||||
*/
|
*/
|
||||||
#define OCTEON_CNF71XX_PASS1_0 0x000d9400
|
#define OCTEON_CNF71XX_PASS1_0 0x000d9400
|
||||||
|
#define OCTEON_CNF71XX_PASS1_1 0x000d9401
|
||||||
|
|
||||||
#define OCTEON_CNF71XX (OCTEON_CNF71XX_PASS1_0 | OM_IGNORE_REVISION)
|
#define OCTEON_CNF71XX (OCTEON_CNF71XX_PASS1_0 | OM_IGNORE_REVISION)
|
||||||
#define OCTEON_CNF71XX_PASS1_X (OCTEON_CNF71XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
#define OCTEON_CNF71XX_PASS1_X (OCTEON_CNF71XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
||||||
|
@ -79,6 +121,8 @@
|
||||||
#define OCTEON_CN68XX_PASS1_1 0x000d9101
|
#define OCTEON_CN68XX_PASS1_1 0x000d9101
|
||||||
#define OCTEON_CN68XX_PASS1_2 0x000d9102
|
#define OCTEON_CN68XX_PASS1_2 0x000d9102
|
||||||
#define OCTEON_CN68XX_PASS2_0 0x000d9108
|
#define OCTEON_CN68XX_PASS2_0 0x000d9108
|
||||||
|
#define OCTEON_CN68XX_PASS2_1 0x000d9109
|
||||||
|
#define OCTEON_CN68XX_PASS2_2 0x000d910a
|
||||||
|
|
||||||
#define OCTEON_CN68XX (OCTEON_CN68XX_PASS2_0 | OM_IGNORE_REVISION)
|
#define OCTEON_CN68XX (OCTEON_CN68XX_PASS2_0 | OM_IGNORE_REVISION)
|
||||||
#define OCTEON_CN68XX_PASS1_X (OCTEON_CN68XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
#define OCTEON_CN68XX_PASS1_X (OCTEON_CN68XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
||||||
|
@ -104,11 +148,18 @@
|
||||||
#define OCTEON_CN63XX_PASS1_X (OCTEON_CN63XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
#define OCTEON_CN63XX_PASS1_X (OCTEON_CN63XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
||||||
#define OCTEON_CN63XX_PASS2_X (OCTEON_CN63XX_PASS2_0 | OM_IGNORE_MINOR_REVISION)
|
#define OCTEON_CN63XX_PASS2_X (OCTEON_CN63XX_PASS2_0 | OM_IGNORE_MINOR_REVISION)
|
||||||
|
|
||||||
|
/* CN62XX is same as CN63XX with 1 MB cache */
|
||||||
|
#define OCTEON_CN62XX OCTEON_CN63XX
|
||||||
|
|
||||||
#define OCTEON_CN61XX_PASS1_0 0x000d9300
|
#define OCTEON_CN61XX_PASS1_0 0x000d9300
|
||||||
|
#define OCTEON_CN61XX_PASS1_1 0x000d9301
|
||||||
|
|
||||||
#define OCTEON_CN61XX (OCTEON_CN61XX_PASS1_0 | OM_IGNORE_REVISION)
|
#define OCTEON_CN61XX (OCTEON_CN61XX_PASS1_0 | OM_IGNORE_REVISION)
|
||||||
#define OCTEON_CN61XX_PASS1_X (OCTEON_CN61XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
#define OCTEON_CN61XX_PASS1_X (OCTEON_CN61XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
||||||
|
|
||||||
|
/* CN60XX is same as CN61XX with 512 KB cache */
|
||||||
|
#define OCTEON_CN60XX OCTEON_CN61XX
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CN5XXX models with new revision encoding
|
* CN5XXX models with new revision encoding
|
||||||
*/
|
*/
|
||||||
|
@ -120,7 +171,7 @@
|
||||||
#define OCTEON_CN58XX_PASS2_2 0x000d030a
|
#define OCTEON_CN58XX_PASS2_2 0x000d030a
|
||||||
#define OCTEON_CN58XX_PASS2_3 0x000d030b
|
#define OCTEON_CN58XX_PASS2_3 0x000d030b
|
||||||
|
|
||||||
#define OCTEON_CN58XX (OCTEON_CN58XX_PASS1_0 | OM_IGNORE_REVISION)
|
#define OCTEON_CN58XX (OCTEON_CN58XX_PASS2_0 | OM_IGNORE_REVISION)
|
||||||
#define OCTEON_CN58XX_PASS1_X (OCTEON_CN58XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
#define OCTEON_CN58XX_PASS1_X (OCTEON_CN58XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
|
||||||
#define OCTEON_CN58XX_PASS2_X (OCTEON_CN58XX_PASS2_0 | OM_IGNORE_MINOR_REVISION)
|
#define OCTEON_CN58XX_PASS2_X (OCTEON_CN58XX_PASS2_0 | OM_IGNORE_MINOR_REVISION)
|
||||||
#define OCTEON_CN58XX_PASS1 OCTEON_CN58XX_PASS1_X
|
#define OCTEON_CN58XX_PASS1 OCTEON_CN58XX_PASS1_X
|
||||||
|
@ -217,12 +268,10 @@
|
||||||
#define OCTEON_CN3XXX (OCTEON_CN58XX_PASS1_0 | OM_MATCH_PREVIOUS_MODELS | OM_IGNORE_REVISION)
|
#define OCTEON_CN3XXX (OCTEON_CN58XX_PASS1_0 | OM_MATCH_PREVIOUS_MODELS | OM_IGNORE_REVISION)
|
||||||
#define OCTEON_CN5XXX (OCTEON_CN58XX_PASS1_0 | OM_MATCH_5XXX_FAMILY_MODELS)
|
#define OCTEON_CN5XXX (OCTEON_CN58XX_PASS1_0 | OM_MATCH_5XXX_FAMILY_MODELS)
|
||||||
#define OCTEON_CN6XXX (OCTEON_CN63XX_PASS1_0 | OM_MATCH_6XXX_FAMILY_MODELS)
|
#define OCTEON_CN6XXX (OCTEON_CN63XX_PASS1_0 | OM_MATCH_6XXX_FAMILY_MODELS)
|
||||||
|
#define OCTEON_CNF7XXX (OCTEON_CNF71XX_PASS1_0 | \
|
||||||
/* These are used to cover entire families of OCTEON processors */
|
OM_MATCH_F7XXX_FAMILY_MODELS)
|
||||||
#define OCTEON_FAM_1 (OCTEON_CN3XXX)
|
#define OCTEON_CN7XXX (OCTEON_CN78XX_PASS1_0 | \
|
||||||
#define OCTEON_FAM_PLUS (OCTEON_CN5XXX)
|
OM_MATCH_7XXX_FAMILY_MODELS)
|
||||||
#define OCTEON_FAM_1_PLUS (OCTEON_FAM_PLUS | OM_MATCH_PREVIOUS_MODELS)
|
|
||||||
#define OCTEON_FAM_2 (OCTEON_CN6XXX)
|
|
||||||
|
|
||||||
/* The revision byte (low byte) has two different encodings.
|
/* The revision byte (low byte) has two different encodings.
|
||||||
* CN3XXX:
|
* CN3XXX:
|
||||||
|
@ -232,7 +281,7 @@
|
||||||
* <4>: alternate package
|
* <4>: alternate package
|
||||||
* <3:0>: revision
|
* <3:0>: revision
|
||||||
*
|
*
|
||||||
* CN5XXX:
|
* CN5XXX and older models:
|
||||||
*
|
*
|
||||||
* bits
|
* bits
|
||||||
* <7>: reserved (0)
|
* <7>: reserved (0)
|
||||||
|
@ -251,17 +300,21 @@
|
||||||
/* CN5XXX and later use different layout of bits in the revision ID field */
|
/* CN5XXX and later use different layout of bits in the revision ID field */
|
||||||
#define OCTEON_58XX_FAMILY_MASK OCTEON_38XX_FAMILY_MASK
|
#define OCTEON_58XX_FAMILY_MASK OCTEON_38XX_FAMILY_MASK
|
||||||
#define OCTEON_58XX_FAMILY_REV_MASK 0x00ffff3f
|
#define OCTEON_58XX_FAMILY_REV_MASK 0x00ffff3f
|
||||||
#define OCTEON_58XX_MODEL_MASK 0x00ffffc0
|
#define OCTEON_58XX_MODEL_MASK 0x00ffff40
|
||||||
#define OCTEON_58XX_MODEL_REV_MASK (OCTEON_58XX_FAMILY_REV_MASK | OCTEON_58XX_MODEL_MASK)
|
#define OCTEON_58XX_MODEL_REV_MASK (OCTEON_58XX_FAMILY_REV_MASK | OCTEON_58XX_MODEL_MASK)
|
||||||
#define OCTEON_58XX_MODEL_MINOR_REV_MASK (OCTEON_58XX_MODEL_REV_MASK & 0x00fffff8)
|
#define OCTEON_58XX_MODEL_MINOR_REV_MASK (OCTEON_58XX_MODEL_REV_MASK & 0x00ffff38)
|
||||||
#define OCTEON_5XXX_MODEL_MASK 0x00ff0fc0
|
#define OCTEON_5XXX_MODEL_MASK 0x00ff0fc0
|
||||||
|
|
||||||
/* forward declarations */
|
|
||||||
static inline uint32_t cvmx_get_proc_id(void) __attribute__ ((pure));
|
static inline uint32_t cvmx_get_proc_id(void) __attribute__ ((pure));
|
||||||
static inline uint64_t cvmx_read_csr(uint64_t csr_addr);
|
static inline uint64_t cvmx_read_csr(uint64_t csr_addr);
|
||||||
|
|
||||||
#define __OCTEON_MATCH_MASK__(x, y, z) (((x) & (z)) == ((y) & (z)))
|
#define __OCTEON_MATCH_MASK__(x, y, z) (((x) & (z)) == ((y) & (z)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __OCTEON_IS_MODEL_COMPILE__(arg_model, chip_model)
|
||||||
|
* returns true if chip_model is identical or belong to the OCTEON
|
||||||
|
* model group specified in arg_model.
|
||||||
|
*/
|
||||||
/* NOTE: This for internal use only! */
|
/* NOTE: This for internal use only! */
|
||||||
#define __OCTEON_IS_MODEL_COMPILE__(arg_model, chip_model) \
|
#define __OCTEON_IS_MODEL_COMPILE__(arg_model, chip_model) \
|
||||||
((((arg_model & OCTEON_38XX_FAMILY_MASK) < OCTEON_CN58XX_PASS1_0) && ( \
|
((((arg_model & OCTEON_38XX_FAMILY_MASK) < OCTEON_CN58XX_PASS1_0) && ( \
|
||||||
|
@ -286,11 +339,18 @@ static inline uint64_t cvmx_read_csr(uint64_t csr_addr);
|
||||||
((((arg_model) & (OM_FLAG_MASK)) == OM_IGNORE_REVISION) \
|
((((arg_model) & (OM_FLAG_MASK)) == OM_IGNORE_REVISION) \
|
||||||
&& __OCTEON_MATCH_MASK__((chip_model), (arg_model), OCTEON_58XX_FAMILY_MASK)) || \
|
&& __OCTEON_MATCH_MASK__((chip_model), (arg_model), OCTEON_58XX_FAMILY_MASK)) || \
|
||||||
((((arg_model) & (OM_FLAG_MASK)) == OM_CHECK_SUBMODEL) \
|
((((arg_model) & (OM_FLAG_MASK)) == OM_CHECK_SUBMODEL) \
|
||||||
&& __OCTEON_MATCH_MASK__((chip_model), (arg_model), OCTEON_58XX_MODEL_REV_MASK)) || \
|
&& __OCTEON_MATCH_MASK__((chip_model), (arg_model), OCTEON_58XX_MODEL_MASK)) || \
|
||||||
((((arg_model) & (OM_MATCH_5XXX_FAMILY_MODELS)) == OM_MATCH_5XXX_FAMILY_MODELS) \
|
((((arg_model) & (OM_MATCH_5XXX_FAMILY_MODELS)) == OM_MATCH_5XXX_FAMILY_MODELS) \
|
||||||
&& ((chip_model) >= OCTEON_CN58XX_PASS1_0) && ((chip_model) < OCTEON_CN63XX_PASS1_0)) || \
|
&& ((chip_model & OCTEON_PRID_MASK) >= OCTEON_CN58XX_PASS1_0) \
|
||||||
|
&& ((chip_model & OCTEON_PRID_MASK) < OCTEON_CN63XX_PASS1_0)) || \
|
||||||
((((arg_model) & (OM_MATCH_6XXX_FAMILY_MODELS)) == OM_MATCH_6XXX_FAMILY_MODELS) \
|
((((arg_model) & (OM_MATCH_6XXX_FAMILY_MODELS)) == OM_MATCH_6XXX_FAMILY_MODELS) \
|
||||||
&& ((chip_model) >= OCTEON_CN63XX_PASS1_0)) || \
|
&& ((chip_model & OCTEON_PRID_MASK) >= OCTEON_CN63XX_PASS1_0) \
|
||||||
|
&& ((chip_model & OCTEON_PRID_MASK) < OCTEON_CNF71XX_PASS1_0)) || \
|
||||||
|
((((arg_model) & (OM_MATCH_F7XXX_FAMILY_MODELS)) == OM_MATCH_F7XXX_FAMILY_MODELS) \
|
||||||
|
&& ((chip_model & OCTEON_PRID_MASK) >= OCTEON_CNF71XX_PASS1_0) \
|
||||||
|
&& ((chip_model & OCTEON_PRID_MASK) < OCTEON_CN78XX_PASS1_0)) || \
|
||||||
|
((((arg_model) & (OM_MATCH_7XXX_FAMILY_MODELS)) == OM_MATCH_7XXX_FAMILY_MODELS) \
|
||||||
|
&& ((chip_model & OCTEON_PRID_MASK) >= OCTEON_CN78XX_PASS1_0)) || \
|
||||||
((((arg_model) & (OM_MATCH_PREVIOUS_MODELS)) == OM_MATCH_PREVIOUS_MODELS) \
|
((((arg_model) & (OM_MATCH_PREVIOUS_MODELS)) == OM_MATCH_PREVIOUS_MODELS) \
|
||||||
&& (((chip_model) & OCTEON_58XX_MODEL_MASK) < ((arg_model) & OCTEON_58XX_MODEL_MASK))) \
|
&& (((chip_model) & OCTEON_58XX_MODEL_MASK) < ((arg_model) & OCTEON_58XX_MODEL_MASK))) \
|
||||||
)))
|
)))
|
||||||
|
@ -300,14 +360,6 @@ static inline int __octeon_is_model_runtime__(uint32_t model)
|
||||||
{
|
{
|
||||||
uint32_t cpuid = cvmx_get_proc_id();
|
uint32_t cpuid = cvmx_get_proc_id();
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for special case of mismarked 3005 samples. We only
|
|
||||||
* need to check if the sub model isn't being ignored
|
|
||||||
*/
|
|
||||||
if ((model & OM_CHECK_SUBMODEL) == OM_CHECK_SUBMODEL) {
|
|
||||||
if (cpuid == OCTEON_CN3010_PASS1 && (cvmx_read_csr(0x80011800800007B8ull) & (1ull << 34)))
|
|
||||||
cpuid |= 0x10;
|
|
||||||
}
|
|
||||||
return __OCTEON_IS_MODEL_COMPILE__(model, cpuid);
|
return __OCTEON_IS_MODEL_COMPILE__(model, cpuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,10 +378,21 @@ static inline int __octeon_is_model_runtime__(uint32_t model)
|
||||||
#define OCTEON_IS_COMMON_BINARY() 1
|
#define OCTEON_IS_COMMON_BINARY() 1
|
||||||
#undef OCTEON_MODEL
|
#undef OCTEON_MODEL
|
||||||
|
|
||||||
|
#define OCTEON_IS_OCTEON1() OCTEON_IS_MODEL(OCTEON_CN3XXX)
|
||||||
|
#define OCTEON_IS_OCTEONPLUS() OCTEON_IS_MODEL(OCTEON_CN5XXX)
|
||||||
|
#define OCTEON_IS_OCTEON2() \
|
||||||
|
(OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
|
||||||
|
|
||||||
|
#define OCTEON_IS_OCTEON3() OCTEON_IS_MODEL(OCTEON_CN7XXX)
|
||||||
|
|
||||||
|
#define OCTEON_IS_OCTEON1PLUS() (OCTEON_IS_OCTEON1() || OCTEON_IS_OCTEONPLUS())
|
||||||
|
|
||||||
const char *__init octeon_model_get_string(uint32_t chip_id);
|
const char *__init octeon_model_get_string(uint32_t chip_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the octeon family, i.e., ProcessorID of the PrID register.
|
* Return the octeon family, i.e., ProcessorID of the PrID register.
|
||||||
|
*
|
||||||
|
* @return the octeon family on success, ((unint32_t)-1) on error.
|
||||||
*/
|
*/
|
||||||
static inline uint32_t cvmx_get_octeon_family(void)
|
static inline uint32_t cvmx_get_octeon_family(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#define __ASM_OCTEON_OCTEON_H
|
#define __ASM_OCTEON_OCTEON_H
|
||||||
|
|
||||||
#include <asm/octeon/cvmx.h>
|
#include <asm/octeon/cvmx.h>
|
||||||
|
#include <asm/bitfield.h>
|
||||||
|
|
||||||
extern uint64_t octeon_bootmem_alloc_range_phys(uint64_t size,
|
extern uint64_t octeon_bootmem_alloc_range_phys(uint64_t size,
|
||||||
uint64_t alignment,
|
uint64_t alignment,
|
||||||
|
@ -53,6 +54,7 @@ extern void octeon_io_clk_delay(unsigned long);
|
||||||
#define OCTOEN_SERIAL_LEN 20
|
#define OCTOEN_SERIAL_LEN 20
|
||||||
|
|
||||||
struct octeon_boot_descriptor {
|
struct octeon_boot_descriptor {
|
||||||
|
#ifdef __BIG_ENDIAN_BITFIELD
|
||||||
/* Start of block referenced by assembly code - do not change! */
|
/* Start of block referenced by assembly code - do not change! */
|
||||||
uint32_t desc_version;
|
uint32_t desc_version;
|
||||||
uint32_t desc_size;
|
uint32_t desc_size;
|
||||||
|
@ -104,77 +106,149 @@ struct octeon_boot_descriptor {
|
||||||
uint8_t mac_addr_base[6];
|
uint8_t mac_addr_base[6];
|
||||||
uint8_t mac_addr_count;
|
uint8_t mac_addr_count;
|
||||||
uint64_t cvmx_desc_vaddr;
|
uint64_t cvmx_desc_vaddr;
|
||||||
|
#else
|
||||||
|
uint32_t desc_size;
|
||||||
|
uint32_t desc_version;
|
||||||
|
uint64_t stack_top;
|
||||||
|
uint64_t heap_base;
|
||||||
|
uint64_t heap_end;
|
||||||
|
/* Only used by bootloader */
|
||||||
|
uint64_t entry_point;
|
||||||
|
uint64_t desc_vaddr;
|
||||||
|
/* End of This block referenced by assembly code - do not change! */
|
||||||
|
uint32_t stack_size;
|
||||||
|
uint32_t exception_base_addr;
|
||||||
|
uint32_t argc;
|
||||||
|
uint32_t heap_size;
|
||||||
|
/*
|
||||||
|
* Argc count for application.
|
||||||
|
* Warning low bit scrambled in little-endian.
|
||||||
|
*/
|
||||||
|
uint32_t argv[OCTEON_ARGV_MAX_ARGS];
|
||||||
|
|
||||||
|
#define BOOT_FLAG_INIT_CORE (1 << 0)
|
||||||
|
#define OCTEON_BL_FLAG_DEBUG (1 << 1)
|
||||||
|
#define OCTEON_BL_FLAG_NO_MAGIC (1 << 2)
|
||||||
|
/* If set, use uart1 for console */
|
||||||
|
#define OCTEON_BL_FLAG_CONSOLE_UART1 (1 << 3)
|
||||||
|
/* If set, use PCI console */
|
||||||
|
#define OCTEON_BL_FLAG_CONSOLE_PCI (1 << 4)
|
||||||
|
/* Call exit on break on serial port */
|
||||||
|
#define OCTEON_BL_FLAG_BREAK (1 << 5)
|
||||||
|
|
||||||
|
uint32_t core_mask;
|
||||||
|
uint32_t flags;
|
||||||
|
/* physical address of free memory descriptor block. */
|
||||||
|
uint32_t phy_mem_desc_addr;
|
||||||
|
/* DRAM size in megabyes. */
|
||||||
|
uint32_t dram_size;
|
||||||
|
/* CPU clock speed, in hz. */
|
||||||
|
uint32_t eclock_hz;
|
||||||
|
/* used to pass flags from app to debugger. */
|
||||||
|
uint32_t debugger_flags_base_addr;
|
||||||
|
/* SPI4 clock in hz. */
|
||||||
|
uint32_t spi_clock_hz;
|
||||||
|
/* DRAM clock speed, in hz. */
|
||||||
|
uint32_t dclock_hz;
|
||||||
|
uint8_t chip_rev_minor;
|
||||||
|
uint8_t chip_rev_major;
|
||||||
|
uint16_t chip_type;
|
||||||
|
uint8_t board_rev_minor;
|
||||||
|
uint8_t board_rev_major;
|
||||||
|
uint16_t board_type;
|
||||||
|
|
||||||
|
uint64_t unused1[4]; /* Not even filled in by bootloader. */
|
||||||
|
|
||||||
|
uint64_t cvmx_desc_vaddr;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
union octeon_cvmemctl {
|
union octeon_cvmemctl {
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
struct {
|
struct {
|
||||||
/* RO 1 = BIST fail, 0 = BIST pass */
|
/* RO 1 = BIST fail, 0 = BIST pass */
|
||||||
uint64_t tlbbist:1;
|
__BITFIELD_FIELD(uint64_t tlbbist:1,
|
||||||
/* RO 1 = BIST fail, 0 = BIST pass */
|
/* RO 1 = BIST fail, 0 = BIST pass */
|
||||||
uint64_t l1cbist:1;
|
__BITFIELD_FIELD(uint64_t l1cbist:1,
|
||||||
/* RO 1 = BIST fail, 0 = BIST pass */
|
/* RO 1 = BIST fail, 0 = BIST pass */
|
||||||
uint64_t l1dbist:1;
|
__BITFIELD_FIELD(uint64_t l1dbist:1,
|
||||||
/* RO 1 = BIST fail, 0 = BIST pass */
|
/* RO 1 = BIST fail, 0 = BIST pass */
|
||||||
uint64_t dcmbist:1;
|
__BITFIELD_FIELD(uint64_t dcmbist:1,
|
||||||
/* RO 1 = BIST fail, 0 = BIST pass */
|
/* RO 1 = BIST fail, 0 = BIST pass */
|
||||||
uint64_t ptgbist:1;
|
__BITFIELD_FIELD(uint64_t ptgbist:1,
|
||||||
/* RO 1 = BIST fail, 0 = BIST pass */
|
/* RO 1 = BIST fail, 0 = BIST pass */
|
||||||
uint64_t wbfbist:1;
|
__BITFIELD_FIELD(uint64_t wbfbist:1,
|
||||||
/* Reserved */
|
/* Reserved */
|
||||||
uint64_t reserved:22;
|
__BITFIELD_FIELD(uint64_t reserved:17,
|
||||||
|
/* OCTEON II - TLB replacement policy: 0 = bitmask LRU; 1 = NLU.
|
||||||
|
* This field selects between the TLB replacement policies:
|
||||||
|
* bitmask LRU or NLU. Bitmask LRU maintains a mask of
|
||||||
|
* recently used TLB entries and avoids them as new entries
|
||||||
|
* are allocated. NLU simply guarantees that the next
|
||||||
|
* allocation is not the last used TLB entry. */
|
||||||
|
__BITFIELD_FIELD(uint64_t tlbnlu:1,
|
||||||
|
/* OCTEON II - Selects the bit in the counter used for
|
||||||
|
* releasing a PAUSE. This counter trips every 2(8+PAUSETIME)
|
||||||
|
* cycles. If not already released, the cnMIPS II core will
|
||||||
|
* always release a given PAUSE instruction within
|
||||||
|
* 2(8+PAUSETIME). If the counter trip happens to line up,
|
||||||
|
* the cnMIPS II core may release the PAUSE instantly. */
|
||||||
|
__BITFIELD_FIELD(uint64_t pausetime:3,
|
||||||
|
/* OCTEON II - This field is an extension of
|
||||||
|
* CvmMemCtl[DIDTTO] */
|
||||||
|
__BITFIELD_FIELD(uint64_t didtto2:1,
|
||||||
/* R/W If set, marked write-buffer entries time out
|
/* R/W If set, marked write-buffer entries time out
|
||||||
* the same as as other entries; if clear, marked
|
* the same as as other entries; if clear, marked
|
||||||
* write-buffer entries use the maximum timeout. */
|
* write-buffer entries use the maximum timeout. */
|
||||||
uint64_t dismarkwblongto:1;
|
__BITFIELD_FIELD(uint64_t dismarkwblongto:1,
|
||||||
/* R/W If set, a merged store does not clear the
|
/* R/W If set, a merged store does not clear the
|
||||||
* write-buffer entry timeout state. */
|
* write-buffer entry timeout state. */
|
||||||
uint64_t dismrgclrwbto:1;
|
__BITFIELD_FIELD(uint64_t dismrgclrwbto:1,
|
||||||
/* R/W Two bits that are the MSBs of the resultant
|
/* R/W Two bits that are the MSBs of the resultant
|
||||||
* CVMSEG LM word location for an IOBDMA. The other 8
|
* CVMSEG LM word location for an IOBDMA. The other 8
|
||||||
* bits come from the SCRADDR field of the IOBDMA. */
|
* bits come from the SCRADDR field of the IOBDMA. */
|
||||||
uint64_t iobdmascrmsb:2;
|
__BITFIELD_FIELD(uint64_t iobdmascrmsb:2,
|
||||||
/* R/W If set, SYNCWS and SYNCS only order marked
|
/* R/W If set, SYNCWS and SYNCS only order marked
|
||||||
* stores; if clear, SYNCWS and SYNCS only order
|
* stores; if clear, SYNCWS and SYNCS only order
|
||||||
* unmarked stores. SYNCWSMARKED has no effect when
|
* unmarked stores. SYNCWSMARKED has no effect when
|
||||||
* DISSYNCWS is set. */
|
* DISSYNCWS is set. */
|
||||||
uint64_t syncwsmarked:1;
|
__BITFIELD_FIELD(uint64_t syncwsmarked:1,
|
||||||
/* R/W If set, SYNCWS acts as SYNCW and SYNCS acts as
|
/* R/W If set, SYNCWS acts as SYNCW and SYNCS acts as
|
||||||
* SYNC. */
|
* SYNC. */
|
||||||
uint64_t dissyncws:1;
|
__BITFIELD_FIELD(uint64_t dissyncws:1,
|
||||||
/* R/W If set, no stall happens on write buffer
|
/* R/W If set, no stall happens on write buffer
|
||||||
* full. */
|
* full. */
|
||||||
uint64_t diswbfst:1;
|
__BITFIELD_FIELD(uint64_t diswbfst:1,
|
||||||
/* R/W If set (and SX set), supervisor-level
|
/* R/W If set (and SX set), supervisor-level
|
||||||
* loads/stores can use XKPHYS addresses with
|
* loads/stores can use XKPHYS addresses with
|
||||||
* VA<48>==0 */
|
* VA<48>==0 */
|
||||||
uint64_t xkmemenas:1;
|
__BITFIELD_FIELD(uint64_t xkmemenas:1,
|
||||||
/* R/W If set (and UX set), user-level loads/stores
|
/* R/W If set (and UX set), user-level loads/stores
|
||||||
* can use XKPHYS addresses with VA<48>==0 */
|
* can use XKPHYS addresses with VA<48>==0 */
|
||||||
uint64_t xkmemenau:1;
|
__BITFIELD_FIELD(uint64_t xkmemenau:1,
|
||||||
/* R/W If set (and SX set), supervisor-level
|
/* R/W If set (and SX set), supervisor-level
|
||||||
* loads/stores can use XKPHYS addresses with
|
* loads/stores can use XKPHYS addresses with
|
||||||
* VA<48>==1 */
|
* VA<48>==1 */
|
||||||
uint64_t xkioenas:1;
|
__BITFIELD_FIELD(uint64_t xkioenas:1,
|
||||||
/* R/W If set (and UX set), user-level loads/stores
|
/* R/W If set (and UX set), user-level loads/stores
|
||||||
* can use XKPHYS addresses with VA<48>==1 */
|
* can use XKPHYS addresses with VA<48>==1 */
|
||||||
uint64_t xkioenau:1;
|
__BITFIELD_FIELD(uint64_t xkioenau:1,
|
||||||
/* R/W If set, all stores act as SYNCW (NOMERGE must
|
/* R/W If set, all stores act as SYNCW (NOMERGE must
|
||||||
* be set when this is set) RW, reset to 0. */
|
* be set when this is set) RW, reset to 0. */
|
||||||
uint64_t allsyncw:1;
|
__BITFIELD_FIELD(uint64_t allsyncw:1,
|
||||||
/* R/W If set, no stores merge, and all stores reach
|
/* R/W If set, no stores merge, and all stores reach
|
||||||
* the coherent bus in order. */
|
* the coherent bus in order. */
|
||||||
uint64_t nomerge:1;
|
__BITFIELD_FIELD(uint64_t nomerge:1,
|
||||||
/* R/W Selects the bit in the counter used for DID
|
/* R/W Selects the bit in the counter used for DID
|
||||||
* time-outs 0 = 231, 1 = 230, 2 = 229, 3 =
|
* time-outs 0 = 231, 1 = 230, 2 = 229, 3 =
|
||||||
* 214. Actual time-out is between 1x and 2x this
|
* 214. Actual time-out is between 1x and 2x this
|
||||||
* interval. For example, with DIDTTO=3, expiration
|
* interval. For example, with DIDTTO=3, expiration
|
||||||
* interval is between 16K and 32K. */
|
* interval is between 16K and 32K. */
|
||||||
uint64_t didtto:2;
|
__BITFIELD_FIELD(uint64_t didtto:2,
|
||||||
/* R/W If set, the (mem) CSR clock never turns off. */
|
/* R/W If set, the (mem) CSR clock never turns off. */
|
||||||
uint64_t csrckalwys:1;
|
__BITFIELD_FIELD(uint64_t csrckalwys:1,
|
||||||
/* R/W If set, mclk never turns off. */
|
/* R/W If set, mclk never turns off. */
|
||||||
uint64_t mclkalwys:1;
|
__BITFIELD_FIELD(uint64_t mclkalwys:1,
|
||||||
/* R/W Selects the bit in the counter used for write
|
/* R/W Selects the bit in the counter used for write
|
||||||
* buffer flush time-outs (WBFLT+11) is the bit
|
* buffer flush time-outs (WBFLT+11) is the bit
|
||||||
* position in an internal counter used to determine
|
* position in an internal counter used to determine
|
||||||
|
@ -182,25 +256,26 @@ union octeon_cvmemctl {
|
||||||
* 2x this interval. For example, with WBFLT = 0, a
|
* 2x this interval. For example, with WBFLT = 0, a
|
||||||
* write buffer expires between 2K and 4K cycles after
|
* write buffer expires between 2K and 4K cycles after
|
||||||
* the write buffer entry is allocated. */
|
* the write buffer entry is allocated. */
|
||||||
uint64_t wbfltime:3;
|
__BITFIELD_FIELD(uint64_t wbfltime:3,
|
||||||
/* R/W If set, do not put Istream in the L2 cache. */
|
/* R/W If set, do not put Istream in the L2 cache. */
|
||||||
uint64_t istrnol2:1;
|
__BITFIELD_FIELD(uint64_t istrnol2:1,
|
||||||
/* R/W The write buffer threshold. */
|
/* R/W The write buffer threshold. */
|
||||||
uint64_t wbthresh:4;
|
__BITFIELD_FIELD(uint64_t wbthresh:4,
|
||||||
/* Reserved */
|
/* Reserved */
|
||||||
uint64_t reserved2:2;
|
__BITFIELD_FIELD(uint64_t reserved2:2,
|
||||||
/* R/W If set, CVMSEG is available for loads/stores in
|
/* R/W If set, CVMSEG is available for loads/stores in
|
||||||
* kernel/debug mode. */
|
* kernel/debug mode. */
|
||||||
uint64_t cvmsegenak:1;
|
__BITFIELD_FIELD(uint64_t cvmsegenak:1,
|
||||||
/* R/W If set, CVMSEG is available for loads/stores in
|
/* R/W If set, CVMSEG is available for loads/stores in
|
||||||
* supervisor mode. */
|
* supervisor mode. */
|
||||||
uint64_t cvmsegenas:1;
|
__BITFIELD_FIELD(uint64_t cvmsegenas:1,
|
||||||
/* R/W If set, CVMSEG is available for loads/stores in
|
/* R/W If set, CVMSEG is available for loads/stores in
|
||||||
* user mode. */
|
* user mode. */
|
||||||
uint64_t cvmsegenau:1;
|
__BITFIELD_FIELD(uint64_t cvmsegenau:1,
|
||||||
/* R/W Size of local memory in cache blocks, 54 (6912
|
/* R/W Size of local memory in cache blocks, 54 (6912
|
||||||
* bytes) is max legal value. */
|
* bytes) is max legal value. */
|
||||||
uint64_t lmemsz:6;
|
__BITFIELD_FIELD(uint64_t lmemsz:6,
|
||||||
|
;)))))))))))))))))))))))))))))))))
|
||||||
} s;
|
} s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -224,6 +299,19 @@ static inline void octeon_npi_write32(uint64_t address, uint32_t val)
|
||||||
cvmx_read64_uint32(address ^ 4);
|
cvmx_read64_uint32(address ^ 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Octeon multiplier save/restore routines from octeon_switch.S */
|
||||||
|
void octeon_mult_save(void);
|
||||||
|
void octeon_mult_restore(void);
|
||||||
|
void octeon_mult_save_end(void);
|
||||||
|
void octeon_mult_restore_end(void);
|
||||||
|
void octeon_mult_save3(void);
|
||||||
|
void octeon_mult_save3_end(void);
|
||||||
|
void octeon_mult_save2(void);
|
||||||
|
void octeon_mult_save2_end(void);
|
||||||
|
void octeon_mult_restore3(void);
|
||||||
|
void octeon_mult_restore3_end(void);
|
||||||
|
void octeon_mult_restore2(void);
|
||||||
|
void octeon_mult_restore2_end(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a 32bit value from the Octeon NPI register space
|
* Read a 32bit value from the Octeon NPI register space
|
||||||
|
|
|
@ -121,6 +121,7 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI_DOMAINS
|
||||||
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
|
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
|
||||||
|
|
||||||
static inline int pci_proc_domain(struct pci_bus *bus)
|
static inline int pci_proc_domain(struct pci_bus *bus)
|
||||||
|
@ -128,6 +129,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
|
||||||
struct pci_controller *hose = bus->sysdata;
|
struct pci_controller *hose = bus->sysdata;
|
||||||
return hose->need_domain_info;
|
return hose->need_domain_info;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_PCI_DOMAINS */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
|
#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following bits are directly used by the TLB hardware
|
* The following bits are implemented by the TLB hardware
|
||||||
*/
|
*/
|
||||||
#define _PAGE_GLOBAL_SHIFT 0
|
#define _PAGE_GLOBAL_SHIFT 0
|
||||||
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
||||||
|
@ -60,43 +60,40 @@
|
||||||
#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1)
|
#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1)
|
||||||
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
|
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
|
||||||
|
|
||||||
#define _PAGE_SILENT_READ _PAGE_VALID
|
|
||||||
#define _PAGE_SILENT_WRITE _PAGE_DIRTY
|
|
||||||
|
|
||||||
#define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3)
|
#define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3)
|
||||||
|
|
||||||
#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
|
#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following are implemented by software
|
* The following bits are implemented in software
|
||||||
*/
|
*/
|
||||||
#define _PAGE_PRESENT_SHIFT 0
|
#define _PAGE_PRESENT_SHIFT (0)
|
||||||
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
|
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
|
||||||
#define _PAGE_READ_SHIFT 1
|
#define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1)
|
||||||
#define _PAGE_READ (1 << _PAGE_READ_SHIFT)
|
#define _PAGE_READ (1 << _PAGE_READ_SHIFT)
|
||||||
#define _PAGE_WRITE_SHIFT 2
|
#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1)
|
||||||
#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
|
#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
|
||||||
#define _PAGE_ACCESSED_SHIFT 3
|
#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1)
|
||||||
#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
|
#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
|
||||||
#define _PAGE_MODIFIED_SHIFT 4
|
#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1)
|
||||||
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
|
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* And these are the hardware TLB bits
|
* The following bits are implemented by the TLB hardware
|
||||||
*/
|
*/
|
||||||
#define _PAGE_GLOBAL_SHIFT 8
|
#define _PAGE_GLOBAL_SHIFT (_PAGE_MODIFIED_SHIFT + 4)
|
||||||
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
||||||
#define _PAGE_VALID_SHIFT 9
|
#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1)
|
||||||
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
|
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
|
||||||
#define _PAGE_SILENT_READ (1 << _PAGE_VALID_SHIFT) /* synonym */
|
#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1)
|
||||||
#define _PAGE_DIRTY_SHIFT 10
|
|
||||||
#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT)
|
#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT)
|
||||||
#define _PAGE_SILENT_WRITE (1 << _PAGE_DIRTY_SHIFT)
|
#define _CACHE_UNCACHED_SHIFT (_PAGE_DIRTY_SHIFT + 1)
|
||||||
#define _CACHE_UNCACHED_SHIFT 11
|
|
||||||
#define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT)
|
#define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT)
|
||||||
#define _CACHE_MASK (1 << _CACHE_UNCACHED_SHIFT)
|
#define _CACHE_MASK _CACHE_UNCACHED
|
||||||
|
|
||||||
#else /* 'Normal' r4K case */
|
#define _PFN_SHIFT PAGE_SHIFT
|
||||||
|
|
||||||
|
#else
|
||||||
/*
|
/*
|
||||||
* When using the RI/XI bit support, we have 13 bits of flags below
|
* When using the RI/XI bit support, we have 13 bits of flags below
|
||||||
* the physical address. The RI/XI bits are placed such that a SRL 5
|
* the physical address. The RI/XI bits are placed such that a SRL 5
|
||||||
|
@ -107,10 +104,8 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following bits are implemented in software
|
* The following bits are implemented in software
|
||||||
*
|
|
||||||
* _PAGE_READ / _PAGE_READ_SHIFT should be unused if cpu_has_rixi.
|
|
||||||
*/
|
*/
|
||||||
#define _PAGE_PRESENT_SHIFT (0)
|
#define _PAGE_PRESENT_SHIFT 0
|
||||||
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
|
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
|
||||||
#define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1)
|
#define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1)
|
||||||
#define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; })
|
#define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; })
|
||||||
|
@ -125,16 +120,11 @@
|
||||||
/* huge tlb page */
|
/* huge tlb page */
|
||||||
#define _PAGE_HUGE_SHIFT (_PAGE_MODIFIED_SHIFT + 1)
|
#define _PAGE_HUGE_SHIFT (_PAGE_MODIFIED_SHIFT + 1)
|
||||||
#define _PAGE_HUGE (1 << _PAGE_HUGE_SHIFT)
|
#define _PAGE_HUGE (1 << _PAGE_HUGE_SHIFT)
|
||||||
#else
|
|
||||||
#define _PAGE_HUGE_SHIFT (_PAGE_MODIFIED_SHIFT)
|
|
||||||
#define _PAGE_HUGE ({BUG(); 1; }) /* Dummy value */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
|
|
||||||
/* huge tlb page */
|
|
||||||
#define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT + 1)
|
#define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT + 1)
|
||||||
#define _PAGE_SPLITTING (1 << _PAGE_SPLITTING_SHIFT)
|
#define _PAGE_SPLITTING (1 << _PAGE_SPLITTING_SHIFT)
|
||||||
#else
|
#else
|
||||||
|
#define _PAGE_HUGE_SHIFT (_PAGE_MODIFIED_SHIFT)
|
||||||
|
#define _PAGE_HUGE ({BUG(); 1; }) /* Dummy value */
|
||||||
#define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT)
|
#define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT)
|
||||||
#define _PAGE_SPLITTING ({BUG(); 1; }) /* Dummy value */
|
#define _PAGE_SPLITTING ({BUG(); 1; }) /* Dummy value */
|
||||||
#endif
|
#endif
|
||||||
|
@ -149,17 +139,10 @@
|
||||||
|
|
||||||
#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1)
|
#define _PAGE_GLOBAL_SHIFT (_PAGE_NO_READ_SHIFT + 1)
|
||||||
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
|
||||||
|
|
||||||
#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1)
|
#define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1)
|
||||||
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
|
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
|
||||||
/* synonym */
|
|
||||||
#define _PAGE_SILENT_READ (_PAGE_VALID)
|
|
||||||
|
|
||||||
/* The MIPS dirty bit */
|
|
||||||
#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1)
|
#define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1)
|
||||||
#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT)
|
#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT)
|
||||||
#define _PAGE_SILENT_WRITE (_PAGE_DIRTY)
|
|
||||||
|
|
||||||
#define _CACHE_SHIFT (_PAGE_DIRTY_SHIFT + 1)
|
#define _CACHE_SHIFT (_PAGE_DIRTY_SHIFT + 1)
|
||||||
#define _CACHE_MASK (7 << _CACHE_SHIFT)
|
#define _CACHE_MASK (7 << _CACHE_SHIFT)
|
||||||
|
|
||||||
|
@ -167,9 +150,9 @@
|
||||||
|
|
||||||
#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */
|
#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */
|
||||||
|
|
||||||
#ifndef _PFN_SHIFT
|
#define _PAGE_SILENT_READ _PAGE_VALID
|
||||||
#define _PFN_SHIFT PAGE_SHIFT
|
#define _PAGE_SILENT_WRITE _PAGE_DIRTY
|
||||||
#endif
|
|
||||||
#define _PFN_MASK (~((1 << (_PFN_SHIFT)) - 1))
|
#define _PFN_MASK (~((1 << (_PFN_SHIFT)) - 1))
|
||||||
|
|
||||||
#ifndef _PAGE_NO_READ
|
#ifndef _PAGE_NO_READ
|
||||||
|
@ -179,9 +162,6 @@
|
||||||
#ifndef _PAGE_NO_EXEC
|
#ifndef _PAGE_NO_EXEC
|
||||||
#define _PAGE_NO_EXEC ({BUG(); 0; })
|
#define _PAGE_NO_EXEC ({BUG(); 0; })
|
||||||
#endif
|
#endif
|
||||||
#ifndef _PAGE_GLOBAL_SHIFT
|
|
||||||
#define _PAGE_GLOBAL_SHIFT ilog2(_PAGE_GLOBAL)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
@ -266,8 +246,9 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __READABLE (_PAGE_SILENT_READ | _PAGE_ACCESSED | (cpu_has_rixi ? 0 : _PAGE_READ))
|
#define __READABLE (_PAGE_SILENT_READ | _PAGE_ACCESSED | (cpu_has_rixi ? 0 : _PAGE_READ))
|
||||||
#define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
|
#define __WRITEABLE (_PAGE_SILENT_WRITE | _PAGE_WRITE | _PAGE_MODIFIED)
|
||||||
|
|
||||||
#define _PAGE_CHG_MASK (_PFN_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK)
|
#define _PAGE_CHG_MASK (_PAGE_ACCESSED | _PAGE_MODIFIED | \
|
||||||
|
_PFN_MASK | _CACHE_MASK)
|
||||||
|
|
||||||
#endif /* _ASM_PGTABLE_BITS_H */
|
#endif /* _ASM_PGTABLE_BITS_H */
|
||||||
|
|
|
@ -99,29 +99,35 @@ extern void paging_init(void);
|
||||||
|
|
||||||
#define htw_stop() \
|
#define htw_stop() \
|
||||||
do { \
|
do { \
|
||||||
if (cpu_has_htw) \
|
unsigned long flags; \
|
||||||
|
\
|
||||||
|
if (cpu_has_htw) { \
|
||||||
|
local_irq_save(flags); \
|
||||||
|
if(!raw_current_cpu_data.htw_seq++) { \
|
||||||
write_c0_pwctl(read_c0_pwctl() & \
|
write_c0_pwctl(read_c0_pwctl() & \
|
||||||
~(1 << MIPS_PWCTL_PWEN_SHIFT)); \
|
~(1 << MIPS_PWCTL_PWEN_SHIFT)); \
|
||||||
|
back_to_back_c0_hazard(); \
|
||||||
|
} \
|
||||||
|
local_irq_restore(flags); \
|
||||||
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define htw_start() \
|
#define htw_start() \
|
||||||
do { \
|
do { \
|
||||||
if (cpu_has_htw) \
|
unsigned long flags; \
|
||||||
|
\
|
||||||
|
if (cpu_has_htw) { \
|
||||||
|
local_irq_save(flags); \
|
||||||
|
if (!--raw_current_cpu_data.htw_seq) { \
|
||||||
write_c0_pwctl(read_c0_pwctl() | \
|
write_c0_pwctl(read_c0_pwctl() | \
|
||||||
(1 << MIPS_PWCTL_PWEN_SHIFT)); \
|
(1 << MIPS_PWCTL_PWEN_SHIFT)); \
|
||||||
} while(0)
|
|
||||||
|
|
||||||
|
|
||||||
#define htw_reset() \
|
|
||||||
do { \
|
|
||||||
if (cpu_has_htw) { \
|
|
||||||
htw_stop(); \
|
|
||||||
back_to_back_c0_hazard(); \
|
|
||||||
htw_start(); \
|
|
||||||
back_to_back_c0_hazard(); \
|
back_to_back_c0_hazard(); \
|
||||||
} \
|
} \
|
||||||
|
local_irq_restore(flags); \
|
||||||
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
|
extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
|
||||||
pte_t pteval);
|
pte_t pteval);
|
||||||
|
|
||||||
|
@ -153,12 +159,13 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
|
||||||
{
|
{
|
||||||
pte_t null = __pte(0);
|
pte_t null = __pte(0);
|
||||||
|
|
||||||
|
htw_stop();
|
||||||
/* Preserve global status for the pair */
|
/* Preserve global status for the pair */
|
||||||
if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL)
|
if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL)
|
||||||
null.pte_low = null.pte_high = _PAGE_GLOBAL;
|
null.pte_low = null.pte_high = _PAGE_GLOBAL;
|
||||||
|
|
||||||
set_pte_at(mm, addr, ptep, null);
|
set_pte_at(mm, addr, ptep, null);
|
||||||
htw_reset();
|
htw_start();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -188,6 +195,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
|
||||||
|
|
||||||
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
|
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
|
||||||
{
|
{
|
||||||
|
htw_stop();
|
||||||
#if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX)
|
#if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX)
|
||||||
/* Preserve global status for the pair */
|
/* Preserve global status for the pair */
|
||||||
if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
|
if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
|
||||||
|
@ -195,7 +203,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
set_pte_at(mm, addr, ptep, __pte(0));
|
set_pte_at(mm, addr, ptep, __pte(0));
|
||||||
htw_reset();
|
htw_start();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -334,7 +342,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
|
||||||
return pte;
|
return pte;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _PAGE_HUGE
|
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
|
||||||
static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE; }
|
static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE; }
|
||||||
|
|
||||||
static inline pte_t pte_mkhuge(pte_t pte)
|
static inline pte_t pte_mkhuge(pte_t pte)
|
||||||
|
@ -342,7 +350,7 @@ static inline pte_t pte_mkhuge(pte_t pte)
|
||||||
pte_val(pte) |= _PAGE_HUGE;
|
pte_val(pte) |= _PAGE_HUGE;
|
||||||
return pte;
|
return pte;
|
||||||
}
|
}
|
||||||
#endif /* _PAGE_HUGE */
|
#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
|
||||||
#endif
|
#endif
|
||||||
static inline int pte_special(pte_t pte) { return 0; }
|
static inline int pte_special(pte_t pte) { return 0; }
|
||||||
static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
|
static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
|
||||||
|
|
|
@ -54,9 +54,7 @@ extern unsigned int vced_count, vcei_count;
|
||||||
#define TASK_SIZE 0x7fff8000UL
|
#define TASK_SIZE 0x7fff8000UL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
#define STACK_TOP_MAX TASK_SIZE
|
#define STACK_TOP_MAX TASK_SIZE
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TASK_IS_32BIT_ADDR 1
|
#define TASK_IS_32BIT_ADDR 1
|
||||||
|
|
||||||
|
@ -73,11 +71,7 @@ extern unsigned int vced_count, vcei_count;
|
||||||
#define TASK_SIZE32 0x7fff8000UL
|
#define TASK_SIZE32 0x7fff8000UL
|
||||||
#define TASK_SIZE64 0x10000000000UL
|
#define TASK_SIZE64 0x10000000000UL
|
||||||
#define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
|
#define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
#define STACK_TOP_MAX TASK_SIZE64
|
#define STACK_TOP_MAX TASK_SIZE64
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define TASK_SIZE_OF(tsk) \
|
#define TASK_SIZE_OF(tsk) \
|
||||||
(test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
|
(test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
|
||||||
|
@ -211,6 +205,8 @@ struct octeon_cop2_state {
|
||||||
unsigned long cop2_gfm_poly;
|
unsigned long cop2_gfm_poly;
|
||||||
/* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */
|
/* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */
|
||||||
unsigned long cop2_gfm_result[2];
|
unsigned long cop2_gfm_result[2];
|
||||||
|
/* DMFC2 rt, 0x24F, DMFC2 rt, 0x50, OCTEON III */
|
||||||
|
unsigned long cop2_sha3[2];
|
||||||
};
|
};
|
||||||
#define COP2_INIT \
|
#define COP2_INIT \
|
||||||
.cp2 = {0,},
|
.cp2 = {0,},
|
||||||
|
@ -399,4 +395,15 @@ unsigned long get_wchan(struct task_struct *p);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions & macros implementing the PR_GET_FP_MODE & PR_SET_FP_MODE options
|
||||||
|
* to the prctl syscall.
|
||||||
|
*/
|
||||||
|
extern int mips_get_process_fp_mode(struct task_struct *task);
|
||||||
|
extern int mips_set_process_fp_mode(struct task_struct *task,
|
||||||
|
unsigned int value);
|
||||||
|
|
||||||
|
#define GET_FP_MODE(task) mips_get_process_fp_mode(task)
|
||||||
|
#define SET_FP_MODE(task,value) mips_set_process_fp_mode(task, value)
|
||||||
|
|
||||||
#endif /* _ASM_PROCESSOR_H */
|
#endif /* _ASM_PROCESSOR_H */
|
||||||
|
|
|
@ -24,13 +24,6 @@ struct boot_param_header;
|
||||||
extern void __dt_setup_arch(void *bph);
|
extern void __dt_setup_arch(void *bph);
|
||||||
extern int __dt_register_buses(const char *bus0, const char *bus1);
|
extern int __dt_register_buses(const char *bus0, const char *bus1);
|
||||||
|
|
||||||
#define dt_setup_arch(sym) \
|
|
||||||
({ \
|
|
||||||
extern char __dtb_##sym##_begin[]; \
|
|
||||||
\
|
|
||||||
__dt_setup_arch(__dtb_##sym##_begin); \
|
|
||||||
})
|
|
||||||
|
|
||||||
#else /* CONFIG_OF */
|
#else /* CONFIG_OF */
|
||||||
static inline void device_tree_init(void) { }
|
static inline void device_tree_init(void) { }
|
||||||
#endif /* CONFIG_OF */
|
#endif /* CONFIG_OF */
|
||||||
|
|
|
@ -40,8 +40,8 @@ struct pt_regs {
|
||||||
unsigned long cp0_cause;
|
unsigned long cp0_cause;
|
||||||
unsigned long cp0_epc;
|
unsigned long cp0_epc;
|
||||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||||
unsigned long long mpl[3]; /* MTM{0,1,2} */
|
unsigned long long mpl[6]; /* MTM{0-5} */
|
||||||
unsigned long long mtp[3]; /* MTP{0,1,2} */
|
unsigned long long mtp[6]; /* MTP{0-5} */
|
||||||
#endif
|
#endif
|
||||||
} __aligned(8);
|
} __aligned(8);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <asm/asm.h>
|
#include <asm/asm.h>
|
||||||
#include <asm/cacheops.h>
|
#include <asm/cacheops.h>
|
||||||
|
#include <asm/compiler.h>
|
||||||
#include <asm/cpu-features.h>
|
#include <asm/cpu-features.h>
|
||||||
#include <asm/cpu-type.h>
|
#include <asm/cpu-type.h>
|
||||||
#include <asm/mipsmtregs.h>
|
#include <asm/mipsmtregs.h>
|
||||||
|
@ -39,7 +40,7 @@ extern void (*r4k_blast_icache)(void);
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set push \n" \
|
" .set push \n" \
|
||||||
" .set noreorder \n" \
|
" .set noreorder \n" \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||||
" cache %0, %1 \n" \
|
" cache %0, %1 \n" \
|
||||||
" .set pop \n" \
|
" .set pop \n" \
|
||||||
: \
|
: \
|
||||||
|
@ -147,7 +148,7 @@ static inline void flush_scache_line(unsigned long addr)
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set push \n" \
|
" .set push \n" \
|
||||||
" .set noreorder \n" \
|
" .set noreorder \n" \
|
||||||
" .set arch=r4000 \n" \
|
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||||
"1: cache %0, (%1) \n" \
|
"1: cache %0, (%1) \n" \
|
||||||
"2: .set pop \n" \
|
"2: .set pop \n" \
|
||||||
" .section __ex_table,\"a\" \n" \
|
" .section __ex_table,\"a\" \n" \
|
||||||
|
@ -218,6 +219,7 @@ static inline void invalidate_tcache_page(unsigned long addr)
|
||||||
cache_op(Page_Invalidate_T, addr);
|
cache_op(Page_Invalidate_T, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
#define cache16_unroll32(base,op) \
|
#define cache16_unroll32(base,op) \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set push \n" \
|
" .set push \n" \
|
||||||
|
@ -322,6 +324,150 @@ static inline void invalidate_tcache_page(unsigned long addr)
|
||||||
: "r" (base), \
|
: "r" (base), \
|
||||||
"i" (op));
|
"i" (op));
|
||||||
|
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* MIPS R6 changed the cache opcode and moved to a 8-bit offset field.
|
||||||
|
* This means we now need to increment the base register before we flush
|
||||||
|
* more cache lines
|
||||||
|
*/
|
||||||
|
#define cache16_unroll32(base,op) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
" .set push\n" \
|
||||||
|
" .set noreorder\n" \
|
||||||
|
" .set mips64r6\n" \
|
||||||
|
" .set noat\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x010(%0)\n" \
|
||||||
|
" cache %1, 0x020(%0); cache %1, 0x030(%0)\n" \
|
||||||
|
" cache %1, 0x040(%0); cache %1, 0x050(%0)\n" \
|
||||||
|
" cache %1, 0x060(%0); cache %1, 0x070(%0)\n" \
|
||||||
|
" cache %1, 0x080(%0); cache %1, 0x090(%0)\n" \
|
||||||
|
" cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)\n" \
|
||||||
|
" cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)\n" \
|
||||||
|
" cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)\n" \
|
||||||
|
" addiu $1, $0, 0x100 \n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x010($1)\n" \
|
||||||
|
" cache %1, 0x020($1); cache %1, 0x030($1)\n" \
|
||||||
|
" cache %1, 0x040($1); cache %1, 0x050($1)\n" \
|
||||||
|
" cache %1, 0x060($1); cache %1, 0x070($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x090($1)\n" \
|
||||||
|
" cache %1, 0x0a0($1); cache %1, 0x0b0($1)\n" \
|
||||||
|
" cache %1, 0x0c0($1); cache %1, 0x0d0($1)\n" \
|
||||||
|
" cache %1, 0x0e0($1); cache %1, 0x0f0($1)\n" \
|
||||||
|
" .set pop\n" \
|
||||||
|
: \
|
||||||
|
: "r" (base), \
|
||||||
|
"i" (op));
|
||||||
|
|
||||||
|
#define cache32_unroll32(base,op) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
" .set push\n" \
|
||||||
|
" .set noreorder\n" \
|
||||||
|
" .set mips64r6\n" \
|
||||||
|
" .set noat\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x020(%0)\n" \
|
||||||
|
" cache %1, 0x040(%0); cache %1, 0x060(%0)\n" \
|
||||||
|
" cache %1, 0x080(%0); cache %1, 0x0a0(%0)\n" \
|
||||||
|
" cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x020($1)\n" \
|
||||||
|
" cache %1, 0x040($1); cache %1, 0x060($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \
|
||||||
|
" cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n" \
|
||||||
|
" addiu $1, $1, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x020($1)\n" \
|
||||||
|
" cache %1, 0x040($1); cache %1, 0x060($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \
|
||||||
|
" cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n" \
|
||||||
|
" addiu $1, $1, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x020($1)\n" \
|
||||||
|
" cache %1, 0x040($1); cache %1, 0x060($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \
|
||||||
|
" cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n" \
|
||||||
|
" .set pop\n" \
|
||||||
|
: \
|
||||||
|
: "r" (base), \
|
||||||
|
"i" (op));
|
||||||
|
|
||||||
|
#define cache64_unroll32(base,op) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
" .set push\n" \
|
||||||
|
" .set noreorder\n" \
|
||||||
|
" .set mips64r6\n" \
|
||||||
|
" .set noat\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x040(%0)\n" \
|
||||||
|
" cache %1, 0x080(%0); cache %1, 0x0c0(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||||
|
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||||
|
" .set pop\n" \
|
||||||
|
: \
|
||||||
|
: "r" (base), \
|
||||||
|
"i" (op));
|
||||||
|
|
||||||
|
#define cache128_unroll32(base,op) \
|
||||||
|
__asm__ __volatile__( \
|
||||||
|
" .set push\n" \
|
||||||
|
" .set noreorder\n" \
|
||||||
|
" .set mips64r6\n" \
|
||||||
|
" .set noat\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||||
|
" addiu $1, %0, 0x100\n" \
|
||||||
|
" .set pop\n" \
|
||||||
|
: \
|
||||||
|
: "r" (base), \
|
||||||
|
"i" (op));
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform the cache operation specified by op using a user mode virtual
|
* Perform the cache operation specified by op using a user mode virtual
|
||||||
* address while in kernel mode.
|
* address while in kernel mode.
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#ifndef _ASM_SGIALIB_H
|
#ifndef _ASM_SGIALIB_H
|
||||||
#define _ASM_SGIALIB_H
|
#define _ASM_SGIALIB_H
|
||||||
|
|
||||||
|
#include <linux/compiler.h>
|
||||||
#include <asm/sgiarcs.h>
|
#include <asm/sgiarcs.h>
|
||||||
|
|
||||||
extern struct linux_romvec *romvec;
|
extern struct linux_romvec *romvec;
|
||||||
|
@ -70,8 +71,11 @@ extern LONG ArcRead(ULONG fd, PVOID buf, ULONG num, PULONG cnt);
|
||||||
extern LONG ArcWrite(ULONG fd, PVOID buf, ULONG num, PULONG cnt);
|
extern LONG ArcWrite(ULONG fd, PVOID buf, ULONG num, PULONG cnt);
|
||||||
|
|
||||||
/* Misc. routines. */
|
/* Misc. routines. */
|
||||||
extern VOID ArcReboot(VOID) __attribute__((noreturn));
|
extern VOID ArcHalt(VOID) __noreturn;
|
||||||
extern VOID ArcEnterInteractiveMode(VOID) __attribute__((noreturn));
|
extern VOID ArcPowerDown(VOID) __noreturn;
|
||||||
|
extern VOID ArcRestart(VOID) __noreturn;
|
||||||
|
extern VOID ArcReboot(VOID) __noreturn;
|
||||||
|
extern VOID ArcEnterInteractiveMode(VOID) __noreturn;
|
||||||
extern VOID ArcFlushAllCaches(VOID);
|
extern VOID ArcFlushAllCaches(VOID);
|
||||||
extern DISPLAY_STATUS *ArcGetDisplayStatus(ULONG FileID);
|
extern DISPLAY_STATUS *ArcGetDisplayStatus(ULONG FileID);
|
||||||
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1998, 1999, 2001, 2003 Ralf Baechle
|
|
||||||
* Copyright (C) 2000, 2001 Silicon Graphics, Inc.
|
|
||||||
*/
|
|
||||||
#ifndef _ASM_SIGINFO_H
|
|
||||||
#define _ASM_SIGINFO_H
|
|
||||||
|
|
||||||
#include <uapi/asm/siginfo.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Duplicated here because of <asm-generic/siginfo.h> braindamage ...
|
|
||||||
*/
|
|
||||||
#include <linux/string.h>
|
|
||||||
|
|
||||||
static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
|
|
||||||
{
|
|
||||||
if (from->si_code < 0)
|
|
||||||
memcpy(to, from, sizeof(*to));
|
|
||||||
else
|
|
||||||
/* _sigchld is currently the largest know union member */
|
|
||||||
memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ASM_SIGINFO_H */
|
|
|
@ -89,7 +89,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
|
||||||
" subu %[ticket], %[ticket], 1 \n"
|
" subu %[ticket], %[ticket], 1 \n"
|
||||||
" .previous \n"
|
" .previous \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
|
: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
|
||||||
[serving_now_ptr] "+m" (lock->h.serving_now),
|
[serving_now_ptr] "+m" (lock->h.serving_now),
|
||||||
[ticket] "=&r" (tmp),
|
[ticket] "=&r" (tmp),
|
||||||
[my_ticket] "=&r" (my_ticket)
|
[my_ticket] "=&r" (my_ticket)
|
||||||
|
@ -122,7 +122,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
|
||||||
" subu %[ticket], %[ticket], 1 \n"
|
" subu %[ticket], %[ticket], 1 \n"
|
||||||
" .previous \n"
|
" .previous \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
|
: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
|
||||||
[serving_now_ptr] "+m" (lock->h.serving_now),
|
[serving_now_ptr] "+m" (lock->h.serving_now),
|
||||||
[ticket] "=&r" (tmp),
|
[ticket] "=&r" (tmp),
|
||||||
[my_ticket] "=&r" (my_ticket)
|
[my_ticket] "=&r" (my_ticket)
|
||||||
|
@ -164,7 +164,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
|
||||||
" li %[ticket], 0 \n"
|
" li %[ticket], 0 \n"
|
||||||
" .previous \n"
|
" .previous \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
|
: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
|
||||||
[ticket] "=&r" (tmp),
|
[ticket] "=&r" (tmp),
|
||||||
[my_ticket] "=&r" (tmp2),
|
[my_ticket] "=&r" (tmp2),
|
||||||
[now_serving] "=&r" (tmp3)
|
[now_serving] "=&r" (tmp3)
|
||||||
|
@ -188,7 +188,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
|
||||||
" li %[ticket], 0 \n"
|
" li %[ticket], 0 \n"
|
||||||
" .previous \n"
|
" .previous \n"
|
||||||
" .set pop \n"
|
" .set pop \n"
|
||||||
: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
|
: [ticket_ptr] "+" GCC_OFF_SMALL_ASM() (lock->lock),
|
||||||
[ticket] "=&r" (tmp),
|
[ticket] "=&r" (tmp),
|
||||||
[my_ticket] "=&r" (tmp2),
|
[my_ticket] "=&r" (tmp2),
|
||||||
[now_serving] "=&r" (tmp3)
|
[now_serving] "=&r" (tmp3)
|
||||||
|
@ -235,8 +235,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
|
||||||
" beqzl %1, 1b \n"
|
" beqzl %1, 1b \n"
|
||||||
" nop \n"
|
" nop \n"
|
||||||
" .set reorder \n"
|
" .set reorder \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
|
@ -245,8 +245,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
|
||||||
" bltz %1, 1b \n"
|
" bltz %1, 1b \n"
|
||||||
" addu %1, 1 \n"
|
" addu %1, 1 \n"
|
||||||
"2: sc %1, %0 \n"
|
"2: sc %1, %0 \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!tmp));
|
} while (unlikely(!tmp));
|
||||||
}
|
}
|
||||||
|
@ -254,9 +254,6 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
|
||||||
smp_llsc_mb();
|
smp_llsc_mb();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note the use of sub, not subu which will make the kernel die with an
|
|
||||||
overflow exception if we ever try to unlock an rwlock that is already
|
|
||||||
unlocked or is being held by a writer. */
|
|
||||||
static inline void arch_read_unlock(arch_rwlock_t *rw)
|
static inline void arch_read_unlock(arch_rwlock_t *rw)
|
||||||
{
|
{
|
||||||
unsigned int tmp;
|
unsigned int tmp;
|
||||||
|
@ -266,20 +263,20 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
|
||||||
if (R10000_LLSC_WAR) {
|
if (R10000_LLSC_WAR) {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"1: ll %1, %2 # arch_read_unlock \n"
|
"1: ll %1, %2 # arch_read_unlock \n"
|
||||||
" sub %1, 1 \n"
|
" addiu %1, 1 \n"
|
||||||
" sc %1, %0 \n"
|
" sc %1, %0 \n"
|
||||||
" beqzl %1, 1b \n"
|
" beqzl %1, 1b \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"1: ll %1, %2 # arch_read_unlock \n"
|
"1: ll %1, %2 # arch_read_unlock \n"
|
||||||
" sub %1, 1 \n"
|
" addiu %1, -1 \n"
|
||||||
" sc %1, %0 \n"
|
" sc %1, %0 \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!tmp));
|
} while (unlikely(!tmp));
|
||||||
}
|
}
|
||||||
|
@ -299,8 +296,8 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
|
||||||
" beqzl %1, 1b \n"
|
" beqzl %1, 1b \n"
|
||||||
" nop \n"
|
" nop \n"
|
||||||
" .set reorder \n"
|
" .set reorder \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
|
@ -309,8 +306,8 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
|
||||||
" bnez %1, 1b \n"
|
" bnez %1, 1b \n"
|
||||||
" lui %1, 0x8000 \n"
|
" lui %1, 0x8000 \n"
|
||||||
"2: sc %1, %0 \n"
|
"2: sc %1, %0 \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!tmp));
|
} while (unlikely(!tmp));
|
||||||
}
|
}
|
||||||
|
@ -349,8 +346,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
|
||||||
__WEAK_LLSC_MB
|
__WEAK_LLSC_MB
|
||||||
" li %2, 1 \n"
|
" li %2, 1 \n"
|
||||||
"2: \n"
|
"2: \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else {
|
} else {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
@ -366,8 +363,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
|
||||||
__WEAK_LLSC_MB
|
__WEAK_LLSC_MB
|
||||||
" li %2, 1 \n"
|
" li %2, 1 \n"
|
||||||
"2: \n"
|
"2: \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,8 +390,8 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
|
||||||
" li %2, 1 \n"
|
" li %2, 1 \n"
|
||||||
" .set reorder \n"
|
" .set reorder \n"
|
||||||
"2: \n"
|
"2: \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
|
@ -406,9 +403,9 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
|
||||||
" sc %1, %0 \n"
|
" sc %1, %0 \n"
|
||||||
" li %2, 1 \n"
|
" li %2, 1 \n"
|
||||||
"2: \n"
|
"2: \n"
|
||||||
: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp),
|
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp),
|
||||||
"=&r" (ret)
|
"=&r" (ret)
|
||||||
: GCC_OFF12_ASM() (rw->lock)
|
: GCC_OFF_SMALL_ASM() (rw->lock)
|
||||||
: "memory");
|
: "memory");
|
||||||
} while (unlikely(!tmp));
|
} while (unlikely(!tmp));
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#ifndef _MIPS_SPRAM_H
|
#ifndef _MIPS_SPRAM_H
|
||||||
#define _MIPS_SPRAM_H
|
#define _MIPS_SPRAM_H
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#if defined(CONFIG_MIPS_SPRAM)
|
||||||
extern __init void spram_config(void);
|
extern __init void spram_config(void);
|
||||||
#else
|
#else
|
||||||
static inline void spram_config(void) { };
|
static inline void spram_config(void) { };
|
||||||
#endif /* CONFIG_CPU_MIPSR2 */
|
#endif /* CONFIG_MIPS_SPRAM */
|
||||||
|
|
||||||
#endif /* _MIPS_SPRAM_H */
|
#endif /* _MIPS_SPRAM_H */
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
LONG_S v1, PT_HI(sp)
|
LONG_S v1, PT_HI(sp)
|
||||||
mflhxu v1
|
mflhxu v1
|
||||||
LONG_S v1, PT_ACX(sp)
|
LONG_S v1, PT_ACX(sp)
|
||||||
#else
|
#elif !defined(CONFIG_CPU_MIPSR6)
|
||||||
mfhi v1
|
mfhi v1
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_32BIT
|
#ifdef CONFIG_32BIT
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
LONG_S $10, PT_R10(sp)
|
LONG_S $10, PT_R10(sp)
|
||||||
LONG_S $11, PT_R11(sp)
|
LONG_S $11, PT_R11(sp)
|
||||||
LONG_S $12, PT_R12(sp)
|
LONG_S $12, PT_R12(sp)
|
||||||
#ifndef CONFIG_CPU_HAS_SMARTMIPS
|
#if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6)
|
||||||
LONG_S v1, PT_HI(sp)
|
LONG_S v1, PT_HI(sp)
|
||||||
mflo v1
|
mflo v1
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
LONG_S $14, PT_R14(sp)
|
LONG_S $14, PT_R14(sp)
|
||||||
LONG_S $15, PT_R15(sp)
|
LONG_S $15, PT_R15(sp)
|
||||||
LONG_S $24, PT_R24(sp)
|
LONG_S $24, PT_R24(sp)
|
||||||
#ifndef CONFIG_CPU_HAS_SMARTMIPS
|
#if !defined(CONFIG_CPU_HAS_SMARTMIPS) && !defined(CONFIG_CPU_MIPSR6)
|
||||||
LONG_S v1, PT_LO(sp)
|
LONG_S v1, PT_LO(sp)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||||
|
@ -226,7 +226,7 @@
|
||||||
mtlhx $24
|
mtlhx $24
|
||||||
LONG_L $24, PT_LO(sp)
|
LONG_L $24, PT_LO(sp)
|
||||||
mtlhx $24
|
mtlhx $24
|
||||||
#else
|
#elif !defined(CONFIG_CPU_MIPSR6)
|
||||||
LONG_L $24, PT_LO(sp)
|
LONG_L $24, PT_LO(sp)
|
||||||
mtlo $24
|
mtlo $24
|
||||||
LONG_L $24, PT_HI(sp)
|
LONG_L $24, PT_HI(sp)
|
||||||
|
|
|
@ -75,9 +75,12 @@ do { \
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __clear_software_ll_bit() \
|
#define __clear_software_ll_bit() \
|
||||||
do { \
|
do { if (cpu_has_rw_llb) { \
|
||||||
|
write_c0_lladdr(0); \
|
||||||
|
} else { \
|
||||||
if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)\
|
if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)\
|
||||||
ll_bit = 0; \
|
ll_bit = 0; \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define switch_to(prev, next, last) \
|
#define switch_to(prev, next, last) \
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct thread_info {
|
||||||
unsigned long tp_value; /* thread pointer */
|
unsigned long tp_value; /* thread pointer */
|
||||||
__u32 cpu; /* current CPU */
|
__u32 cpu; /* current CPU */
|
||||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||||
|
int r2_emul_return; /* 1 => Returning from R2 emulator */
|
||||||
mm_segment_t addr_limit; /*
|
mm_segment_t addr_limit; /*
|
||||||
* thread address space limit:
|
* thread address space limit:
|
||||||
* 0x7fffffff for user-thead
|
* 0x7fffffff for user-thead
|
||||||
|
|
|
@ -21,20 +21,20 @@
|
||||||
enum major_op {
|
enum major_op {
|
||||||
spec_op, bcond_op, j_op, jal_op,
|
spec_op, bcond_op, j_op, jal_op,
|
||||||
beq_op, bne_op, blez_op, bgtz_op,
|
beq_op, bne_op, blez_op, bgtz_op,
|
||||||
addi_op, addiu_op, slti_op, sltiu_op,
|
addi_op, cbcond0_op = addi_op, addiu_op, slti_op, sltiu_op,
|
||||||
andi_op, ori_op, xori_op, lui_op,
|
andi_op, ori_op, xori_op, lui_op,
|
||||||
cop0_op, cop1_op, cop2_op, cop1x_op,
|
cop0_op, cop1_op, cop2_op, cop1x_op,
|
||||||
beql_op, bnel_op, blezl_op, bgtzl_op,
|
beql_op, bnel_op, blezl_op, bgtzl_op,
|
||||||
daddi_op, daddiu_op, ldl_op, ldr_op,
|
daddi_op, cbcond1_op = daddi_op, daddiu_op, ldl_op, ldr_op,
|
||||||
spec2_op, jalx_op, mdmx_op, spec3_op,
|
spec2_op, jalx_op, mdmx_op, spec3_op,
|
||||||
lb_op, lh_op, lwl_op, lw_op,
|
lb_op, lh_op, lwl_op, lw_op,
|
||||||
lbu_op, lhu_op, lwr_op, lwu_op,
|
lbu_op, lhu_op, lwr_op, lwu_op,
|
||||||
sb_op, sh_op, swl_op, sw_op,
|
sb_op, sh_op, swl_op, sw_op,
|
||||||
sdl_op, sdr_op, swr_op, cache_op,
|
sdl_op, sdr_op, swr_op, cache_op,
|
||||||
ll_op, lwc1_op, lwc2_op, pref_op,
|
ll_op, lwc1_op, lwc2_op, bc6_op = lwc2_op, pref_op,
|
||||||
lld_op, ldc1_op, ldc2_op, ld_op,
|
lld_op, ldc1_op, ldc2_op, beqzcjic_op = ldc2_op, ld_op,
|
||||||
sc_op, swc1_op, swc2_op, major_3b_op,
|
sc_op, swc1_op, swc2_op, balc6_op = swc2_op, major_3b_op,
|
||||||
scd_op, sdc1_op, sdc2_op, sd_op
|
scd_op, sdc1_op, sdc2_op, bnezcjialc_op = sdc2_op, sd_op
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -83,9 +83,12 @@ enum spec3_op {
|
||||||
swe_op = 0x1f, bshfl_op = 0x20,
|
swe_op = 0x1f, bshfl_op = 0x20,
|
||||||
swle_op = 0x21, swre_op = 0x22,
|
swle_op = 0x21, swre_op = 0x22,
|
||||||
prefe_op = 0x23, dbshfl_op = 0x24,
|
prefe_op = 0x23, dbshfl_op = 0x24,
|
||||||
lbue_op = 0x28, lhue_op = 0x29,
|
cache6_op = 0x25, sc6_op = 0x26,
|
||||||
lbe_op = 0x2c, lhe_op = 0x2d,
|
scd6_op = 0x27, lbue_op = 0x28,
|
||||||
lle_op = 0x2e, lwe_op = 0x2f,
|
lhue_op = 0x29, lbe_op = 0x2c,
|
||||||
|
lhe_op = 0x2d, lle_op = 0x2e,
|
||||||
|
lwe_op = 0x2f, pref6_op = 0x35,
|
||||||
|
ll6_op = 0x36, lld6_op = 0x37,
|
||||||
rdhwr_op = 0x3b
|
rdhwr_op = 0x3b
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -112,7 +115,8 @@ enum cop_op {
|
||||||
mfhc_op = 0x03, mtc_op = 0x04,
|
mfhc_op = 0x03, mtc_op = 0x04,
|
||||||
dmtc_op = 0x05, ctc_op = 0x06,
|
dmtc_op = 0x05, ctc_op = 0x06,
|
||||||
mthc0_op = 0x06, mthc_op = 0x07,
|
mthc0_op = 0x06, mthc_op = 0x07,
|
||||||
bc_op = 0x08, cop_op = 0x10,
|
bc_op = 0x08, bc1eqz_op = 0x09,
|
||||||
|
bc1nez_op = 0x0d, cop_op = 0x10,
|
||||||
copm_op = 0x18
|
copm_op = 0x18
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,6 @@
|
||||||
|
|
||||||
#define HAVE_ARCH_SIGINFO_T
|
#define HAVE_ARCH_SIGINFO_T
|
||||||
|
|
||||||
/*
|
|
||||||
* We duplicate the generic versions - <asm-generic/siginfo.h> is just borked
|
|
||||||
* by design ...
|
|
||||||
*/
|
|
||||||
#define HAVE_ARCH_COPY_SIGINFO
|
|
||||||
struct siginfo;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Careful to keep union _sifields from shifting ...
|
* Careful to keep union _sifields from shifting ...
|
||||||
*/
|
*/
|
||||||
|
@ -35,8 +28,9 @@ struct siginfo;
|
||||||
|
|
||||||
#define __ARCH_SIGSYS
|
#define __ARCH_SIGSYS
|
||||||
|
|
||||||
#include <asm-generic/siginfo.h>
|
#include <uapi/asm-generic/siginfo.h>
|
||||||
|
|
||||||
|
/* We can't use generic siginfo_t, because our si_code and si_errno are swapped */
|
||||||
typedef struct siginfo {
|
typedef struct siginfo {
|
||||||
int si_signo;
|
int si_signo;
|
||||||
int si_code;
|
int si_code;
|
||||||
|
@ -124,5 +118,6 @@ typedef struct siginfo {
|
||||||
#define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */
|
#define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */
|
||||||
#define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */
|
#define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */
|
||||||
|
|
||||||
|
#include <asm-generic/siginfo.h>
|
||||||
|
|
||||||
#endif /* _UAPI_ASM_SIGINFO_H */
|
#endif /* _UAPI_ASM_SIGINFO_H */
|
||||||
|
|
|
@ -52,7 +52,7 @@ obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
|
||||||
obj-$(CONFIG_MIPS_CMP) += smp-cmp.o
|
obj-$(CONFIG_MIPS_CMP) += smp-cmp.o
|
||||||
obj-$(CONFIG_MIPS_CPS) += smp-cps.o cps-vec.o
|
obj-$(CONFIG_MIPS_CPS) += smp-cps.o cps-vec.o
|
||||||
obj-$(CONFIG_MIPS_GIC_IPI) += smp-gic.o
|
obj-$(CONFIG_MIPS_GIC_IPI) += smp-gic.o
|
||||||
obj-$(CONFIG_CPU_MIPSR2) += spram.o
|
obj-$(CONFIG_MIPS_SPRAM) += spram.o
|
||||||
|
|
||||||
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
|
obj-$(CONFIG_MIPS_VPE_LOADER) += vpe.o
|
||||||
obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o
|
obj-$(CONFIG_MIPS_VPE_LOADER_CMP) += vpe-cmp.o
|
||||||
|
@ -90,6 +90,7 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||||
obj-$(CONFIG_EARLY_PRINTK_8250) += early_printk_8250.o
|
obj-$(CONFIG_EARLY_PRINTK_8250) += early_printk_8250.o
|
||||||
obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
|
obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
|
||||||
obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
|
obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
|
||||||
|
obj-$(CONFIG_MIPSR2_TO_R6_EMULATOR) += mips-r2-to-r6-emul.o
|
||||||
|
|
||||||
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
|
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@ void output_thread_info_defines(void)
|
||||||
OFFSET(TI_TP_VALUE, thread_info, tp_value);
|
OFFSET(TI_TP_VALUE, thread_info, tp_value);
|
||||||
OFFSET(TI_CPU, thread_info, cpu);
|
OFFSET(TI_CPU, thread_info, cpu);
|
||||||
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
||||||
|
OFFSET(TI_R2_EMUL_RET, thread_info, r2_emul_return);
|
||||||
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
||||||
OFFSET(TI_REGS, thread_info, regs);
|
OFFSET(TI_REGS, thread_info, regs);
|
||||||
DEFINE(_THREAD_SIZE, THREAD_SIZE);
|
DEFINE(_THREAD_SIZE, THREAD_SIZE);
|
||||||
|
@ -381,6 +382,7 @@ void output_octeon_cop2_state_defines(void)
|
||||||
OFFSET(OCTEON_CP2_GFM_RESULT, octeon_cop2_state, cop2_gfm_result);
|
OFFSET(OCTEON_CP2_GFM_RESULT, octeon_cop2_state, cop2_gfm_result);
|
||||||
OFFSET(OCTEON_CP2_HSH_DATW, octeon_cop2_state, cop2_hsh_datw);
|
OFFSET(OCTEON_CP2_HSH_DATW, octeon_cop2_state, cop2_hsh_datw);
|
||||||
OFFSET(OCTEON_CP2_HSH_IVW, octeon_cop2_state, cop2_hsh_ivw);
|
OFFSET(OCTEON_CP2_HSH_IVW, octeon_cop2_state, cop2_hsh_ivw);
|
||||||
|
OFFSET(OCTEON_CP2_SHA3, octeon_cop2_state, cop2_sha3);
|
||||||
OFFSET(THREAD_CP2, task_struct, thread.cp2);
|
OFFSET(THREAD_CP2, task_struct, thread.cp2);
|
||||||
OFFSET(THREAD_CVMSEG, task_struct, thread.cvmseg.cvmseg);
|
OFFSET(THREAD_CVMSEG, task_struct, thread.cvmseg.cvmseg);
|
||||||
BLANK();
|
BLANK();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
#include <asm/fpu_emulator.h>
|
#include <asm/fpu_emulator.h>
|
||||||
#include <asm/inst.h>
|
#include <asm/inst.h>
|
||||||
|
#include <asm/mips-r2-to-r6-emul.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
|
@ -399,11 +400,21 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
|
||||||
* @returns: -EFAULT on error and forces SIGBUS, and on success
|
* @returns: -EFAULT on error and forces SIGBUS, and on success
|
||||||
* returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
|
* returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
|
||||||
* evaluating the branch.
|
* evaluating the branch.
|
||||||
|
*
|
||||||
|
* MIPS R6 Compact branches and forbidden slots:
|
||||||
|
* Compact branches do not throw exceptions because they do
|
||||||
|
* not have delay slots. The forbidden slot instruction ($PC+4)
|
||||||
|
* is only executed if the branch was not taken. Otherwise the
|
||||||
|
* forbidden slot is skipped entirely. This means that the
|
||||||
|
* only possible reason to be here because of a MIPS R6 compact
|
||||||
|
* branch instruction is that the forbidden slot has thrown one.
|
||||||
|
* In that case the branch was not taken, so the EPC can be safely
|
||||||
|
* set to EPC + 8.
|
||||||
*/
|
*/
|
||||||
int __compute_return_epc_for_insn(struct pt_regs *regs,
|
int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
union mips_instruction insn)
|
union mips_instruction insn)
|
||||||
{
|
{
|
||||||
unsigned int bit, fcr31, dspcontrol;
|
unsigned int bit, fcr31, dspcontrol, reg;
|
||||||
long epc = regs->cp0_epc;
|
long epc = regs->cp0_epc;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -417,6 +428,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
regs->regs[insn.r_format.rd] = epc + 8;
|
regs->regs[insn.r_format.rd] = epc + 8;
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case jr_op:
|
case jr_op:
|
||||||
|
if (NO_R6EMU && insn.r_format.func == jr_op)
|
||||||
|
goto sigill_r6;
|
||||||
regs->cp0_epc = regs->regs[insn.r_format.rs];
|
regs->cp0_epc = regs->regs[insn.r_format.rs];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -429,8 +442,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
*/
|
*/
|
||||||
case bcond_op:
|
case bcond_op:
|
||||||
switch (insn.i_format.rt) {
|
switch (insn.i_format.rt) {
|
||||||
case bltz_op:
|
|
||||||
case bltzl_op:
|
case bltzl_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
goto sigill_r6;
|
||||||
|
case bltz_op:
|
||||||
if ((long)regs->regs[insn.i_format.rs] < 0) {
|
if ((long)regs->regs[insn.i_format.rs] < 0) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
if (insn.i_format.rt == bltzl_op)
|
if (insn.i_format.rt == bltzl_op)
|
||||||
|
@ -440,8 +455,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
regs->cp0_epc = epc;
|
regs->cp0_epc = epc;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case bgez_op:
|
|
||||||
case bgezl_op:
|
case bgezl_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
goto sigill_r6;
|
||||||
|
case bgez_op:
|
||||||
if ((long)regs->regs[insn.i_format.rs] >= 0) {
|
if ((long)regs->regs[insn.i_format.rs] >= 0) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
if (insn.i_format.rt == bgezl_op)
|
if (insn.i_format.rt == bgezl_op)
|
||||||
|
@ -453,7 +470,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
|
|
||||||
case bltzal_op:
|
case bltzal_op:
|
||||||
case bltzall_op:
|
case bltzall_op:
|
||||||
|
if (NO_R6EMU && (insn.i_format.rs ||
|
||||||
|
insn.i_format.rt == bltzall_op)) {
|
||||||
|
ret = -SIGILL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
regs->regs[31] = epc + 8;
|
regs->regs[31] = epc + 8;
|
||||||
|
/*
|
||||||
|
* OK we are here either because we hit a NAL
|
||||||
|
* instruction or because we are emulating an
|
||||||
|
* old bltzal{,l} one. Lets figure out what the
|
||||||
|
* case really is.
|
||||||
|
*/
|
||||||
|
if (!insn.i_format.rs) {
|
||||||
|
/*
|
||||||
|
* NAL or BLTZAL with rs == 0
|
||||||
|
* Doesn't matter if we are R6 or not. The
|
||||||
|
* result is the same
|
||||||
|
*/
|
||||||
|
regs->cp0_epc += 4 +
|
||||||
|
(insn.i_format.simmediate << 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Now do the real thing for non-R6 BLTZAL{,L} */
|
||||||
if ((long)regs->regs[insn.i_format.rs] < 0) {
|
if ((long)regs->regs[insn.i_format.rs] < 0) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
if (insn.i_format.rt == bltzall_op)
|
if (insn.i_format.rt == bltzall_op)
|
||||||
|
@ -465,7 +504,29 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
|
|
||||||
case bgezal_op:
|
case bgezal_op:
|
||||||
case bgezall_op:
|
case bgezall_op:
|
||||||
|
if (NO_R6EMU && (insn.i_format.rs ||
|
||||||
|
insn.i_format.rt == bgezall_op)) {
|
||||||
|
ret = -SIGILL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
regs->regs[31] = epc + 8;
|
regs->regs[31] = epc + 8;
|
||||||
|
/*
|
||||||
|
* OK we are here either because we hit a BAL
|
||||||
|
* instruction or because we are emulating an
|
||||||
|
* old bgezal{,l} one. Lets figure out what the
|
||||||
|
* case really is.
|
||||||
|
*/
|
||||||
|
if (!insn.i_format.rs) {
|
||||||
|
/*
|
||||||
|
* BAL or BGEZAL with rs == 0
|
||||||
|
* Doesn't matter if we are R6 or not. The
|
||||||
|
* result is the same
|
||||||
|
*/
|
||||||
|
regs->cp0_epc += 4 +
|
||||||
|
(insn.i_format.simmediate << 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Now do the real thing for non-R6 BGEZAL{,L} */
|
||||||
if ((long)regs->regs[insn.i_format.rs] >= 0) {
|
if ((long)regs->regs[insn.i_format.rs] >= 0) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
if (insn.i_format.rt == bgezall_op)
|
if (insn.i_format.rt == bgezall_op)
|
||||||
|
@ -477,7 +538,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
|
|
||||||
case bposge32_op:
|
case bposge32_op:
|
||||||
if (!cpu_has_dsp)
|
if (!cpu_has_dsp)
|
||||||
goto sigill;
|
goto sigill_dsp;
|
||||||
|
|
||||||
dspcontrol = rddsp(0x01);
|
dspcontrol = rddsp(0x01);
|
||||||
|
|
||||||
|
@ -508,8 +569,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
/*
|
/*
|
||||||
* These are conditional and in i_format.
|
* These are conditional and in i_format.
|
||||||
*/
|
*/
|
||||||
case beq_op:
|
|
||||||
case beql_op:
|
case beql_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
goto sigill_r6;
|
||||||
|
case beq_op:
|
||||||
if (regs->regs[insn.i_format.rs] ==
|
if (regs->regs[insn.i_format.rs] ==
|
||||||
regs->regs[insn.i_format.rt]) {
|
regs->regs[insn.i_format.rt]) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
@ -520,8 +583,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
regs->cp0_epc = epc;
|
regs->cp0_epc = epc;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case bne_op:
|
|
||||||
case bnel_op:
|
case bnel_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
goto sigill_r6;
|
||||||
|
case bne_op:
|
||||||
if (regs->regs[insn.i_format.rs] !=
|
if (regs->regs[insn.i_format.rs] !=
|
||||||
regs->regs[insn.i_format.rt]) {
|
regs->regs[insn.i_format.rt]) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
@ -532,8 +597,31 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
regs->cp0_epc = epc;
|
regs->cp0_epc = epc;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case blez_op: /* not really i_format */
|
case blezl_op: /* not really i_format */
|
||||||
case blezl_op:
|
if (NO_R6EMU)
|
||||||
|
goto sigill_r6;
|
||||||
|
case blez_op:
|
||||||
|
/*
|
||||||
|
* Compact branches for R6 for the
|
||||||
|
* blez and blezl opcodes.
|
||||||
|
* BLEZ | rs = 0 | rt != 0 == BLEZALC
|
||||||
|
* BLEZ | rs = rt != 0 == BGEZALC
|
||||||
|
* BLEZ | rs != 0 | rt != 0 == BGEUC
|
||||||
|
* BLEZL | rs = 0 | rt != 0 == BLEZC
|
||||||
|
* BLEZL | rs = rt != 0 == BGEZC
|
||||||
|
* BLEZL | rs != 0 | rt != 0 == BGEC
|
||||||
|
*
|
||||||
|
* For real BLEZ{,L}, rt is always 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (cpu_has_mips_r6 && insn.i_format.rt) {
|
||||||
|
if ((insn.i_format.opcode == blez_op) &&
|
||||||
|
((!insn.i_format.rs && insn.i_format.rt) ||
|
||||||
|
(insn.i_format.rs == insn.i_format.rt)))
|
||||||
|
regs->regs[31] = epc + 4;
|
||||||
|
regs->cp0_epc += 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* rt field assumed to be zero */
|
/* rt field assumed to be zero */
|
||||||
if ((long)regs->regs[insn.i_format.rs] <= 0) {
|
if ((long)regs->regs[insn.i_format.rs] <= 0) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
@ -544,8 +632,32 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
regs->cp0_epc = epc;
|
regs->cp0_epc = epc;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case bgtz_op:
|
|
||||||
case bgtzl_op:
|
case bgtzl_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
goto sigill_r6;
|
||||||
|
case bgtz_op:
|
||||||
|
/*
|
||||||
|
* Compact branches for R6 for the
|
||||||
|
* bgtz and bgtzl opcodes.
|
||||||
|
* BGTZ | rs = 0 | rt != 0 == BGTZALC
|
||||||
|
* BGTZ | rs = rt != 0 == BLTZALC
|
||||||
|
* BGTZ | rs != 0 | rt != 0 == BLTUC
|
||||||
|
* BGTZL | rs = 0 | rt != 0 == BGTZC
|
||||||
|
* BGTZL | rs = rt != 0 == BLTZC
|
||||||
|
* BGTZL | rs != 0 | rt != 0 == BLTC
|
||||||
|
*
|
||||||
|
* *ZALC varint for BGTZ &&& rt != 0
|
||||||
|
* For real GTZ{,L}, rt is always 0.
|
||||||
|
*/
|
||||||
|
if (cpu_has_mips_r6 && insn.i_format.rt) {
|
||||||
|
if ((insn.i_format.opcode == blez_op) &&
|
||||||
|
((!insn.i_format.rs && insn.i_format.rt) ||
|
||||||
|
(insn.i_format.rs == insn.i_format.rt)))
|
||||||
|
regs->regs[31] = epc + 4;
|
||||||
|
regs->cp0_epc += 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* rt field assumed to be zero */
|
/* rt field assumed to be zero */
|
||||||
if ((long)regs->regs[insn.i_format.rs] > 0) {
|
if ((long)regs->regs[insn.i_format.rs] > 0) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
@ -560,6 +672,46 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
* And now the FPA/cp1 branch instructions.
|
* And now the FPA/cp1 branch instructions.
|
||||||
*/
|
*/
|
||||||
case cop1_op:
|
case cop1_op:
|
||||||
|
if (cpu_has_mips_r6 &&
|
||||||
|
((insn.i_format.rs == bc1eqz_op) ||
|
||||||
|
(insn.i_format.rs == bc1nez_op))) {
|
||||||
|
if (!used_math()) { /* First time FPU user */
|
||||||
|
ret = init_fpu();
|
||||||
|
if (ret && NO_R6EMU) {
|
||||||
|
ret = -ret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
set_used_math();
|
||||||
|
}
|
||||||
|
lose_fpu(1); /* Save FPU state for the emulator. */
|
||||||
|
reg = insn.i_format.rt;
|
||||||
|
bit = 0;
|
||||||
|
switch (insn.i_format.rs) {
|
||||||
|
case bc1eqz_op:
|
||||||
|
/* Test bit 0 */
|
||||||
|
if (get_fpr32(¤t->thread.fpu.fpr[reg], 0)
|
||||||
|
& 0x1)
|
||||||
|
bit = 1;
|
||||||
|
break;
|
||||||
|
case bc1nez_op:
|
||||||
|
/* Test bit 0 */
|
||||||
|
if (!(get_fpr32(¤t->thread.fpu.fpr[reg], 0)
|
||||||
|
& 0x1))
|
||||||
|
bit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
own_fpu(1);
|
||||||
|
if (bit)
|
||||||
|
epc = epc + 4 +
|
||||||
|
(insn.i_format.simmediate << 2);
|
||||||
|
else
|
||||||
|
epc += 8;
|
||||||
|
regs->cp0_epc = epc;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
if (is_fpu_owner())
|
if (is_fpu_owner())
|
||||||
fcr31 = read_32bit_cp1_register(CP1_STATUS);
|
fcr31 = read_32bit_cp1_register(CP1_STATUS);
|
||||||
|
@ -574,7 +726,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
case 0: /* bc1f */
|
case 0: /* bc1f */
|
||||||
case 2: /* bc1fl */
|
case 2: /* bc1fl */
|
||||||
if (~fcr31 & (1 << bit)) {
|
if (~fcr31 & (1 << bit)) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 +
|
||||||
|
(insn.i_format.simmediate << 2);
|
||||||
if (insn.i_format.rt == 2)
|
if (insn.i_format.rt == 2)
|
||||||
ret = BRANCH_LIKELY_TAKEN;
|
ret = BRANCH_LIKELY_TAKEN;
|
||||||
} else
|
} else
|
||||||
|
@ -585,7 +738,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
case 1: /* bc1t */
|
case 1: /* bc1t */
|
||||||
case 3: /* bc1tl */
|
case 3: /* bc1tl */
|
||||||
if (fcr31 & (1 << bit)) {
|
if (fcr31 & (1 << bit)) {
|
||||||
epc = epc + 4 + (insn.i_format.simmediate << 2);
|
epc = epc + 4 +
|
||||||
|
(insn.i_format.simmediate << 2);
|
||||||
if (insn.i_format.rt == 3)
|
if (insn.i_format.rt == 3)
|
||||||
ret = BRANCH_LIKELY_TAKEN;
|
ret = BRANCH_LIKELY_TAKEN;
|
||||||
} else
|
} else
|
||||||
|
@ -594,6 +748,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||||
case lwc2_op: /* This is bbit0 on Octeon */
|
case lwc2_op: /* This is bbit0 on Octeon */
|
||||||
if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
|
if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
|
||||||
|
@ -626,15 +781,72 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
||||||
epc += 8;
|
epc += 8;
|
||||||
regs->cp0_epc = epc;
|
regs->cp0_epc = epc;
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
case bc6_op:
|
||||||
|
/* Only valid for MIPS R6 */
|
||||||
|
if (!cpu_has_mips_r6) {
|
||||||
|
ret = -SIGILL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
regs->cp0_epc += 8;
|
||||||
|
break;
|
||||||
|
case balc6_op:
|
||||||
|
if (!cpu_has_mips_r6) {
|
||||||
|
ret = -SIGILL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Compact branch: BALC */
|
||||||
|
regs->regs[31] = epc + 4;
|
||||||
|
epc += 4 + (insn.i_format.simmediate << 2);
|
||||||
|
regs->cp0_epc = epc;
|
||||||
|
break;
|
||||||
|
case beqzcjic_op:
|
||||||
|
if (!cpu_has_mips_r6) {
|
||||||
|
ret = -SIGILL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Compact branch: BEQZC || JIC */
|
||||||
|
regs->cp0_epc += 8;
|
||||||
|
break;
|
||||||
|
case bnezcjialc_op:
|
||||||
|
if (!cpu_has_mips_r6) {
|
||||||
|
ret = -SIGILL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Compact branch: BNEZC || JIALC */
|
||||||
|
if (insn.i_format.rs)
|
||||||
|
regs->regs[31] = epc + 4;
|
||||||
|
regs->cp0_epc += 8;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case cbcond0_op:
|
||||||
|
case cbcond1_op:
|
||||||
|
/* Only valid for MIPS R6 */
|
||||||
|
if (!cpu_has_mips_r6) {
|
||||||
|
ret = -SIGILL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Compact branches:
|
||||||
|
* bovc, beqc, beqzalc, bnvc, bnec, bnezlac
|
||||||
|
*/
|
||||||
|
if (insn.i_format.rt && !insn.i_format.rs)
|
||||||
|
regs->regs[31] = epc + 4;
|
||||||
|
regs->cp0_epc += 8;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
sigill:
|
sigill_dsp:
|
||||||
printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
|
printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
|
||||||
force_sig(SIGBUS, current);
|
force_sig(SIGBUS, current);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
sigill_r6:
|
||||||
|
pr_info("%s: R2 branch but r2-to-r6 emulator is not preset - sending SIGILL.\n",
|
||||||
|
current->comm);
|
||||||
|
force_sig(SIGILL, current);
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__compute_return_epc_for_insn);
|
EXPORT_SYMBOL_GPL(__compute_return_epc_for_insn);
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/irqchip/mips-gic.h>
|
|
||||||
|
|
||||||
#include <asm/time.h>
|
#include <asm/time.h>
|
||||||
#include <asm/cevt-r4k.h>
|
#include <asm/cevt-r4k.h>
|
||||||
|
@ -40,7 +39,7 @@ int cp0_timer_irq_installed;
|
||||||
|
|
||||||
irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
|
irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
const int r2 = cpu_has_mips_r2;
|
const int r2 = cpu_has_mips_r2_r6;
|
||||||
struct clock_event_device *cd;
|
struct clock_event_device *cd;
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
|
@ -85,10 +84,7 @@ void mips_event_handler(struct clock_event_device *dev)
|
||||||
*/
|
*/
|
||||||
static int c0_compare_int_pending(void)
|
static int c0_compare_int_pending(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_MIPS_GIC
|
/* When cpu_has_mips_r2, this checks Cause.TI instead of Cause.IP7 */
|
||||||
if (gic_present)
|
|
||||||
return gic_get_timer_pending();
|
|
||||||
#endif
|
|
||||||
return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP);
|
return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,11 +99,11 @@ not_nmi:
|
||||||
xori t2, t1, 0x7
|
xori t2, t1, 0x7
|
||||||
beqz t2, 1f
|
beqz t2, 1f
|
||||||
li t3, 32
|
li t3, 32
|
||||||
addi t1, t1, 1
|
addiu t1, t1, 1
|
||||||
sllv t1, t3, t1
|
sllv t1, t3, t1
|
||||||
1: /* At this point t1 == I-cache sets per way */
|
1: /* At this point t1 == I-cache sets per way */
|
||||||
_EXT t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
|
_EXT t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
|
||||||
addi t2, t2, 1
|
addiu t2, t2, 1
|
||||||
mul t1, t1, t0
|
mul t1, t1, t0
|
||||||
mul t1, t1, t2
|
mul t1, t1, t2
|
||||||
|
|
||||||
|
@ -126,11 +126,11 @@ icache_done:
|
||||||
xori t2, t1, 0x7
|
xori t2, t1, 0x7
|
||||||
beqz t2, 1f
|
beqz t2, 1f
|
||||||
li t3, 32
|
li t3, 32
|
||||||
addi t1, t1, 1
|
addiu t1, t1, 1
|
||||||
sllv t1, t3, t1
|
sllv t1, t3, t1
|
||||||
1: /* At this point t1 == D-cache sets per way */
|
1: /* At this point t1 == D-cache sets per way */
|
||||||
_EXT t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
|
_EXT t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
|
||||||
addi t2, t2, 1
|
addiu t2, t2, 1
|
||||||
mul t1, t1, t0
|
mul t1, t1, t0
|
||||||
mul t1, t1, t2
|
mul t1, t1, t2
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ LEAF(mips_cps_core_init)
|
||||||
mfc0 t0, CP0_MVPCONF0
|
mfc0 t0, CP0_MVPCONF0
|
||||||
srl t0, t0, MVPCONF0_PVPE_SHIFT
|
srl t0, t0, MVPCONF0_PVPE_SHIFT
|
||||||
andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
|
andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
|
||||||
addi t7, t0, 1
|
addiu t7, t0, 1
|
||||||
|
|
||||||
/* If there's only 1, we're done */
|
/* If there's only 1, we're done */
|
||||||
beqz t0, 2f
|
beqz t0, 2f
|
||||||
|
@ -280,7 +280,7 @@ LEAF(mips_cps_core_init)
|
||||||
mttc0 t0, CP0_TCHALT
|
mttc0 t0, CP0_TCHALT
|
||||||
|
|
||||||
/* Next VPE */
|
/* Next VPE */
|
||||||
addi t5, t5, 1
|
addiu t5, t5, 1
|
||||||
slt t0, t5, t7
|
slt t0, t5, t7
|
||||||
bnez t0, 1b
|
bnez t0, 1b
|
||||||
nop
|
nop
|
||||||
|
@ -317,7 +317,7 @@ LEAF(mips_cps_boot_vpes)
|
||||||
mfc0 t1, CP0_MVPCONF0
|
mfc0 t1, CP0_MVPCONF0
|
||||||
srl t1, t1, MVPCONF0_PVPE_SHIFT
|
srl t1, t1, MVPCONF0_PVPE_SHIFT
|
||||||
andi t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
|
andi t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
|
||||||
addi t1, t1, 1
|
addiu t1, t1, 1
|
||||||
|
|
||||||
/* Calculate a mask for the VPE ID from EBase.CPUNum */
|
/* Calculate a mask for the VPE ID from EBase.CPUNum */
|
||||||
clz t1, t1
|
clz t1, t1
|
||||||
|
@ -424,7 +424,7 @@ LEAF(mips_cps_boot_vpes)
|
||||||
|
|
||||||
/* Next VPE */
|
/* Next VPE */
|
||||||
2: srl t6, t6, 1
|
2: srl t6, t6, 1
|
||||||
addi t5, t5, 1
|
addiu t5, t5, 1
|
||||||
bnez t6, 1b
|
bnez t6, 1b
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
|
|
@ -244,7 +244,7 @@ static inline void check_daddi(void)
|
||||||
panic(bug64hit, !DADDI_WAR ? daddiwar : nowar);
|
panic(bug64hit, !DADDI_WAR ? daddiwar : nowar);
|
||||||
}
|
}
|
||||||
|
|
||||||
int daddiu_bug = -1;
|
int daddiu_bug = config_enabled(CONFIG_CPU_MIPSR6) ? 0 : -1;
|
||||||
|
|
||||||
static inline void check_daddiu(void)
|
static inline void check_daddiu(void)
|
||||||
{
|
{
|
||||||
|
@ -314,11 +314,14 @@ static inline void check_daddiu(void)
|
||||||
|
|
||||||
void __init check_bugs64_early(void)
|
void __init check_bugs64_early(void)
|
||||||
{
|
{
|
||||||
|
if (!config_enabled(CONFIG_CPU_MIPSR6)) {
|
||||||
check_mult_sh();
|
check_mult_sh();
|
||||||
check_daddiu();
|
check_daddiu();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void __init check_bugs64(void)
|
void __init check_bugs64(void)
|
||||||
{
|
{
|
||||||
|
if (!config_enabled(CONFIG_CPU_MIPSR6))
|
||||||
check_daddi();
|
check_daddi();
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,6 +237,13 @@ static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
|
||||||
c->isa_level |= MIPS_CPU_ISA_II | MIPS_CPU_ISA_III;
|
c->isa_level |= MIPS_CPU_ISA_II | MIPS_CPU_ISA_III;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* R6 incompatible with everything else */
|
||||||
|
case MIPS_CPU_ISA_M64R6:
|
||||||
|
c->isa_level |= MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6;
|
||||||
|
case MIPS_CPU_ISA_M32R6:
|
||||||
|
c->isa_level |= MIPS_CPU_ISA_M32R6;
|
||||||
|
/* Break here so we don't add incompatible ISAs */
|
||||||
|
break;
|
||||||
case MIPS_CPU_ISA_M32R2:
|
case MIPS_CPU_ISA_M32R2:
|
||||||
c->isa_level |= MIPS_CPU_ISA_M32R2;
|
c->isa_level |= MIPS_CPU_ISA_M32R2;
|
||||||
case MIPS_CPU_ISA_M32R1:
|
case MIPS_CPU_ISA_M32R1:
|
||||||
|
@ -326,6 +333,9 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c)
|
||||||
case 1:
|
case 1:
|
||||||
set_isa(c, MIPS_CPU_ISA_M32R2);
|
set_isa(c, MIPS_CPU_ISA_M32R2);
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
|
set_isa(c, MIPS_CPU_ISA_M32R6);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto unknown;
|
goto unknown;
|
||||||
}
|
}
|
||||||
|
@ -338,6 +348,9 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c)
|
||||||
case 1:
|
case 1:
|
||||||
set_isa(c, MIPS_CPU_ISA_M64R2);
|
set_isa(c, MIPS_CPU_ISA_M64R2);
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
|
set_isa(c, MIPS_CPU_ISA_M64R6);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto unknown;
|
goto unknown;
|
||||||
}
|
}
|
||||||
|
@ -424,8 +437,10 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
|
||||||
if (config3 & MIPS_CONF3_MSA)
|
if (config3 & MIPS_CONF3_MSA)
|
||||||
c->ases |= MIPS_ASE_MSA;
|
c->ases |= MIPS_ASE_MSA;
|
||||||
/* Only tested on 32-bit cores */
|
/* Only tested on 32-bit cores */
|
||||||
if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT))
|
if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT)) {
|
||||||
|
c->htw_seq = 0;
|
||||||
c->options |= MIPS_CPU_HTW;
|
c->options |= MIPS_CPU_HTW;
|
||||||
|
}
|
||||||
|
|
||||||
return config3 & MIPS_CONF_M;
|
return config3 & MIPS_CONF_M;
|
||||||
}
|
}
|
||||||
|
@ -499,6 +514,8 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
|
||||||
c->options |= MIPS_CPU_EVA;
|
c->options |= MIPS_CPU_EVA;
|
||||||
if (config5 & MIPS_CONF5_MRP)
|
if (config5 & MIPS_CONF5_MRP)
|
||||||
c->options |= MIPS_CPU_MAAR;
|
c->options |= MIPS_CPU_MAAR;
|
||||||
|
if (config5 & MIPS_CONF5_LLB)
|
||||||
|
c->options |= MIPS_CPU_RW_LLB;
|
||||||
|
|
||||||
return config5 & MIPS_CONF_M;
|
return config5 & MIPS_CONF_M;
|
||||||
}
|
}
|
||||||
|
@ -533,7 +550,7 @@ static void decode_configs(struct cpuinfo_mips *c)
|
||||||
|
|
||||||
if (cpu_has_rixi) {
|
if (cpu_has_rixi) {
|
||||||
/* Enable the RIXI exceptions */
|
/* Enable the RIXI exceptions */
|
||||||
write_c0_pagegrain(read_c0_pagegrain() | PG_IEC);
|
set_c0_pagegrain(PG_IEC);
|
||||||
back_to_back_c0_hazard();
|
back_to_back_c0_hazard();
|
||||||
/* Verify the IEC bit is set */
|
/* Verify the IEC bit is set */
|
||||||
if (read_c0_pagegrain() & PG_IEC)
|
if (read_c0_pagegrain() & PG_IEC)
|
||||||
|
@ -541,7 +558,7 @@ static void decode_configs(struct cpuinfo_mips *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_MIPS_CPS
|
#ifndef CONFIG_MIPS_CPS
|
||||||
if (cpu_has_mips_r2) {
|
if (cpu_has_mips_r2_r6) {
|
||||||
c->core = get_ebase_cpunum();
|
c->core = get_ebase_cpunum();
|
||||||
if (cpu_has_mipsmt)
|
if (cpu_has_mipsmt)
|
||||||
c->core >>= fls(core_nvpes()) - 1;
|
c->core >>= fls(core_nvpes()) - 1;
|
||||||
|
@ -896,6 +913,11 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
|
||||||
{
|
{
|
||||||
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
||||||
switch (c->processor_id & PRID_IMP_MASK) {
|
switch (c->processor_id & PRID_IMP_MASK) {
|
||||||
|
case PRID_IMP_QEMU_GENERIC:
|
||||||
|
c->writecombine = _CACHE_UNCACHED;
|
||||||
|
c->cputype = CPU_QEMU_GENERIC;
|
||||||
|
__cpu_name[cpu] = "MIPS GENERIC QEMU";
|
||||||
|
break;
|
||||||
case PRID_IMP_4KC:
|
case PRID_IMP_4KC:
|
||||||
c->cputype = CPU_4KC;
|
c->cputype = CPU_4KC;
|
||||||
c->writecombine = _CACHE_UNCACHED;
|
c->writecombine = _CACHE_UNCACHED;
|
||||||
|
@ -1345,8 +1367,7 @@ void cpu_probe(void)
|
||||||
if (c->options & MIPS_CPU_FPU) {
|
if (c->options & MIPS_CPU_FPU) {
|
||||||
c->fpu_id = cpu_get_fpu_id();
|
c->fpu_id = cpu_get_fpu_id();
|
||||||
|
|
||||||
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
|
if (c->isa_level & cpu_has_mips_r) {
|
||||||
MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
|
|
||||||
if (c->fpu_id & MIPS_FPIR_3D)
|
if (c->fpu_id & MIPS_FPIR_3D)
|
||||||
c->ases |= MIPS_ASE_MIPS3D;
|
c->ases |= MIPS_ASE_MIPS3D;
|
||||||
if (c->fpu_id & MIPS_FPIR_FREP)
|
if (c->fpu_id & MIPS_FPIR_FREP)
|
||||||
|
@ -1354,7 +1375,7 @@ void cpu_probe(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu_has_mips_r2) {
|
if (cpu_has_mips_r2_r6) {
|
||||||
c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
|
c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
|
||||||
/* R2 has Performance Counter Interrupt indicator */
|
/* R2 has Performance Counter Interrupt indicator */
|
||||||
c->options |= MIPS_CPU_PCI;
|
c->options |= MIPS_CPU_PCI;
|
||||||
|
|
|
@ -11,29 +11,112 @@
|
||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
/* FPU modes */
|
||||||
enum {
|
enum {
|
||||||
FP_ERROR = -1,
|
FP_FRE,
|
||||||
FP_DOUBLE_64A = -2,
|
FP_FR0,
|
||||||
|
FP_FR1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct mode_req - ABI FPU mode requirements
|
||||||
|
* @single: The program being loaded needs an FPU but it will only issue
|
||||||
|
* single precision instructions meaning that it can execute in
|
||||||
|
* either FR0 or FR1.
|
||||||
|
* @soft: The soft(-float) requirement means that the program being
|
||||||
|
* loaded needs has no FPU dependency at all (i.e. it has no
|
||||||
|
* FPU instructions).
|
||||||
|
* @fr1: The program being loaded depends on FPU being in FR=1 mode.
|
||||||
|
* @frdefault: The program being loaded depends on the default FPU mode.
|
||||||
|
* That is FR0 for O32 and FR1 for N32/N64.
|
||||||
|
* @fre: The program being loaded depends on FPU with FRE=1. This mode is
|
||||||
|
* a bridge which uses FR=1 whilst still being able to maintain
|
||||||
|
* full compatibility with pre-existing code using the O32 FP32
|
||||||
|
* ABI.
|
||||||
|
*
|
||||||
|
* More information about the FP ABIs can be found here:
|
||||||
|
*
|
||||||
|
* https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking#10.4.1._Basic_mode_set-up
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct mode_req {
|
||||||
|
bool single;
|
||||||
|
bool soft;
|
||||||
|
bool fr1;
|
||||||
|
bool frdefault;
|
||||||
|
bool fre;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mode_req fpu_reqs[] = {
|
||||||
|
[MIPS_ABI_FP_ANY] = { true, true, true, true, true },
|
||||||
|
[MIPS_ABI_FP_DOUBLE] = { false, false, false, true, true },
|
||||||
|
[MIPS_ABI_FP_SINGLE] = { true, false, false, false, false },
|
||||||
|
[MIPS_ABI_FP_SOFT] = { false, true, false, false, false },
|
||||||
|
[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
|
||||||
|
[MIPS_ABI_FP_XX] = { false, false, true, true, true },
|
||||||
|
[MIPS_ABI_FP_64] = { false, false, true, false, false },
|
||||||
|
[MIPS_ABI_FP_64A] = { false, false, true, false, true }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mode requirements when .MIPS.abiflags is not present in the ELF.
|
||||||
|
* Not present means that everything is acceptable except FR1.
|
||||||
|
*/
|
||||||
|
static struct mode_req none_req = { true, true, false, true, true };
|
||||||
|
|
||||||
int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
|
int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
|
||||||
bool is_interp, struct arch_elf_state *state)
|
bool is_interp, struct arch_elf_state *state)
|
||||||
{
|
{
|
||||||
struct elf32_hdr *ehdr = _ehdr;
|
struct elf32_hdr *ehdr32 = _ehdr;
|
||||||
struct elf32_phdr *phdr = _phdr;
|
struct elf32_phdr *phdr32 = _phdr;
|
||||||
|
struct elf64_phdr *phdr64 = _phdr;
|
||||||
struct mips_elf_abiflags_v0 abiflags;
|
struct mips_elf_abiflags_v0 abiflags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (config_enabled(CONFIG_64BIT) &&
|
/* Lets see if this is an O32 ELF */
|
||||||
(ehdr->e_ident[EI_CLASS] != ELFCLASS32))
|
if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
|
||||||
|
/* FR = 1 for N32 */
|
||||||
|
if (ehdr32->e_flags & EF_MIPS_ABI2)
|
||||||
|
state->overall_fp_mode = FP_FR1;
|
||||||
|
else
|
||||||
|
/* Set a good default FPU mode for O32 */
|
||||||
|
state->overall_fp_mode = cpu_has_mips_r6 ?
|
||||||
|
FP_FRE : FP_FR0;
|
||||||
|
|
||||||
|
if (ehdr32->e_flags & EF_MIPS_FP64) {
|
||||||
|
/*
|
||||||
|
* Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it
|
||||||
|
* later if needed
|
||||||
|
*/
|
||||||
|
if (is_interp)
|
||||||
|
state->interp_fp_abi = MIPS_ABI_FP_OLD_64;
|
||||||
|
else
|
||||||
|
state->fp_abi = MIPS_ABI_FP_OLD_64;
|
||||||
|
}
|
||||||
|
if (phdr32->p_type != PT_MIPS_ABIFLAGS)
|
||||||
return 0;
|
return 0;
|
||||||
if (phdr->p_type != PT_MIPS_ABIFLAGS)
|
|
||||||
return 0;
|
if (phdr32->p_filesz < sizeof(abiflags))
|
||||||
if (phdr->p_filesz < sizeof(abiflags))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = kernel_read(elf, phdr->p_offset, (char *)&abiflags,
|
ret = kernel_read(elf, phdr32->p_offset,
|
||||||
|
(char *)&abiflags,
|
||||||
sizeof(abiflags));
|
sizeof(abiflags));
|
||||||
|
} else {
|
||||||
|
/* FR=1 is really the only option for 64-bit */
|
||||||
|
state->overall_fp_mode = FP_FR1;
|
||||||
|
|
||||||
|
if (phdr64->p_type != PT_MIPS_ABIFLAGS)
|
||||||
|
return 0;
|
||||||
|
if (phdr64->p_filesz < sizeof(abiflags))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = kernel_read(elf, phdr64->p_offset,
|
||||||
|
(char *)&abiflags,
|
||||||
|
sizeof(abiflags));
|
||||||
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (ret != sizeof(abiflags))
|
if (ret != sizeof(abiflags))
|
||||||
|
@ -48,35 +131,30 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned get_fp_abi(struct elf32_hdr *ehdr, int in_abi)
|
static inline unsigned get_fp_abi(int in_abi)
|
||||||
{
|
{
|
||||||
/* If the ABI requirement is provided, simply return that */
|
/* If the ABI requirement is provided, simply return that */
|
||||||
if (in_abi != -1)
|
if (in_abi != MIPS_ABI_FP_UNKNOWN)
|
||||||
return in_abi;
|
return in_abi;
|
||||||
|
|
||||||
/* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */
|
/* Unknown ABI */
|
||||||
if (ehdr->e_flags & EF_MIPS_FP64)
|
return MIPS_ABI_FP_UNKNOWN;
|
||||||
return MIPS_ABI_FP_64;
|
|
||||||
|
|
||||||
/* Default to MIPS_ABI_FP_DOUBLE */
|
|
||||||
return MIPS_ABI_FP_DOUBLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_check_elf(void *_ehdr, bool has_interpreter,
|
int arch_check_elf(void *_ehdr, bool has_interpreter,
|
||||||
struct arch_elf_state *state)
|
struct arch_elf_state *state)
|
||||||
{
|
{
|
||||||
struct elf32_hdr *ehdr = _ehdr;
|
struct elf32_hdr *ehdr = _ehdr;
|
||||||
unsigned fp_abi, interp_fp_abi, abi0, abi1;
|
struct mode_req prog_req, interp_req;
|
||||||
|
int fp_abi, interp_fp_abi, abi0, abi1, max_abi;
|
||||||
|
|
||||||
/* Ignore non-O32 binaries */
|
if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
|
||||||
if (config_enabled(CONFIG_64BIT) &&
|
|
||||||
(ehdr->e_ident[EI_CLASS] != ELFCLASS32))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fp_abi = get_fp_abi(ehdr, state->fp_abi);
|
fp_abi = get_fp_abi(state->fp_abi);
|
||||||
|
|
||||||
if (has_interpreter) {
|
if (has_interpreter) {
|
||||||
interp_fp_abi = get_fp_abi(ehdr, state->interp_fp_abi);
|
interp_fp_abi = get_fp_abi(state->interp_fp_abi);
|
||||||
|
|
||||||
abi0 = min(fp_abi, interp_fp_abi);
|
abi0 = min(fp_abi, interp_fp_abi);
|
||||||
abi1 = max(fp_abi, interp_fp_abi);
|
abi1 = max(fp_abi, interp_fp_abi);
|
||||||
|
@ -84,108 +162,103 @@ int arch_check_elf(void *_ehdr, bool has_interpreter,
|
||||||
abi0 = abi1 = fp_abi;
|
abi0 = abi1 = fp_abi;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->overall_abi = FP_ERROR;
|
/* ABI limits. O32 = FP_64A, N32/N64 = FP_SOFT */
|
||||||
|
max_abi = ((ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
|
||||||
|
(!(ehdr->e_flags & EF_MIPS_ABI2))) ?
|
||||||
|
MIPS_ABI_FP_64A : MIPS_ABI_FP_SOFT;
|
||||||
|
|
||||||
if (abi0 == abi1) {
|
if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) ||
|
||||||
state->overall_abi = abi0;
|
(abi1 > max_abi && abi1 != MIPS_ABI_FP_UNKNOWN))
|
||||||
} else if (abi0 == MIPS_ABI_FP_ANY) {
|
|
||||||
state->overall_abi = abi1;
|
|
||||||
} else if (abi0 == MIPS_ABI_FP_DOUBLE) {
|
|
||||||
switch (abi1) {
|
|
||||||
case MIPS_ABI_FP_XX:
|
|
||||||
state->overall_abi = MIPS_ABI_FP_DOUBLE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MIPS_ABI_FP_64A:
|
|
||||||
state->overall_abi = FP_DOUBLE_64A;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (abi0 == MIPS_ABI_FP_SINGLE ||
|
|
||||||
abi0 == MIPS_ABI_FP_SOFT) {
|
|
||||||
/* Cannot link with other ABIs */
|
|
||||||
} else if (abi0 == MIPS_ABI_FP_OLD_64) {
|
|
||||||
switch (abi1) {
|
|
||||||
case MIPS_ABI_FP_XX:
|
|
||||||
case MIPS_ABI_FP_64:
|
|
||||||
case MIPS_ABI_FP_64A:
|
|
||||||
state->overall_abi = MIPS_ABI_FP_64;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (abi0 == MIPS_ABI_FP_XX ||
|
|
||||||
abi0 == MIPS_ABI_FP_64 ||
|
|
||||||
abi0 == MIPS_ABI_FP_64A) {
|
|
||||||
state->overall_abi = MIPS_ABI_FP_64;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state->overall_abi) {
|
|
||||||
case MIPS_ABI_FP_64:
|
|
||||||
case MIPS_ABI_FP_64A:
|
|
||||||
case FP_DOUBLE_64A:
|
|
||||||
if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
|
|
||||||
return -ELIBBAD;
|
return -ELIBBAD;
|
||||||
break;
|
|
||||||
|
|
||||||
case FP_ERROR:
|
/* It's time to determine the FPU mode requirements */
|
||||||
|
prog_req = (abi0 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi0];
|
||||||
|
interp_req = (abi1 == MIPS_ABI_FP_UNKNOWN) ? none_req : fpu_reqs[abi1];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether the program's and interp's ABIs have a matching FPU
|
||||||
|
* mode requirement.
|
||||||
|
*/
|
||||||
|
prog_req.single = interp_req.single && prog_req.single;
|
||||||
|
prog_req.soft = interp_req.soft && prog_req.soft;
|
||||||
|
prog_req.fr1 = interp_req.fr1 && prog_req.fr1;
|
||||||
|
prog_req.frdefault = interp_req.frdefault && prog_req.frdefault;
|
||||||
|
prog_req.fre = interp_req.fre && prog_req.fre;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the desired FPU mode
|
||||||
|
*
|
||||||
|
* Decision making:
|
||||||
|
*
|
||||||
|
* - We want FR_FRE if FRE=1 and both FR=1 and FR=0 are false. This
|
||||||
|
* means that we have a combination of program and interpreter
|
||||||
|
* that inherently require the hybrid FP mode.
|
||||||
|
* - If FR1 and FRDEFAULT is true, that means we hit the any-abi or
|
||||||
|
* fpxx case. This is because, in any-ABI (or no-ABI) we have no FPU
|
||||||
|
* instructions so we don't care about the mode. We will simply use
|
||||||
|
* the one preferred by the hardware. In fpxx case, that ABI can
|
||||||
|
* handle both FR=1 and FR=0, so, again, we simply choose the one
|
||||||
|
* preferred by the hardware. Next, if we only use single-precision
|
||||||
|
* FPU instructions, and the default ABI FPU mode is not good
|
||||||
|
* (ie single + any ABI combination), we set again the FPU mode to the
|
||||||
|
* one is preferred by the hardware. Next, if we know that the code
|
||||||
|
* will only use single-precision instructions, shown by single being
|
||||||
|
* true but frdefault being false, then we again set the FPU mode to
|
||||||
|
* the one that is preferred by the hardware.
|
||||||
|
* - We want FP_FR1 if that's the only matching mode and the default one
|
||||||
|
* is not good.
|
||||||
|
* - Return with -ELIBADD if we can't find a matching FPU mode.
|
||||||
|
*/
|
||||||
|
if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1)
|
||||||
|
state->overall_fp_mode = FP_FRE;
|
||||||
|
else if ((prog_req.fr1 && prog_req.frdefault) ||
|
||||||
|
(prog_req.single && !prog_req.frdefault))
|
||||||
|
/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
|
||||||
|
state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
|
||||||
|
cpu_has_mips_r2_r6) ?
|
||||||
|
FP_FR1 : FP_FR0;
|
||||||
|
else if (prog_req.fr1)
|
||||||
|
state->overall_fp_mode = FP_FR1;
|
||||||
|
else if (!prog_req.fre && !prog_req.frdefault &&
|
||||||
|
!prog_req.fr1 && !prog_req.single && !prog_req.soft)
|
||||||
return -ELIBBAD;
|
return -ELIBBAD;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mips_set_personality_fp(struct arch_elf_state *state)
|
static inline void set_thread_fp_mode(int hybrid, int regs32)
|
||||||
{
|
{
|
||||||
if (config_enabled(CONFIG_FP32XX_HYBRID_FPRS)) {
|
if (hybrid)
|
||||||
/*
|
|
||||||
* Use hybrid FPRs for all code which can correctly execute
|
|
||||||
* with that mode.
|
|
||||||
*/
|
|
||||||
switch (state->overall_abi) {
|
|
||||||
case MIPS_ABI_FP_DOUBLE:
|
|
||||||
case MIPS_ABI_FP_SINGLE:
|
|
||||||
case MIPS_ABI_FP_SOFT:
|
|
||||||
case MIPS_ABI_FP_XX:
|
|
||||||
case MIPS_ABI_FP_ANY:
|
|
||||||
/* FR=1, FRE=1 */
|
|
||||||
clear_thread_flag(TIF_32BIT_FPREGS);
|
|
||||||
set_thread_flag(TIF_HYBRID_FPREGS);
|
set_thread_flag(TIF_HYBRID_FPREGS);
|
||||||
return;
|
else
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state->overall_abi) {
|
|
||||||
case MIPS_ABI_FP_DOUBLE:
|
|
||||||
case MIPS_ABI_FP_SINGLE:
|
|
||||||
case MIPS_ABI_FP_SOFT:
|
|
||||||
/* FR=0 */
|
|
||||||
set_thread_flag(TIF_32BIT_FPREGS);
|
|
||||||
clear_thread_flag(TIF_HYBRID_FPREGS);
|
clear_thread_flag(TIF_HYBRID_FPREGS);
|
||||||
break;
|
if (regs32)
|
||||||
|
|
||||||
case FP_DOUBLE_64A:
|
|
||||||
/* FR=1, FRE=1 */
|
|
||||||
clear_thread_flag(TIF_32BIT_FPREGS);
|
|
||||||
set_thread_flag(TIF_HYBRID_FPREGS);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MIPS_ABI_FP_64:
|
|
||||||
case MIPS_ABI_FP_64A:
|
|
||||||
/* FR=1, FRE=0 */
|
|
||||||
clear_thread_flag(TIF_32BIT_FPREGS);
|
|
||||||
clear_thread_flag(TIF_HYBRID_FPREGS);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MIPS_ABI_FP_XX:
|
|
||||||
case MIPS_ABI_FP_ANY:
|
|
||||||
if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
|
|
||||||
set_thread_flag(TIF_32BIT_FPREGS);
|
set_thread_flag(TIF_32BIT_FPREGS);
|
||||||
else
|
else
|
||||||
clear_thread_flag(TIF_32BIT_FPREGS);
|
clear_thread_flag(TIF_32BIT_FPREGS);
|
||||||
|
}
|
||||||
|
|
||||||
clear_thread_flag(TIF_HYBRID_FPREGS);
|
void mips_set_personality_fp(struct arch_elf_state *state)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function is only ever called for O32 ELFs so we should
|
||||||
|
* not be worried about N32/N64 binaries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (state->overall_fp_mode) {
|
||||||
|
case FP_FRE:
|
||||||
|
set_thread_fp_mode(1, 0);
|
||||||
|
break;
|
||||||
|
case FP_FR0:
|
||||||
|
set_thread_fp_mode(0, 1);
|
||||||
|
break;
|
||||||
|
case FP_FR1:
|
||||||
|
set_thread_fp_mode(0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case FP_ERROR:
|
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,11 @@ resume_userspace:
|
||||||
local_irq_disable # make sure we dont miss an
|
local_irq_disable # make sure we dont miss an
|
||||||
# interrupt setting need_resched
|
# interrupt setting need_resched
|
||||||
# between sampling and return
|
# between sampling and return
|
||||||
|
#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
|
||||||
|
lw k0, TI_R2_EMUL_RET($28)
|
||||||
|
bnez k0, restore_all_from_r2_emul
|
||||||
|
#endif
|
||||||
|
|
||||||
LONG_L a2, TI_FLAGS($28) # current->work
|
LONG_L a2, TI_FLAGS($28) # current->work
|
||||||
andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace)
|
andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace)
|
||||||
bnez t0, work_pending
|
bnez t0, work_pending
|
||||||
|
@ -114,6 +119,19 @@ restore_partial: # restore partial frame
|
||||||
RESTORE_SP_AND_RET
|
RESTORE_SP_AND_RET
|
||||||
.set at
|
.set at
|
||||||
|
|
||||||
|
#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
|
||||||
|
restore_all_from_r2_emul: # restore full frame
|
||||||
|
.set noat
|
||||||
|
sw zero, TI_R2_EMUL_RET($28) # reset it
|
||||||
|
RESTORE_TEMP
|
||||||
|
RESTORE_AT
|
||||||
|
RESTORE_STATIC
|
||||||
|
RESTORE_SOME
|
||||||
|
LONG_L sp, PT_R29(sp)
|
||||||
|
eretnc
|
||||||
|
.set at
|
||||||
|
#endif
|
||||||
|
|
||||||
work_pending:
|
work_pending:
|
||||||
andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
|
andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
|
||||||
beqz t0, work_notifysig
|
beqz t0, work_notifysig
|
||||||
|
@ -158,7 +176,8 @@ syscall_exit_work:
|
||||||
jal syscall_trace_leave
|
jal syscall_trace_leave
|
||||||
b resume_userspace
|
b resume_userspace
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
|
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \
|
||||||
|
defined(CONFIG_MIPS_MT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MIPS32R2 Instruction Hazard Barrier - must be called
|
* MIPS32R2 Instruction Hazard Barrier - must be called
|
||||||
|
@ -171,4 +190,4 @@ LEAF(mips_ihb)
|
||||||
nop
|
nop
|
||||||
END(mips_ihb)
|
END(mips_ihb)
|
||||||
|
|
||||||
#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
|
#endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */
|
||||||
|
|
|
@ -125,7 +125,7 @@ LEAF(__r4k_wait)
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
#endif
|
#endif
|
||||||
.set arch=r4000
|
.set MIPS_ISA_ARCH_LEVEL_RAW
|
||||||
wait
|
wait
|
||||||
/* end of rollback region (the region size must be power of two) */
|
/* end of rollback region (the region size must be power of two) */
|
||||||
1:
|
1:
|
||||||
|
|
|
@ -186,6 +186,7 @@ void __init check_wait(void)
|
||||||
case CPU_PROAPTIV:
|
case CPU_PROAPTIV:
|
||||||
case CPU_P5600:
|
case CPU_P5600:
|
||||||
case CPU_M5150:
|
case CPU_M5150:
|
||||||
|
case CPU_QEMU_GENERIC:
|
||||||
cpu_wait = r4k_wait;
|
cpu_wait = r4k_wait;
|
||||||
if (read_c0_config7() & MIPS_CONF7_WII)
|
if (read_c0_config7() & MIPS_CONF7_WII)
|
||||||
cpu_wait = r4k_wait_irqoff;
|
cpu_wait = r4k_wait_irqoff;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,6 +14,8 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/ftrace.h>
|
#include <asm/ftrace.h>
|
||||||
|
#include <asm/fpu.h>
|
||||||
|
#include <asm/msa.h>
|
||||||
|
|
||||||
extern void *__bzero(void *__s, size_t __count);
|
extern void *__bzero(void *__s, size_t __count);
|
||||||
extern long __strncpy_from_kernel_nocheck_asm(char *__to,
|
extern long __strncpy_from_kernel_nocheck_asm(char *__to,
|
||||||
|
@ -31,6 +33,14 @@ extern long __strnlen_kernel_asm(const char *s);
|
||||||
extern long __strnlen_user_nocheck_asm(const char *s);
|
extern long __strnlen_user_nocheck_asm(const char *s);
|
||||||
extern long __strnlen_user_asm(const char *s);
|
extern long __strnlen_user_asm(const char *s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Core architecture code
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL_GPL(_save_fp);
|
||||||
|
#ifdef CONFIG_CPU_HAS_MSA
|
||||||
|
EXPORT_SYMBOL_GPL(_save_msa);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* String functions
|
* String functions
|
||||||
*/
|
*/
|
||||||
|
@ -67,11 +77,13 @@ EXPORT_SYMBOL(__strnlen_kernel_asm);
|
||||||
EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
|
EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
|
||||||
EXPORT_SYMBOL(__strnlen_user_asm);
|
EXPORT_SYMBOL(__strnlen_user_asm);
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
EXPORT_SYMBOL(csum_partial);
|
EXPORT_SYMBOL(csum_partial);
|
||||||
EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
||||||
EXPORT_SYMBOL(__csum_partial_copy_kernel);
|
EXPORT_SYMBOL(__csum_partial_copy_kernel);
|
||||||
EXPORT_SYMBOL(__csum_partial_copy_to_user);
|
EXPORT_SYMBOL(__csum_partial_copy_to_user);
|
||||||
EXPORT_SYMBOL(__csum_partial_copy_from_user);
|
EXPORT_SYMBOL(__csum_partial_copy_from_user);
|
||||||
|
#endif
|
||||||
|
|
||||||
EXPORT_SYMBOL(invalid_pte_table);
|
EXPORT_SYMBOL(invalid_pte_table);
|
||||||
#ifdef CONFIG_FUNCTION_TRACER
|
#ifdef CONFIG_FUNCTION_TRACER
|
||||||
|
|
|
@ -31,15 +31,11 @@
|
||||||
/*
|
/*
|
||||||
* check if we need to save FPU registers
|
* check if we need to save FPU registers
|
||||||
*/
|
*/
|
||||||
|
.set push
|
||||||
|
.set noreorder
|
||||||
|
beqz a3, 1f
|
||||||
PTR_L t3, TASK_THREAD_INFO(a0)
|
PTR_L t3, TASK_THREAD_INFO(a0)
|
||||||
LONG_L t0, TI_FLAGS(t3)
|
.set pop
|
||||||
li t1, _TIF_USEDFPU
|
|
||||||
and t2, t0, t1
|
|
||||||
beqz t2, 1f
|
|
||||||
nor t1, zero, t1
|
|
||||||
|
|
||||||
and t0, t0, t1
|
|
||||||
LONG_S t0, TI_FLAGS(t3)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* clear saved user stack CU1 bit
|
* clear saved user stack CU1 bit
|
||||||
|
@ -56,36 +52,9 @@
|
||||||
.set pop
|
.set pop
|
||||||
1:
|
1:
|
||||||
|
|
||||||
/* check if we need to save COP2 registers */
|
|
||||||
PTR_L t2, TASK_THREAD_INFO(a0)
|
|
||||||
LONG_L t0, ST_OFF(t2)
|
|
||||||
bbit0 t0, 30, 1f
|
|
||||||
|
|
||||||
/* Disable COP2 in the stored process state */
|
|
||||||
li t1, ST0_CU2
|
|
||||||
xor t0, t1
|
|
||||||
LONG_S t0, ST_OFF(t2)
|
|
||||||
|
|
||||||
/* Enable COP2 so we can save it */
|
|
||||||
mfc0 t0, CP0_STATUS
|
|
||||||
or t0, t1
|
|
||||||
mtc0 t0, CP0_STATUS
|
|
||||||
|
|
||||||
/* Save COP2 */
|
|
||||||
daddu a0, THREAD_CP2
|
|
||||||
jal octeon_cop2_save
|
|
||||||
dsubu a0, THREAD_CP2
|
|
||||||
|
|
||||||
/* Disable COP2 now that we are done */
|
|
||||||
mfc0 t0, CP0_STATUS
|
|
||||||
li t1, ST0_CU2
|
|
||||||
xor t0, t1
|
|
||||||
mtc0 t0, CP0_STATUS
|
|
||||||
|
|
||||||
1:
|
|
||||||
#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
|
#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
|
||||||
/* Check if we need to store CVMSEG state */
|
/* Check if we need to store CVMSEG state */
|
||||||
mfc0 t0, $11,7 /* CvmMemCtl */
|
dmfc0 t0, $11,7 /* CvmMemCtl */
|
||||||
bbit0 t0, 6, 3f /* Is user access enabled? */
|
bbit0 t0, 6, 3f /* Is user access enabled? */
|
||||||
|
|
||||||
/* Store the CVMSEG state */
|
/* Store the CVMSEG state */
|
||||||
|
@ -109,9 +78,9 @@
|
||||||
.set reorder
|
.set reorder
|
||||||
|
|
||||||
/* Disable access to CVMSEG */
|
/* Disable access to CVMSEG */
|
||||||
mfc0 t0, $11,7 /* CvmMemCtl */
|
dmfc0 t0, $11,7 /* CvmMemCtl */
|
||||||
xori t0, t0, 0x40 /* Bit 6 is CVMSEG user enable */
|
xori t0, t0, 0x40 /* Bit 6 is CVMSEG user enable */
|
||||||
mtc0 t0, $11,7 /* CvmMemCtl */
|
dmtc0 t0, $11,7 /* CvmMemCtl */
|
||||||
#endif
|
#endif
|
||||||
3:
|
3:
|
||||||
|
|
||||||
|
@ -147,6 +116,8 @@
|
||||||
* void octeon_cop2_save(struct octeon_cop2_state *a0)
|
* void octeon_cop2_save(struct octeon_cop2_state *a0)
|
||||||
*/
|
*/
|
||||||
.align 7
|
.align 7
|
||||||
|
.set push
|
||||||
|
.set noreorder
|
||||||
LEAF(octeon_cop2_save)
|
LEAF(octeon_cop2_save)
|
||||||
|
|
||||||
dmfc0 t9, $9,7 /* CvmCtl register. */
|
dmfc0 t9, $9,7 /* CvmCtl register. */
|
||||||
|
@ -157,17 +128,17 @@
|
||||||
dmfc2 t2, 0x0200
|
dmfc2 t2, 0x0200
|
||||||
sd t0, OCTEON_CP2_CRC_IV(a0)
|
sd t0, OCTEON_CP2_CRC_IV(a0)
|
||||||
sd t1, OCTEON_CP2_CRC_LENGTH(a0)
|
sd t1, OCTEON_CP2_CRC_LENGTH(a0)
|
||||||
sd t2, OCTEON_CP2_CRC_POLY(a0)
|
|
||||||
/* Skip next instructions if CvmCtl[NODFA_CP2] set */
|
/* Skip next instructions if CvmCtl[NODFA_CP2] set */
|
||||||
bbit1 t9, 28, 1f
|
bbit1 t9, 28, 1f
|
||||||
|
sd t2, OCTEON_CP2_CRC_POLY(a0)
|
||||||
|
|
||||||
/* Save the LLM state */
|
/* Save the LLM state */
|
||||||
dmfc2 t0, 0x0402
|
dmfc2 t0, 0x0402
|
||||||
dmfc2 t1, 0x040A
|
dmfc2 t1, 0x040A
|
||||||
sd t0, OCTEON_CP2_LLM_DAT(a0)
|
sd t0, OCTEON_CP2_LLM_DAT(a0)
|
||||||
sd t1, OCTEON_CP2_LLM_DAT+8(a0)
|
|
||||||
|
|
||||||
1: bbit1 t9, 26, 3f /* done if CvmCtl[NOCRYPTO] set */
|
1: bbit1 t9, 26, 3f /* done if CvmCtl[NOCRYPTO] set */
|
||||||
|
sd t1, OCTEON_CP2_LLM_DAT+8(a0)
|
||||||
|
|
||||||
/* Save the COP2 crypto state */
|
/* Save the COP2 crypto state */
|
||||||
/* this part is mostly common to both pass 1 and later revisions */
|
/* this part is mostly common to both pass 1 and later revisions */
|
||||||
|
@ -198,18 +169,20 @@
|
||||||
sd t2, OCTEON_CP2_AES_KEY+16(a0)
|
sd t2, OCTEON_CP2_AES_KEY+16(a0)
|
||||||
dmfc2 t2, 0x0101
|
dmfc2 t2, 0x0101
|
||||||
sd t3, OCTEON_CP2_AES_KEY+24(a0)
|
sd t3, OCTEON_CP2_AES_KEY+24(a0)
|
||||||
mfc0 t3, $15,0 /* Get the processor ID register */
|
mfc0 v0, $15,0 /* Get the processor ID register */
|
||||||
sd t0, OCTEON_CP2_AES_KEYLEN(a0)
|
sd t0, OCTEON_CP2_AES_KEYLEN(a0)
|
||||||
li t0, 0x000d0000 /* This is the processor ID of Octeon Pass1 */
|
li v1, 0x000d0000 /* This is the processor ID of Octeon Pass1 */
|
||||||
sd t1, OCTEON_CP2_AES_RESULT(a0)
|
sd t1, OCTEON_CP2_AES_RESULT(a0)
|
||||||
sd t2, OCTEON_CP2_AES_RESULT+8(a0)
|
|
||||||
/* Skip to the Pass1 version of the remainder of the COP2 state */
|
/* Skip to the Pass1 version of the remainder of the COP2 state */
|
||||||
beq t3, t0, 2f
|
beq v0, v1, 2f
|
||||||
|
sd t2, OCTEON_CP2_AES_RESULT+8(a0)
|
||||||
|
|
||||||
/* the non-pass1 state when !CvmCtl[NOCRYPTO] */
|
/* the non-pass1 state when !CvmCtl[NOCRYPTO] */
|
||||||
dmfc2 t1, 0x0240
|
dmfc2 t1, 0x0240
|
||||||
dmfc2 t2, 0x0241
|
dmfc2 t2, 0x0241
|
||||||
|
ori v1, v1, 0x9500 /* lowest OCTEON III PrId*/
|
||||||
dmfc2 t3, 0x0242
|
dmfc2 t3, 0x0242
|
||||||
|
subu v1, v0, v1 /* prid - lowest OCTEON III PrId */
|
||||||
dmfc2 t0, 0x0243
|
dmfc2 t0, 0x0243
|
||||||
sd t1, OCTEON_CP2_HSH_DATW(a0)
|
sd t1, OCTEON_CP2_HSH_DATW(a0)
|
||||||
dmfc2 t1, 0x0244
|
dmfc2 t1, 0x0244
|
||||||
|
@ -262,8 +235,16 @@
|
||||||
sd t1, OCTEON_CP2_GFM_MULT+8(a0)
|
sd t1, OCTEON_CP2_GFM_MULT+8(a0)
|
||||||
sd t2, OCTEON_CP2_GFM_POLY(a0)
|
sd t2, OCTEON_CP2_GFM_POLY(a0)
|
||||||
sd t3, OCTEON_CP2_GFM_RESULT(a0)
|
sd t3, OCTEON_CP2_GFM_RESULT(a0)
|
||||||
|
bltz v1, 4f
|
||||||
sd t0, OCTEON_CP2_GFM_RESULT+8(a0)
|
sd t0, OCTEON_CP2_GFM_RESULT+8(a0)
|
||||||
|
/* OCTEON III things*/
|
||||||
|
dmfc2 t0, 0x024F
|
||||||
|
dmfc2 t1, 0x0050
|
||||||
|
sd t0, OCTEON_CP2_SHA3(a0)
|
||||||
|
sd t1, OCTEON_CP2_SHA3+8(a0)
|
||||||
|
4:
|
||||||
jr ra
|
jr ra
|
||||||
|
nop
|
||||||
|
|
||||||
2: /* pass 1 special stuff when !CvmCtl[NOCRYPTO] */
|
2: /* pass 1 special stuff when !CvmCtl[NOCRYPTO] */
|
||||||
dmfc2 t3, 0x0040
|
dmfc2 t3, 0x0040
|
||||||
|
@ -289,7 +270,9 @@
|
||||||
|
|
||||||
3: /* pass 1 or CvmCtl[NOCRYPTO] set */
|
3: /* pass 1 or CvmCtl[NOCRYPTO] set */
|
||||||
jr ra
|
jr ra
|
||||||
|
nop
|
||||||
END(octeon_cop2_save)
|
END(octeon_cop2_save)
|
||||||
|
.set pop
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void octeon_cop2_restore(struct octeon_cop2_state *a0)
|
* void octeon_cop2_restore(struct octeon_cop2_state *a0)
|
||||||
|
@ -354,9 +337,9 @@
|
||||||
ld t2, OCTEON_CP2_AES_RESULT+8(a0)
|
ld t2, OCTEON_CP2_AES_RESULT+8(a0)
|
||||||
mfc0 t3, $15,0 /* Get the processor ID register */
|
mfc0 t3, $15,0 /* Get the processor ID register */
|
||||||
dmtc2 t0, 0x0110
|
dmtc2 t0, 0x0110
|
||||||
li t0, 0x000d0000 /* This is the processor ID of Octeon Pass1 */
|
li v0, 0x000d0000 /* This is the processor ID of Octeon Pass1 */
|
||||||
dmtc2 t1, 0x0100
|
dmtc2 t1, 0x0100
|
||||||
bne t0, t3, 3f /* Skip the next stuff for non-pass1 */
|
bne v0, t3, 3f /* Skip the next stuff for non-pass1 */
|
||||||
dmtc2 t2, 0x0101
|
dmtc2 t2, 0x0101
|
||||||
|
|
||||||
/* this code is specific for pass 1 */
|
/* this code is specific for pass 1 */
|
||||||
|
@ -384,6 +367,7 @@
|
||||||
|
|
||||||
3: /* this is post-pass1 code */
|
3: /* this is post-pass1 code */
|
||||||
ld t2, OCTEON_CP2_HSH_DATW(a0)
|
ld t2, OCTEON_CP2_HSH_DATW(a0)
|
||||||
|
ori v0, v0, 0x9500 /* lowest OCTEON III PrId*/
|
||||||
ld t0, OCTEON_CP2_HSH_DATW+8(a0)
|
ld t0, OCTEON_CP2_HSH_DATW+8(a0)
|
||||||
ld t1, OCTEON_CP2_HSH_DATW+16(a0)
|
ld t1, OCTEON_CP2_HSH_DATW+16(a0)
|
||||||
dmtc2 t2, 0x0240
|
dmtc2 t2, 0x0240
|
||||||
|
@ -437,9 +421,15 @@
|
||||||
dmtc2 t2, 0x0259
|
dmtc2 t2, 0x0259
|
||||||
ld t2, OCTEON_CP2_GFM_RESULT+8(a0)
|
ld t2, OCTEON_CP2_GFM_RESULT+8(a0)
|
||||||
dmtc2 t0, 0x025E
|
dmtc2 t0, 0x025E
|
||||||
|
subu v0, t3, v0 /* prid - lowest OCTEON III PrId */
|
||||||
dmtc2 t1, 0x025A
|
dmtc2 t1, 0x025A
|
||||||
|
bltz v0, done_restore
|
||||||
dmtc2 t2, 0x025B
|
dmtc2 t2, 0x025B
|
||||||
|
/* OCTEON III things*/
|
||||||
|
ld t0, OCTEON_CP2_SHA3(a0)
|
||||||
|
ld t1, OCTEON_CP2_SHA3+8(a0)
|
||||||
|
dmtc2 t0, 0x0051
|
||||||
|
dmtc2 t1, 0x0050
|
||||||
done_restore:
|
done_restore:
|
||||||
jr ra
|
jr ra
|
||||||
nop
|
nop
|
||||||
|
@ -450,18 +440,23 @@ done_restore:
|
||||||
* void octeon_mult_save()
|
* void octeon_mult_save()
|
||||||
* sp is assumed to point to a struct pt_regs
|
* sp is assumed to point to a struct pt_regs
|
||||||
*
|
*
|
||||||
* NOTE: This is called in SAVE_SOME in stackframe.h. It can only
|
* NOTE: This is called in SAVE_TEMP in stackframe.h. It can
|
||||||
* safely modify k0 and k1.
|
* safely modify v1,k0, k1,$10-$15, and $24. It will
|
||||||
|
* be overwritten with a processor specific version of the code.
|
||||||
*/
|
*/
|
||||||
.align 7
|
.p2align 7
|
||||||
.set push
|
.set push
|
||||||
.set noreorder
|
.set noreorder
|
||||||
LEAF(octeon_mult_save)
|
LEAF(octeon_mult_save)
|
||||||
dmfc0 k0, $9,7 /* CvmCtl register. */
|
jr ra
|
||||||
bbit1 k0, 27, 1f /* Skip CvmCtl[NOMUL] */
|
|
||||||
nop
|
nop
|
||||||
|
.space 30 * 4, 0
|
||||||
|
octeon_mult_save_end:
|
||||||
|
EXPORT(octeon_mult_save_end)
|
||||||
|
END(octeon_mult_save)
|
||||||
|
|
||||||
/* Save the multiplier state */
|
LEAF(octeon_mult_save2)
|
||||||
|
/* Save the multiplier state OCTEON II and earlier*/
|
||||||
v3mulu k0, $0, $0
|
v3mulu k0, $0, $0
|
||||||
v3mulu k1, $0, $0
|
v3mulu k1, $0, $0
|
||||||
sd k0, PT_MTP(sp) /* PT_MTP has P0 */
|
sd k0, PT_MTP(sp) /* PT_MTP has P0 */
|
||||||
|
@ -476,44 +471,107 @@ done_restore:
|
||||||
sd k0, PT_MPL+8(sp) /* PT_MPL+8 has MPL1 */
|
sd k0, PT_MPL+8(sp) /* PT_MPL+8 has MPL1 */
|
||||||
jr ra
|
jr ra
|
||||||
sd k1, PT_MPL+16(sp) /* PT_MPL+16 has MPL2 */
|
sd k1, PT_MPL+16(sp) /* PT_MPL+16 has MPL2 */
|
||||||
|
octeon_mult_save2_end:
|
||||||
|
EXPORT(octeon_mult_save2_end)
|
||||||
|
END(octeon_mult_save2)
|
||||||
|
|
||||||
1: /* Resume here if CvmCtl[NOMUL] */
|
LEAF(octeon_mult_save3)
|
||||||
|
/* Save the multiplier state OCTEON III */
|
||||||
|
v3mulu $10, $0, $0 /* read P0 */
|
||||||
|
v3mulu $11, $0, $0 /* read P1 */
|
||||||
|
v3mulu $12, $0, $0 /* read P2 */
|
||||||
|
sd $10, PT_MTP+(0*8)(sp) /* store P0 */
|
||||||
|
v3mulu $10, $0, $0 /* read P3 */
|
||||||
|
sd $11, PT_MTP+(1*8)(sp) /* store P1 */
|
||||||
|
v3mulu $11, $0, $0 /* read P4 */
|
||||||
|
sd $12, PT_MTP+(2*8)(sp) /* store P2 */
|
||||||
|
ori $13, $0, 1
|
||||||
|
v3mulu $12, $0, $0 /* read P5 */
|
||||||
|
sd $10, PT_MTP+(3*8)(sp) /* store P3 */
|
||||||
|
v3mulu $13, $13, $0 /* P4-P0 = MPL5-MPL1, $13 = MPL0 */
|
||||||
|
sd $11, PT_MTP+(4*8)(sp) /* store P4 */
|
||||||
|
v3mulu $10, $0, $0 /* read MPL1 */
|
||||||
|
sd $12, PT_MTP+(5*8)(sp) /* store P5 */
|
||||||
|
v3mulu $11, $0, $0 /* read MPL2 */
|
||||||
|
sd $13, PT_MPL+(0*8)(sp) /* store MPL0 */
|
||||||
|
v3mulu $12, $0, $0 /* read MPL3 */
|
||||||
|
sd $10, PT_MPL+(1*8)(sp) /* store MPL1 */
|
||||||
|
v3mulu $10, $0, $0 /* read MPL4 */
|
||||||
|
sd $11, PT_MPL+(2*8)(sp) /* store MPL2 */
|
||||||
|
v3mulu $11, $0, $0 /* read MPL5 */
|
||||||
|
sd $12, PT_MPL+(3*8)(sp) /* store MPL3 */
|
||||||
|
sd $10, PT_MPL+(4*8)(sp) /* store MPL4 */
|
||||||
jr ra
|
jr ra
|
||||||
END(octeon_mult_save)
|
sd $11, PT_MPL+(5*8)(sp) /* store MPL5 */
|
||||||
|
octeon_mult_save3_end:
|
||||||
|
EXPORT(octeon_mult_save3_end)
|
||||||
|
END(octeon_mult_save3)
|
||||||
.set pop
|
.set pop
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void octeon_mult_restore()
|
* void octeon_mult_restore()
|
||||||
* sp is assumed to point to a struct pt_regs
|
* sp is assumed to point to a struct pt_regs
|
||||||
*
|
*
|
||||||
* NOTE: This is called in RESTORE_SOME in stackframe.h.
|
* NOTE: This is called in RESTORE_TEMP in stackframe.h.
|
||||||
*/
|
*/
|
||||||
.align 7
|
.p2align 7
|
||||||
.set push
|
.set push
|
||||||
.set noreorder
|
.set noreorder
|
||||||
LEAF(octeon_mult_restore)
|
LEAF(octeon_mult_restore)
|
||||||
dmfc0 k1, $9,7 /* CvmCtl register. */
|
jr ra
|
||||||
|
nop
|
||||||
|
.space 30 * 4, 0
|
||||||
|
octeon_mult_restore_end:
|
||||||
|
EXPORT(octeon_mult_restore_end)
|
||||||
|
END(octeon_mult_restore)
|
||||||
|
|
||||||
|
LEAF(octeon_mult_restore2)
|
||||||
ld v0, PT_MPL(sp) /* MPL0 */
|
ld v0, PT_MPL(sp) /* MPL0 */
|
||||||
ld v1, PT_MPL+8(sp) /* MPL1 */
|
ld v1, PT_MPL+8(sp) /* MPL1 */
|
||||||
ld k0, PT_MPL+16(sp) /* MPL2 */
|
ld k0, PT_MPL+16(sp) /* MPL2 */
|
||||||
bbit1 k1, 27, 1f /* Skip CvmCtl[NOMUL] */
|
|
||||||
/* Normally falls through, so no time wasted here */
|
|
||||||
nop
|
|
||||||
|
|
||||||
/* Restore the multiplier state */
|
/* Restore the multiplier state */
|
||||||
ld k1, PT_MTP+16(sp) /* P2 */
|
ld k1, PT_MTP+16(sp) /* P2 */
|
||||||
MTM0 v0 /* MPL0 */
|
mtm0 v0 /* MPL0 */
|
||||||
ld v0, PT_MTP+8(sp) /* P1 */
|
ld v0, PT_MTP+8(sp) /* P1 */
|
||||||
MTM1 v1 /* MPL1 */
|
mtm1 v1 /* MPL1 */
|
||||||
ld v1, PT_MTP(sp) /* P0 */
|
ld v1, PT_MTP(sp) /* P0 */
|
||||||
MTM2 k0 /* MPL2 */
|
mtm2 k0 /* MPL2 */
|
||||||
MTP2 k1 /* P2 */
|
mtp2 k1 /* P2 */
|
||||||
MTP1 v0 /* P1 */
|
mtp1 v0 /* P1 */
|
||||||
jr ra
|
jr ra
|
||||||
MTP0 v1 /* P0 */
|
mtp0 v1 /* P0 */
|
||||||
|
octeon_mult_restore2_end:
|
||||||
|
EXPORT(octeon_mult_restore2_end)
|
||||||
|
END(octeon_mult_restore2)
|
||||||
|
|
||||||
1: /* Resume here if CvmCtl[NOMUL] */
|
LEAF(octeon_mult_restore3)
|
||||||
|
ld $12, PT_MPL+(0*8)(sp) /* read MPL0 */
|
||||||
|
ld $13, PT_MPL+(3*8)(sp) /* read MPL3 */
|
||||||
|
ld $10, PT_MPL+(1*8)(sp) /* read MPL1 */
|
||||||
|
ld $11, PT_MPL+(4*8)(sp) /* read MPL4 */
|
||||||
|
.word 0x718d0008
|
||||||
|
/* mtm0 $12, $13 restore MPL0 and MPL3 */
|
||||||
|
ld $12, PT_MPL+(2*8)(sp) /* read MPL2 */
|
||||||
|
.word 0x714b000c
|
||||||
|
/* mtm1 $10, $11 restore MPL1 and MPL4 */
|
||||||
|
ld $13, PT_MPL+(5*8)(sp) /* read MPL5 */
|
||||||
|
ld $10, PT_MTP+(0*8)(sp) /* read P0 */
|
||||||
|
ld $11, PT_MTP+(3*8)(sp) /* read P3 */
|
||||||
|
.word 0x718d000d
|
||||||
|
/* mtm2 $12, $13 restore MPL2 and MPL5 */
|
||||||
|
ld $12, PT_MTP+(1*8)(sp) /* read P1 */
|
||||||
|
.word 0x714b0009
|
||||||
|
/* mtp0 $10, $11 restore P0 and P3 */
|
||||||
|
ld $13, PT_MTP+(4*8)(sp) /* read P4 */
|
||||||
|
ld $10, PT_MTP+(2*8)(sp) /* read P2 */
|
||||||
|
ld $11, PT_MTP+(5*8)(sp) /* read P5 */
|
||||||
|
.word 0x718d000a
|
||||||
|
/* mtp1 $12, $13 restore P1 and P4 */
|
||||||
jr ra
|
jr ra
|
||||||
nop
|
.word 0x714b000b
|
||||||
END(octeon_mult_restore)
|
/* mtp2 $10, $11 restore P2 and P5 */
|
||||||
|
|
||||||
|
octeon_mult_restore3_end:
|
||||||
|
EXPORT(octeon_mult_restore3_end)
|
||||||
|
END(octeon_mult_restore3)
|
||||||
.set pop
|
.set pop
|
||||||
|
|
|
@ -82,7 +82,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||||
seq_printf(m, "]\n");
|
seq_printf(m, "]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_printf(m, "isa\t\t\t: mips1");
|
seq_printf(m, "isa\t\t\t:");
|
||||||
|
if (cpu_has_mips_r1)
|
||||||
|
seq_printf(m, " mips1");
|
||||||
if (cpu_has_mips_2)
|
if (cpu_has_mips_2)
|
||||||
seq_printf(m, "%s", " mips2");
|
seq_printf(m, "%s", " mips2");
|
||||||
if (cpu_has_mips_3)
|
if (cpu_has_mips_3)
|
||||||
|
@ -95,10 +97,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||||
seq_printf(m, "%s", " mips32r1");
|
seq_printf(m, "%s", " mips32r1");
|
||||||
if (cpu_has_mips32r2)
|
if (cpu_has_mips32r2)
|
||||||
seq_printf(m, "%s", " mips32r2");
|
seq_printf(m, "%s", " mips32r2");
|
||||||
|
if (cpu_has_mips32r6)
|
||||||
|
seq_printf(m, "%s", " mips32r6");
|
||||||
if (cpu_has_mips64r1)
|
if (cpu_has_mips64r1)
|
||||||
seq_printf(m, "%s", " mips64r1");
|
seq_printf(m, "%s", " mips64r1");
|
||||||
if (cpu_has_mips64r2)
|
if (cpu_has_mips64r2)
|
||||||
seq_printf(m, "%s", " mips64r2");
|
seq_printf(m, "%s", " mips64r2");
|
||||||
|
if (cpu_has_mips64r6)
|
||||||
|
seq_printf(m, "%s", " mips64r6");
|
||||||
seq_printf(m, "\n");
|
seq_printf(m, "\n");
|
||||||
|
|
||||||
seq_printf(m, "ASEs implemented\t:");
|
seq_printf(m, "ASEs implemented\t:");
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
|
#include <linux/prctl.h>
|
||||||
|
|
||||||
#include <asm/asm.h>
|
#include <asm/asm.h>
|
||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
|
@ -562,3 +563,98 @@ void arch_trigger_all_cpu_backtrace(bool include_self)
|
||||||
{
|
{
|
||||||
smp_call_function(arch_dump_stack, NULL, 1);
|
smp_call_function(arch_dump_stack, NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mips_get_process_fp_mode(struct task_struct *task)
|
||||||
|
{
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
if (!test_tsk_thread_flag(task, TIF_32BIT_FPREGS))
|
||||||
|
value |= PR_FP_MODE_FR;
|
||||||
|
if (test_tsk_thread_flag(task, TIF_HYBRID_FPREGS))
|
||||||
|
value |= PR_FP_MODE_FRE;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
|
||||||
|
{
|
||||||
|
const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE;
|
||||||
|
unsigned long switch_count;
|
||||||
|
struct task_struct *t;
|
||||||
|
|
||||||
|
/* Check the value is valid */
|
||||||
|
if (value & ~known_bits)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Avoid inadvertently triggering emulation */
|
||||||
|
if ((value & PR_FP_MODE_FR) && cpu_has_fpu &&
|
||||||
|
!(current_cpu_data.fpu_id & MIPS_FPIR_F64))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
if ((value & PR_FP_MODE_FRE) && cpu_has_fpu && !cpu_has_fre)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* FR = 0 not supported in MIPS R6 */
|
||||||
|
if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Save FP & vector context, then disable FPU & MSA */
|
||||||
|
if (task->signal == current->signal)
|
||||||
|
lose_fpu(1);
|
||||||
|
|
||||||
|
/* Prevent any threads from obtaining live FP context */
|
||||||
|
atomic_set(&task->mm->context.fp_mode_switching, 1);
|
||||||
|
smp_mb__after_atomic();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there are multiple online CPUs then wait until all threads whose
|
||||||
|
* FP mode is about to change have been context switched. This approach
|
||||||
|
* allows us to only worry about whether an FP mode switch is in
|
||||||
|
* progress when FP is first used in a tasks time slice. Pretty much all
|
||||||
|
* of the mode switch overhead can thus be confined to cases where mode
|
||||||
|
* switches are actually occuring. That is, to here. However for the
|
||||||
|
* thread performing the mode switch it may take a while...
|
||||||
|
*/
|
||||||
|
if (num_online_cpus() > 1) {
|
||||||
|
spin_lock_irq(&task->sighand->siglock);
|
||||||
|
|
||||||
|
for_each_thread(task, t) {
|
||||||
|
if (t == current)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch_count = t->nvcsw + t->nivcsw;
|
||||||
|
|
||||||
|
do {
|
||||||
|
spin_unlock_irq(&task->sighand->siglock);
|
||||||
|
cond_resched();
|
||||||
|
spin_lock_irq(&task->sighand->siglock);
|
||||||
|
} while ((t->nvcsw + t->nivcsw) == switch_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irq(&task->sighand->siglock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are now no threads of the process with live FP context, so it
|
||||||
|
* is safe to proceed with the FP mode switch.
|
||||||
|
*/
|
||||||
|
for_each_thread(task, t) {
|
||||||
|
/* Update desired FP register width */
|
||||||
|
if (value & PR_FP_MODE_FR) {
|
||||||
|
clear_tsk_thread_flag(t, TIF_32BIT_FPREGS);
|
||||||
|
} else {
|
||||||
|
set_tsk_thread_flag(t, TIF_32BIT_FPREGS);
|
||||||
|
clear_tsk_thread_flag(t, TIF_MSA_CTX_LIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update desired FP single layout */
|
||||||
|
if (value & PR_FP_MODE_FRE)
|
||||||
|
set_tsk_thread_flag(t, TIF_HYBRID_FPREGS);
|
||||||
|
else
|
||||||
|
clear_tsk_thread_flag(t, TIF_HYBRID_FPREGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow threads to use FP again */
|
||||||
|
atomic_set(&task->mm->context.fp_mode_switching, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.set noreorder
|
.set noreorder
|
||||||
.set arch=r4000
|
.set MIPS_ISA_ARCH_LEVEL_RAW
|
||||||
|
|
||||||
LEAF(_save_fp_context)
|
LEAF(_save_fp_context)
|
||||||
.set push
|
.set push
|
||||||
|
@ -42,7 +42,8 @@ LEAF(_save_fp_context)
|
||||||
cfc1 t1, fcr31
|
cfc1 t1, fcr31
|
||||||
.set pop
|
.set pop
|
||||||
|
|
||||||
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
|
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
|
||||||
|
defined(CONFIG_CPU_MIPS32_R6)
|
||||||
.set push
|
.set push
|
||||||
SET_HARDFLOAT
|
SET_HARDFLOAT
|
||||||
#ifdef CONFIG_CPU_MIPS32_R2
|
#ifdef CONFIG_CPU_MIPS32_R2
|
||||||
|
@ -105,10 +106,12 @@ LEAF(_save_fp_context32)
|
||||||
SET_HARDFLOAT
|
SET_HARDFLOAT
|
||||||
cfc1 t1, fcr31
|
cfc1 t1, fcr31
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPS64_R6
|
||||||
mfc0 t0, CP0_STATUS
|
mfc0 t0, CP0_STATUS
|
||||||
sll t0, t0, 5
|
sll t0, t0, 5
|
||||||
bgez t0, 1f # skip storing odd if FR=0
|
bgez t0, 1f # skip storing odd if FR=0
|
||||||
nop
|
nop
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Store the 16 odd double precision registers */
|
/* Store the 16 odd double precision registers */
|
||||||
EX sdc1 $f1, SC32_FPREGS+8(a0)
|
EX sdc1 $f1, SC32_FPREGS+8(a0)
|
||||||
|
@ -163,7 +166,8 @@ LEAF(_save_fp_context32)
|
||||||
LEAF(_restore_fp_context)
|
LEAF(_restore_fp_context)
|
||||||
EX lw t1, SC_FPC_CSR(a0)
|
EX lw t1, SC_FPC_CSR(a0)
|
||||||
|
|
||||||
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
|
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
|
||||||
|
defined(CONFIG_CPU_MIPS32_R6)
|
||||||
.set push
|
.set push
|
||||||
SET_HARDFLOAT
|
SET_HARDFLOAT
|
||||||
#ifdef CONFIG_CPU_MIPS32_R2
|
#ifdef CONFIG_CPU_MIPS32_R2
|
||||||
|
@ -223,10 +227,12 @@ LEAF(_restore_fp_context32)
|
||||||
SET_HARDFLOAT
|
SET_HARDFLOAT
|
||||||
EX lw t1, SC32_FPC_CSR(a0)
|
EX lw t1, SC32_FPC_CSR(a0)
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPS64_R6
|
||||||
mfc0 t0, CP0_STATUS
|
mfc0 t0, CP0_STATUS
|
||||||
sll t0, t0, 5
|
sll t0, t0, 5
|
||||||
bgez t0, 1f # skip loading odd if FR=0
|
bgez t0, 1f # skip loading odd if FR=0
|
||||||
nop
|
nop
|
||||||
|
#endif
|
||||||
|
|
||||||
EX ldc1 $f1, SC32_FPREGS+8(a0)
|
EX ldc1 $f1, SC32_FPREGS+8(a0)
|
||||||
EX ldc1 $f3, SC32_FPREGS+24(a0)
|
EX ldc1 $f3, SC32_FPREGS+24(a0)
|
||||||
|
|
|
@ -115,7 +115,8 @@
|
||||||
* Save a thread's fp context.
|
* Save a thread's fp context.
|
||||||
*/
|
*/
|
||||||
LEAF(_save_fp)
|
LEAF(_save_fp)
|
||||||
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
|
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
|
||||||
|
defined(CONFIG_CPU_MIPS32_R6)
|
||||||
mfc0 t0, CP0_STATUS
|
mfc0 t0, CP0_STATUS
|
||||||
#endif
|
#endif
|
||||||
fpu_save_double a0 t0 t1 # clobbers t1
|
fpu_save_double a0 t0 t1 # clobbers t1
|
||||||
|
@ -126,7 +127,8 @@ LEAF(_save_fp)
|
||||||
* Restore a thread's fp context.
|
* Restore a thread's fp context.
|
||||||
*/
|
*/
|
||||||
LEAF(_restore_fp)
|
LEAF(_restore_fp)
|
||||||
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
|
#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) || \
|
||||||
|
defined(CONFIG_CPU_MIPS32_R6)
|
||||||
mfc0 t0, CP0_STATUS
|
mfc0 t0, CP0_STATUS
|
||||||
#endif
|
#endif
|
||||||
fpu_restore_double a0 t0 t1 # clobbers t1
|
fpu_restore_double a0 t0 t1 # clobbers t1
|
||||||
|
@ -240,9 +242,9 @@ LEAF(_init_fpu)
|
||||||
mtc1 t1, $f30
|
mtc1 t1, $f30
|
||||||
mtc1 t1, $f31
|
mtc1 t1, $f31
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_MIPS32_R2
|
#if defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS32_R6)
|
||||||
.set push
|
.set push
|
||||||
.set mips32r2
|
.set MIPS_ISA_LEVEL_RAW
|
||||||
.set fp=64
|
.set fp=64
|
||||||
sll t0, t0, 5 # is Status.FR set?
|
sll t0, t0, 5 # is Status.FR set?
|
||||||
bgez t0, 1f # no: skip setting upper 32b
|
bgez t0, 1f # no: skip setting upper 32b
|
||||||
|
@ -280,9 +282,9 @@ LEAF(_init_fpu)
|
||||||
mthc1 t1, $f30
|
mthc1 t1, $f30
|
||||||
mthc1 t1, $f31
|
mthc1 t1, $f31
|
||||||
1: .set pop
|
1: .set pop
|
||||||
#endif /* CONFIG_CPU_MIPS32_R2 */
|
#endif /* CONFIG_CPU_MIPS32_R2 || CONFIG_CPU_MIPS32_R6 */
|
||||||
#else
|
#else
|
||||||
.set arch=r4000
|
.set MIPS_ISA_ARCH_LEVEL_RAW
|
||||||
dmtc1 t1, $f0
|
dmtc1 t1, $f0
|
||||||
dmtc1 t1, $f2
|
dmtc1 t1, $f2
|
||||||
dmtc1 t1, $f4
|
dmtc1 t1, $f4
|
||||||
|
|
|
@ -208,6 +208,7 @@ void spram_config(void)
|
||||||
case CPU_INTERAPTIV:
|
case CPU_INTERAPTIV:
|
||||||
case CPU_PROAPTIV:
|
case CPU_PROAPTIV:
|
||||||
case CPU_P5600:
|
case CPU_P5600:
|
||||||
|
case CPU_QEMU_GENERIC:
|
||||||
config0 = read_c0_config();
|
config0 = read_c0_config();
|
||||||
/* FIXME: addresses are Malta specific */
|
/* FIXME: addresses are Malta specific */
|
||||||
if (config0 & (1<<24)) {
|
if (config0 & (1<<24)) {
|
||||||
|
|
|
@ -136,7 +136,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
|
||||||
: "memory");
|
: "memory");
|
||||||
} else if (cpu_has_llsc) {
|
} else if (cpu_has_llsc) {
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
" .set arch=r4000 \n"
|
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||||
" li %[err], 0 \n"
|
" li %[err], 0 \n"
|
||||||
"1: ll %[old], (%[addr]) \n"
|
"1: ll %[old], (%[addr]) \n"
|
||||||
" move %[tmp], %[new] \n"
|
" move %[tmp], %[new] \n"
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
#include <asm/fpu_emulator.h>
|
#include <asm/fpu_emulator.h>
|
||||||
#include <asm/idle.h>
|
#include <asm/idle.h>
|
||||||
|
#include <asm/mips-r2-to-r6-emul.h>
|
||||||
#include <asm/mipsregs.h>
|
#include <asm/mipsregs.h>
|
||||||
#include <asm/mipsmtregs.h>
|
#include <asm/mipsmtregs.h>
|
||||||
#include <asm/module.h>
|
#include <asm/module.h>
|
||||||
|
@ -837,7 +838,7 @@ out:
|
||||||
exception_exit(prev_state);
|
exception_exit(prev_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
||||||
const char *str)
|
const char *str)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
|
@ -1027,7 +1028,34 @@ asmlinkage void do_ri(struct pt_regs *regs)
|
||||||
unsigned int opcode = 0;
|
unsigned int opcode = 0;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid any kernel code. Just emulate the R2 instruction
|
||||||
|
* as quickly as possible.
|
||||||
|
*/
|
||||||
|
if (mipsr2_emulation && cpu_has_mips_r6 &&
|
||||||
|
likely(user_mode(regs))) {
|
||||||
|
if (likely(get_user(opcode, epc) >= 0)) {
|
||||||
|
status = mipsr2_decoder(regs, opcode);
|
||||||
|
switch (status) {
|
||||||
|
case 0:
|
||||||
|
case SIGEMT:
|
||||||
|
task_thread_info(current)->r2_emul_return = 1;
|
||||||
|
return;
|
||||||
|
case SIGILL:
|
||||||
|
goto no_r2_instr;
|
||||||
|
default:
|
||||||
|
process_fpemu_return(status,
|
||||||
|
¤t->thread.cp0_baduaddr);
|
||||||
|
task_thread_info(current)->r2_emul_return = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
no_r2_instr:
|
||||||
|
|
||||||
prev_state = exception_enter();
|
prev_state = exception_enter();
|
||||||
|
|
||||||
if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
|
if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
|
||||||
SIGILL) == NOTIFY_STOP)
|
SIGILL) == NOTIFY_STOP)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1134,10 +1162,29 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wait_on_fp_mode_switch(atomic_t *p)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The FP mode for this task is currently being switched. That may
|
||||||
|
* involve modifications to the format of this tasks FP context which
|
||||||
|
* make it unsafe to proceed with execution for the moment. Instead,
|
||||||
|
* schedule some other task.
|
||||||
|
*/
|
||||||
|
schedule();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int enable_restore_fp_context(int msa)
|
static int enable_restore_fp_context(int msa)
|
||||||
{
|
{
|
||||||
int err, was_fpu_owner, prior_msa;
|
int err, was_fpu_owner, prior_msa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If an FP mode switch is currently underway, wait for it to
|
||||||
|
* complete before proceeding.
|
||||||
|
*/
|
||||||
|
wait_on_atomic_t(¤t->mm->context.fp_mode_switching,
|
||||||
|
wait_on_fp_mode_switch, TASK_KILLABLE);
|
||||||
|
|
||||||
if (!used_math()) {
|
if (!used_math()) {
|
||||||
/* First time FP context user. */
|
/* First time FP context user. */
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
|
@ -1541,6 +1588,7 @@ static inline void parity_protection_init(void)
|
||||||
case CPU_INTERAPTIV:
|
case CPU_INTERAPTIV:
|
||||||
case CPU_PROAPTIV:
|
case CPU_PROAPTIV:
|
||||||
case CPU_P5600:
|
case CPU_P5600:
|
||||||
|
case CPU_QEMU_GENERIC:
|
||||||
{
|
{
|
||||||
#define ERRCTL_PE 0x80000000
|
#define ERRCTL_PE 0x80000000
|
||||||
#define ERRCTL_L2P 0x00800000
|
#define ERRCTL_L2P 0x00800000
|
||||||
|
@ -1630,7 +1678,7 @@ asmlinkage void cache_parity_error(void)
|
||||||
printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n",
|
printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n",
|
||||||
reg_val & (1<<30) ? "secondary" : "primary",
|
reg_val & (1<<30) ? "secondary" : "primary",
|
||||||
reg_val & (1<<31) ? "data" : "insn");
|
reg_val & (1<<31) ? "data" : "insn");
|
||||||
if (cpu_has_mips_r2 &&
|
if ((cpu_has_mips_r2_r6) &&
|
||||||
((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
|
((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
|
||||||
pr_err("Error bits: %s%s%s%s%s%s%s%s\n",
|
pr_err("Error bits: %s%s%s%s%s%s%s%s\n",
|
||||||
reg_val & (1<<29) ? "ED " : "",
|
reg_val & (1<<29) ? "ED " : "",
|
||||||
|
@ -1670,7 +1718,7 @@ asmlinkage void do_ftlb(void)
|
||||||
unsigned int reg_val;
|
unsigned int reg_val;
|
||||||
|
|
||||||
/* For the moment, report the problem and hang. */
|
/* For the moment, report the problem and hang. */
|
||||||
if (cpu_has_mips_r2 &&
|
if ((cpu_has_mips_r2_r6) &&
|
||||||
((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
|
((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
|
||||||
pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
|
pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
|
||||||
read_c0_ecc());
|
read_c0_ecc());
|
||||||
|
@ -1959,7 +2007,7 @@ static void configure_hwrena(void)
|
||||||
{
|
{
|
||||||
unsigned int hwrena = cpu_hwrena_impl_bits;
|
unsigned int hwrena = cpu_hwrena_impl_bits;
|
||||||
|
|
||||||
if (cpu_has_mips_r2)
|
if (cpu_has_mips_r2_r6)
|
||||||
hwrena |= 0x0000000f;
|
hwrena |= 0x0000000f;
|
||||||
|
|
||||||
if (!noulri && cpu_has_userlocal)
|
if (!noulri && cpu_has_userlocal)
|
||||||
|
@ -2003,7 +2051,7 @@ void per_cpu_trap_init(bool is_boot_cpu)
|
||||||
* o read IntCtl.IPTI to determine the timer interrupt
|
* o read IntCtl.IPTI to determine the timer interrupt
|
||||||
* o read IntCtl.IPPCI to determine the performance counter interrupt
|
* o read IntCtl.IPPCI to determine the performance counter interrupt
|
||||||
*/
|
*/
|
||||||
if (cpu_has_mips_r2) {
|
if (cpu_has_mips_r2_r6) {
|
||||||
cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
|
cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
|
||||||
cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
|
cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
|
||||||
cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
|
cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
|
||||||
|
@ -2094,7 +2142,7 @@ void __init trap_init(void)
|
||||||
#else
|
#else
|
||||||
ebase = CKSEG0;
|
ebase = CKSEG0;
|
||||||
#endif
|
#endif
|
||||||
if (cpu_has_mips_r2)
|
if (cpu_has_mips_r2_r6)
|
||||||
ebase += (read_c0_ebase() & 0x3ffff000);
|
ebase += (read_c0_ebase() & 0x3ffff000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,7 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
: "=&r" (value), "=r" (res) \
|
: "=&r" (value), "=r" (res) \
|
||||||
: "r" (addr), "i" (-EFAULT));
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
#define LoadW(addr, value, res) \
|
#define LoadW(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
"1:\t"user_lwl("%0", "(%2)")"\n" \
|
"1:\t"user_lwl("%0", "(%2)")"\n" \
|
||||||
|
@ -146,6 +147,39 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
".previous" \
|
".previous" \
|
||||||
: "=&r" (value), "=r" (res) \
|
: "=&r" (value), "=r" (res) \
|
||||||
: "r" (addr), "i" (-EFAULT));
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
#else
|
||||||
|
/* MIPSR6 has no lwl instruction */
|
||||||
|
#define LoadW(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:"user_lb("%0", "0(%2)")"\n\t" \
|
||||||
|
"2:"user_lbu("$1", "1(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"3:"user_lbu("$1", "2(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"4:"user_lbu("$1", "3(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"li\t%1, 0\n" \
|
||||||
|
".set\tpop\n" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%1, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (value), "=r" (res) \
|
||||||
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
#define LoadHWU(addr, value, res) \
|
#define LoadHWU(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
|
@ -169,6 +203,7 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
: "=&r" (value), "=r" (res) \
|
: "=&r" (value), "=r" (res) \
|
||||||
: "r" (addr), "i" (-EFAULT));
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
#define LoadWU(addr, value, res) \
|
#define LoadWU(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
"1:\t"user_lwl("%0", "(%2)")"\n" \
|
"1:\t"user_lwl("%0", "(%2)")"\n" \
|
||||||
|
@ -206,6 +241,87 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
".previous" \
|
".previous" \
|
||||||
: "=&r" (value), "=r" (res) \
|
: "=&r" (value), "=r" (res) \
|
||||||
: "r" (addr), "i" (-EFAULT));
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
#else
|
||||||
|
/* MIPSR6 has not lwl and ldl instructions */
|
||||||
|
#define LoadWU(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:"user_lbu("%0", "0(%2)")"\n\t" \
|
||||||
|
"2:"user_lbu("$1", "1(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"3:"user_lbu("$1", "2(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"4:"user_lbu("$1", "3(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"li\t%1, 0\n" \
|
||||||
|
".set\tpop\n" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%1, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (value), "=r" (res) \
|
||||||
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
|
||||||
|
#define LoadDW(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:lb\t%0, 0(%2)\n\t" \
|
||||||
|
"2:lbu\t $1, 1(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"3:lbu\t$1, 2(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"4:lbu\t$1, 3(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"5:lbu\t$1, 4(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"6:lbu\t$1, 5(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"7:lbu\t$1, 6(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"8:lbu\t$1, 7(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"li\t%1, 0\n" \
|
||||||
|
".set\tpop\n\t" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%1, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t5b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t6b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t7b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t8b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (value), "=r" (res) \
|
||||||
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
|
|
||||||
#define StoreHW(addr, value, res) \
|
#define StoreHW(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
|
@ -228,6 +344,7 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
: "=r" (res) \
|
: "=r" (res) \
|
||||||
: "r" (value), "r" (addr), "i" (-EFAULT));
|
: "r" (value), "r" (addr), "i" (-EFAULT));
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
#define StoreW(addr, value, res) \
|
#define StoreW(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
"1:\t"user_swl("%1", "(%2)")"\n" \
|
"1:\t"user_swl("%1", "(%2)")"\n" \
|
||||||
|
@ -263,9 +380,82 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
".previous" \
|
".previous" \
|
||||||
: "=r" (res) \
|
: "=r" (res) \
|
||||||
: "r" (value), "r" (addr), "i" (-EFAULT));
|
: "r" (value), "r" (addr), "i" (-EFAULT));
|
||||||
#endif
|
#else
|
||||||
|
/* MIPSR6 has no swl and sdl instructions */
|
||||||
|
#define StoreW(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:"user_sb("%1", "3(%2)")"\n\t" \
|
||||||
|
"srl\t$1, %1, 0x8\n\t" \
|
||||||
|
"2:"user_sb("$1", "2(%2)")"\n\t" \
|
||||||
|
"srl\t$1, $1, 0x8\n\t" \
|
||||||
|
"3:"user_sb("$1", "1(%2)")"\n\t" \
|
||||||
|
"srl\t$1, $1, 0x8\n\t" \
|
||||||
|
"4:"user_sb("$1", "0(%2)")"\n\t" \
|
||||||
|
".set\tpop\n\t" \
|
||||||
|
"li\t%0, 0\n" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%0, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (res) \
|
||||||
|
: "r" (value), "r" (addr), "i" (-EFAULT) \
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
#define StoreDW(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:sb\t%1, 7(%2)\n\t" \
|
||||||
|
"dsrl\t$1, %1, 0x8\n\t" \
|
||||||
|
"2:sb\t$1, 6(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"3:sb\t$1, 5(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"4:sb\t$1, 4(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"5:sb\t$1, 3(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"6:sb\t$1, 2(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"7:sb\t$1, 1(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"8:sb\t$1, 0(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
".set\tpop\n\t" \
|
||||||
|
"li\t%0, 0\n" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%0, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t5b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t6b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t7b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t8b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (res) \
|
||||||
|
: "r" (value), "r" (addr), "i" (-EFAULT) \
|
||||||
|
: "memory");
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
|
#else /* __BIG_ENDIAN */
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN
|
|
||||||
#define LoadHW(addr, value, res) \
|
#define LoadHW(addr, value, res) \
|
||||||
__asm__ __volatile__ (".set\tnoat\n" \
|
__asm__ __volatile__ (".set\tnoat\n" \
|
||||||
"1:\t"user_lb("%0", "1(%2)")"\n" \
|
"1:\t"user_lb("%0", "1(%2)")"\n" \
|
||||||
|
@ -286,6 +476,7 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
: "=&r" (value), "=r" (res) \
|
: "=&r" (value), "=r" (res) \
|
||||||
: "r" (addr), "i" (-EFAULT));
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
#define LoadW(addr, value, res) \
|
#define LoadW(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
"1:\t"user_lwl("%0", "3(%2)")"\n" \
|
"1:\t"user_lwl("%0", "3(%2)")"\n" \
|
||||||
|
@ -303,6 +494,40 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
".previous" \
|
".previous" \
|
||||||
: "=&r" (value), "=r" (res) \
|
: "=&r" (value), "=r" (res) \
|
||||||
: "r" (addr), "i" (-EFAULT));
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
#else
|
||||||
|
/* MIPSR6 has no lwl instruction */
|
||||||
|
#define LoadW(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:"user_lb("%0", "3(%2)")"\n\t" \
|
||||||
|
"2:"user_lbu("$1", "2(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"3:"user_lbu("$1", "1(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"4:"user_lbu("$1", "0(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"li\t%1, 0\n" \
|
||||||
|
".set\tpop\n" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%1, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (value), "=r" (res) \
|
||||||
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
|
|
||||||
#define LoadHWU(addr, value, res) \
|
#define LoadHWU(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
|
@ -326,6 +551,7 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
: "=&r" (value), "=r" (res) \
|
: "=&r" (value), "=r" (res) \
|
||||||
: "r" (addr), "i" (-EFAULT));
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
#define LoadWU(addr, value, res) \
|
#define LoadWU(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
"1:\t"user_lwl("%0", "3(%2)")"\n" \
|
"1:\t"user_lwl("%0", "3(%2)")"\n" \
|
||||||
|
@ -363,6 +589,86 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
".previous" \
|
".previous" \
|
||||||
: "=&r" (value), "=r" (res) \
|
: "=&r" (value), "=r" (res) \
|
||||||
: "r" (addr), "i" (-EFAULT));
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
#else
|
||||||
|
/* MIPSR6 has not lwl and ldl instructions */
|
||||||
|
#define LoadWU(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:"user_lbu("%0", "3(%2)")"\n\t" \
|
||||||
|
"2:"user_lbu("$1", "2(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"3:"user_lbu("$1", "1(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"4:"user_lbu("$1", "0(%2)")"\n\t" \
|
||||||
|
"sll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"li\t%1, 0\n" \
|
||||||
|
".set\tpop\n" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%1, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (value), "=r" (res) \
|
||||||
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
|
||||||
|
#define LoadDW(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:lb\t%0, 7(%2)\n\t" \
|
||||||
|
"2:lbu\t$1, 6(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"3:lbu\t$1, 5(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"4:lbu\t$1, 4(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"5:lbu\t$1, 3(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"6:lbu\t$1, 2(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"7:lbu\t$1, 1(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"8:lbu\t$1, 0(%2)\n\t" \
|
||||||
|
"dsll\t%0, 0x8\n\t" \
|
||||||
|
"or\t%0, $1\n\t" \
|
||||||
|
"li\t%1, 0\n" \
|
||||||
|
".set\tpop\n\t" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%1, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t5b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t6b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t7b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t8b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (value), "=r" (res) \
|
||||||
|
: "r" (addr), "i" (-EFAULT));
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
|
|
||||||
#define StoreHW(addr, value, res) \
|
#define StoreHW(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
|
@ -384,7 +690,7 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
".previous" \
|
".previous" \
|
||||||
: "=r" (res) \
|
: "=r" (res) \
|
||||||
: "r" (value), "r" (addr), "i" (-EFAULT));
|
: "r" (value), "r" (addr), "i" (-EFAULT));
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
#define StoreW(addr, value, res) \
|
#define StoreW(addr, value, res) \
|
||||||
__asm__ __volatile__ ( \
|
__asm__ __volatile__ ( \
|
||||||
"1:\t"user_swl("%1", "3(%2)")"\n" \
|
"1:\t"user_swl("%1", "3(%2)")"\n" \
|
||||||
|
@ -420,6 +726,79 @@ extern void show_registers(struct pt_regs *regs);
|
||||||
".previous" \
|
".previous" \
|
||||||
: "=r" (res) \
|
: "=r" (res) \
|
||||||
: "r" (value), "r" (addr), "i" (-EFAULT));
|
: "r" (value), "r" (addr), "i" (-EFAULT));
|
||||||
|
#else
|
||||||
|
/* MIPSR6 has no swl and sdl instructions */
|
||||||
|
#define StoreW(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:"user_sb("%1", "0(%2)")"\n\t" \
|
||||||
|
"srl\t$1, %1, 0x8\n\t" \
|
||||||
|
"2:"user_sb("$1", "1(%2)")"\n\t" \
|
||||||
|
"srl\t$1, $1, 0x8\n\t" \
|
||||||
|
"3:"user_sb("$1", "2(%2)")"\n\t" \
|
||||||
|
"srl\t$1, $1, 0x8\n\t" \
|
||||||
|
"4:"user_sb("$1", "3(%2)")"\n\t" \
|
||||||
|
".set\tpop\n\t" \
|
||||||
|
"li\t%0, 0\n" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%0, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (res) \
|
||||||
|
: "r" (value), "r" (addr), "i" (-EFAULT) \
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
#define StoreDW(addr, value, res) \
|
||||||
|
__asm__ __volatile__ ( \
|
||||||
|
".set\tpush\n\t" \
|
||||||
|
".set\tnoat\n\t" \
|
||||||
|
"1:sb\t%1, 0(%2)\n\t" \
|
||||||
|
"dsrl\t$1, %1, 0x8\n\t" \
|
||||||
|
"2:sb\t$1, 1(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"3:sb\t$1, 2(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"4:sb\t$1, 3(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"5:sb\t$1, 4(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"6:sb\t$1, 5(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"7:sb\t$1, 6(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
"8:sb\t$1, 7(%2)\n\t" \
|
||||||
|
"dsrl\t$1, $1, 0x8\n\t" \
|
||||||
|
".set\tpop\n\t" \
|
||||||
|
"li\t%0, 0\n" \
|
||||||
|
"10:\n\t" \
|
||||||
|
".insn\n\t" \
|
||||||
|
".section\t.fixup,\"ax\"\n\t" \
|
||||||
|
"11:\tli\t%0, %3\n\t" \
|
||||||
|
"j\t10b\n\t" \
|
||||||
|
".previous\n\t" \
|
||||||
|
".section\t__ex_table,\"a\"\n\t" \
|
||||||
|
STR(PTR)"\t1b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t2b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t3b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t4b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t5b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t6b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t7b, 11b\n\t" \
|
||||||
|
STR(PTR)"\t8b, 11b\n\t" \
|
||||||
|
".previous" \
|
||||||
|
: "=&r" (res) \
|
||||||
|
: "r" (value), "r" (addr), "i" (-EFAULT) \
|
||||||
|
: "memory");
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void emulate_load_store_insn(struct pt_regs *regs,
|
static void emulate_load_store_insn(struct pt_regs *regs,
|
||||||
|
@ -703,10 +1082,13 @@ static void emulate_load_store_insn(struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
/*
|
/*
|
||||||
* COP2 is available to implementor for application specific use.
|
* COP2 is available to implementor for application specific use.
|
||||||
* It's up to applications to register a notifier chain and do
|
* It's up to applications to register a notifier chain and do
|
||||||
* whatever they have to do, including possible sending of signals.
|
* whatever they have to do, including possible sending of signals.
|
||||||
|
*
|
||||||
|
* This instruction has been reallocated in Release 6
|
||||||
*/
|
*/
|
||||||
case lwc2_op:
|
case lwc2_op:
|
||||||
cu2_notifier_call_chain(CU2_LWC2_OP, regs);
|
cu2_notifier_call_chain(CU2_LWC2_OP, regs);
|
||||||
|
@ -723,7 +1105,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
|
||||||
case sdc2_op:
|
case sdc2_op:
|
||||||
cu2_notifier_call_chain(CU2_SDC2_OP, regs);
|
cu2_notifier_call_chain(CU2_SDC2_OP, regs);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* Pheeee... We encountered an yet unknown instruction or
|
* Pheeee... We encountered an yet unknown instruction or
|
||||||
|
|
|
@ -8,6 +8,7 @@ lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \
|
||||||
|
|
||||||
obj-y += iomap.o
|
obj-y += iomap.o
|
||||||
obj-$(CONFIG_PCI) += iomap-pci.o
|
obj-$(CONFIG_PCI) += iomap-pci.o
|
||||||
|
lib-$(CONFIG_GENERIC_CSUM) := $(filter-out csum_partial.o, $(lib-y))
|
||||||
|
|
||||||
obj-$(CONFIG_CPU_GENERIC_DUMP_TLB) += dump_tlb.o
|
obj-$(CONFIG_CPU_GENERIC_DUMP_TLB) += dump_tlb.o
|
||||||
obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
|
obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
|
||||||
|
|
|
@ -293,9 +293,14 @@
|
||||||
and t0, src, ADDRMASK
|
and t0, src, ADDRMASK
|
||||||
PREFS( 0, 2*32(src) )
|
PREFS( 0, 2*32(src) )
|
||||||
PREFD( 1, 2*32(dst) )
|
PREFD( 1, 2*32(dst) )
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
bnez t1, .Ldst_unaligned\@
|
bnez t1, .Ldst_unaligned\@
|
||||||
nop
|
nop
|
||||||
bnez t0, .Lsrc_unaligned_dst_aligned\@
|
bnez t0, .Lsrc_unaligned_dst_aligned\@
|
||||||
|
#else
|
||||||
|
or t0, t0, t1
|
||||||
|
bnez t0, .Lcopy_unaligned_bytes\@
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* use delay slot for fall-through
|
* use delay slot for fall-through
|
||||||
* src and dst are aligned; need to compute rem
|
* src and dst are aligned; need to compute rem
|
||||||
|
@ -376,6 +381,7 @@
|
||||||
bne rem, len, 1b
|
bne rem, len, 1b
|
||||||
.set noreorder
|
.set noreorder
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
/*
|
/*
|
||||||
* src and dst are aligned, need to copy rem bytes (rem < NBYTES)
|
* src and dst are aligned, need to copy rem bytes (rem < NBYTES)
|
||||||
* A loop would do only a byte at a time with possible branch
|
* A loop would do only a byte at a time with possible branch
|
||||||
|
@ -477,6 +483,7 @@
|
||||||
bne len, rem, 1b
|
bne len, rem, 1b
|
||||||
.set noreorder
|
.set noreorder
|
||||||
|
|
||||||
|
#endif /* !CONFIG_CPU_MIPSR6 */
|
||||||
.Lcopy_bytes_checklen\@:
|
.Lcopy_bytes_checklen\@:
|
||||||
beqz len, .Ldone\@
|
beqz len, .Ldone\@
|
||||||
nop
|
nop
|
||||||
|
@ -504,6 +511,22 @@
|
||||||
.Ldone\@:
|
.Ldone\@:
|
||||||
jr ra
|
jr ra
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_MIPSR6
|
||||||
|
.Lcopy_unaligned_bytes\@:
|
||||||
|
1:
|
||||||
|
COPY_BYTE(0)
|
||||||
|
COPY_BYTE(1)
|
||||||
|
COPY_BYTE(2)
|
||||||
|
COPY_BYTE(3)
|
||||||
|
COPY_BYTE(4)
|
||||||
|
COPY_BYTE(5)
|
||||||
|
COPY_BYTE(6)
|
||||||
|
COPY_BYTE(7)
|
||||||
|
ADD src, src, 8
|
||||||
|
b 1b
|
||||||
|
ADD dst, dst, 8
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
.if __memcpy == 1
|
.if __memcpy == 1
|
||||||
END(memcpy)
|
END(memcpy)
|
||||||
.set __memcpy, 0
|
.set __memcpy, 0
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
.set at
|
.set at
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
R10KCBARRIER(0(ra))
|
R10KCBARRIER(0(ra))
|
||||||
#ifdef __MIPSEB__
|
#ifdef __MIPSEB__
|
||||||
EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
|
EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
|
||||||
|
@ -120,6 +121,30 @@
|
||||||
PTR_SUBU a0, t0 /* long align ptr */
|
PTR_SUBU a0, t0 /* long align ptr */
|
||||||
PTR_ADDU a2, t0 /* correct size */
|
PTR_ADDU a2, t0 /* correct size */
|
||||||
|
|
||||||
|
#else /* CONFIG_CPU_MIPSR6 */
|
||||||
|
#define STORE_BYTE(N) \
|
||||||
|
EX(sb, a1, N(a0), .Lbyte_fixup\@); \
|
||||||
|
beqz t0, 0f; \
|
||||||
|
PTR_ADDU t0, 1;
|
||||||
|
|
||||||
|
PTR_ADDU a2, t0 /* correct size */
|
||||||
|
PTR_ADDU t0, 1
|
||||||
|
STORE_BYTE(0)
|
||||||
|
STORE_BYTE(1)
|
||||||
|
#if LONGSIZE == 4
|
||||||
|
EX(sb, a1, 2(a0), .Lbyte_fixup\@)
|
||||||
|
#else
|
||||||
|
STORE_BYTE(2)
|
||||||
|
STORE_BYTE(3)
|
||||||
|
STORE_BYTE(4)
|
||||||
|
STORE_BYTE(5)
|
||||||
|
EX(sb, a1, 6(a0), .Lbyte_fixup\@)
|
||||||
|
#endif
|
||||||
|
0:
|
||||||
|
ori a0, STORMASK
|
||||||
|
xori a0, STORMASK
|
||||||
|
PTR_ADDIU a0, STORSIZE
|
||||||
|
#endif /* CONFIG_CPU_MIPSR6 */
|
||||||
1: ori t1, a2, 0x3f /* # of full blocks */
|
1: ori t1, a2, 0x3f /* # of full blocks */
|
||||||
xori t1, 0x3f
|
xori t1, 0x3f
|
||||||
beqz t1, .Lmemset_partial\@ /* no block to fill */
|
beqz t1, .Lmemset_partial\@ /* no block to fill */
|
||||||
|
@ -159,6 +184,7 @@
|
||||||
andi a2, STORMASK /* At most one long to go */
|
andi a2, STORMASK /* At most one long to go */
|
||||||
|
|
||||||
beqz a2, 1f
|
beqz a2, 1f
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
PTR_ADDU a0, a2 /* What's left */
|
PTR_ADDU a0, a2 /* What's left */
|
||||||
R10KCBARRIER(0(ra))
|
R10KCBARRIER(0(ra))
|
||||||
#ifdef __MIPSEB__
|
#ifdef __MIPSEB__
|
||||||
|
@ -166,6 +192,22 @@
|
||||||
#else
|
#else
|
||||||
EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
|
EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
PTR_SUBU t0, $0, a2
|
||||||
|
PTR_ADDIU t0, 1
|
||||||
|
STORE_BYTE(0)
|
||||||
|
STORE_BYTE(1)
|
||||||
|
#if LONGSIZE == 4
|
||||||
|
EX(sb, a1, 2(a0), .Lbyte_fixup\@)
|
||||||
|
#else
|
||||||
|
STORE_BYTE(2)
|
||||||
|
STORE_BYTE(3)
|
||||||
|
STORE_BYTE(4)
|
||||||
|
STORE_BYTE(5)
|
||||||
|
EX(sb, a1, 6(a0), .Lbyte_fixup\@)
|
||||||
|
#endif
|
||||||
|
0:
|
||||||
|
#endif
|
||||||
1: jr ra
|
1: jr ra
|
||||||
move a2, zero
|
move a2, zero
|
||||||
|
|
||||||
|
@ -186,6 +228,11 @@
|
||||||
.hidden __memset
|
.hidden __memset
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
.Lbyte_fixup\@:
|
||||||
|
PTR_SUBU a2, $0, t0
|
||||||
|
jr ra
|
||||||
|
PTR_ADDIU a2, 1
|
||||||
|
|
||||||
.Lfirst_fixup\@:
|
.Lfirst_fixup\@:
|
||||||
jr ra
|
jr ra
|
||||||
nop
|
nop
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/stringify.h>
|
#include <linux/stringify.h>
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_MIPSR2
|
#if !defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_MIPSR6)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For cli() we have to insert nops to make sure that the new value
|
* For cli() we have to insert nops to make sure that the new value
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/fpu_emulator.h>
|
#include <asm/fpu_emulator.h>
|
||||||
#include <asm/fpu.h>
|
#include <asm/fpu.h>
|
||||||
|
#include <asm/mips-r2-to-r6-emul.h>
|
||||||
|
|
||||||
#include "ieee754.h"
|
#include "ieee754.h"
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ static int fpux_emu(struct pt_regs *,
|
||||||
#define modeindex(v) ((v) & FPU_CSR_RM)
|
#define modeindex(v) ((v) & FPU_CSR_RM)
|
||||||
|
|
||||||
/* convert condition code register number to csr bit */
|
/* convert condition code register number to csr bit */
|
||||||
static const unsigned int fpucondbit[8] = {
|
const unsigned int fpucondbit[8] = {
|
||||||
FPU_CSR_COND0,
|
FPU_CSR_COND0,
|
||||||
FPU_CSR_COND1,
|
FPU_CSR_COND1,
|
||||||
FPU_CSR_COND2,
|
FPU_CSR_COND2,
|
||||||
|
@ -448,6 +449,9 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
dec_insn.next_pc_inc;
|
dec_insn.next_pc_inc;
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case jr_op:
|
case jr_op:
|
||||||
|
/* For R6, JR already emulated in jalr_op */
|
||||||
|
if (NO_R6EMU && insn.r_format.opcode == jr_op)
|
||||||
|
break;
|
||||||
*contpc = regs->regs[insn.r_format.rs];
|
*contpc = regs->regs[insn.r_format.rs];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -456,12 +460,18 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
switch (insn.i_format.rt) {
|
switch (insn.i_format.rt) {
|
||||||
case bltzal_op:
|
case bltzal_op:
|
||||||
case bltzall_op:
|
case bltzall_op:
|
||||||
|
if (NO_R6EMU && (insn.i_format.rs ||
|
||||||
|
insn.i_format.rt == bltzall_op))
|
||||||
|
break;
|
||||||
|
|
||||||
regs->regs[31] = regs->cp0_epc +
|
regs->regs[31] = regs->cp0_epc +
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
dec_insn.next_pc_inc;
|
dec_insn.next_pc_inc;
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case bltz_op:
|
|
||||||
case bltzl_op:
|
case bltzl_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
break;
|
||||||
|
case bltz_op:
|
||||||
if ((long)regs->regs[insn.i_format.rs] < 0)
|
if ((long)regs->regs[insn.i_format.rs] < 0)
|
||||||
*contpc = regs->cp0_epc +
|
*contpc = regs->cp0_epc +
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
|
@ -473,12 +483,18 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
return 1;
|
return 1;
|
||||||
case bgezal_op:
|
case bgezal_op:
|
||||||
case bgezall_op:
|
case bgezall_op:
|
||||||
|
if (NO_R6EMU && (insn.i_format.rs ||
|
||||||
|
insn.i_format.rt == bgezall_op))
|
||||||
|
break;
|
||||||
|
|
||||||
regs->regs[31] = regs->cp0_epc +
|
regs->regs[31] = regs->cp0_epc +
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
dec_insn.next_pc_inc;
|
dec_insn.next_pc_inc;
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case bgez_op:
|
|
||||||
case bgezl_op:
|
case bgezl_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
break;
|
||||||
|
case bgez_op:
|
||||||
if ((long)regs->regs[insn.i_format.rs] >= 0)
|
if ((long)regs->regs[insn.i_format.rs] >= 0)
|
||||||
*contpc = regs->cp0_epc +
|
*contpc = regs->cp0_epc +
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
|
@ -505,8 +521,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
/* Set microMIPS mode bit: XOR for jalx. */
|
/* Set microMIPS mode bit: XOR for jalx. */
|
||||||
*contpc ^= bit;
|
*contpc ^= bit;
|
||||||
return 1;
|
return 1;
|
||||||
case beq_op:
|
|
||||||
case beql_op:
|
case beql_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
break;
|
||||||
|
case beq_op:
|
||||||
if (regs->regs[insn.i_format.rs] ==
|
if (regs->regs[insn.i_format.rs] ==
|
||||||
regs->regs[insn.i_format.rt])
|
regs->regs[insn.i_format.rt])
|
||||||
*contpc = regs->cp0_epc +
|
*contpc = regs->cp0_epc +
|
||||||
|
@ -517,8 +535,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
dec_insn.next_pc_inc;
|
dec_insn.next_pc_inc;
|
||||||
return 1;
|
return 1;
|
||||||
case bne_op:
|
|
||||||
case bnel_op:
|
case bnel_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
break;
|
||||||
|
case bne_op:
|
||||||
if (regs->regs[insn.i_format.rs] !=
|
if (regs->regs[insn.i_format.rs] !=
|
||||||
regs->regs[insn.i_format.rt])
|
regs->regs[insn.i_format.rt])
|
||||||
*contpc = regs->cp0_epc +
|
*contpc = regs->cp0_epc +
|
||||||
|
@ -529,8 +549,34 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
dec_insn.next_pc_inc;
|
dec_insn.next_pc_inc;
|
||||||
return 1;
|
return 1;
|
||||||
case blez_op:
|
|
||||||
case blezl_op:
|
case blezl_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
break;
|
||||||
|
case blez_op:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compact branches for R6 for the
|
||||||
|
* blez and blezl opcodes.
|
||||||
|
* BLEZ | rs = 0 | rt != 0 == BLEZALC
|
||||||
|
* BLEZ | rs = rt != 0 == BGEZALC
|
||||||
|
* BLEZ | rs != 0 | rt != 0 == BGEUC
|
||||||
|
* BLEZL | rs = 0 | rt != 0 == BLEZC
|
||||||
|
* BLEZL | rs = rt != 0 == BGEZC
|
||||||
|
* BLEZL | rs != 0 | rt != 0 == BGEC
|
||||||
|
*
|
||||||
|
* For real BLEZ{,L}, rt is always 0.
|
||||||
|
*/
|
||||||
|
if (cpu_has_mips_r6 && insn.i_format.rt) {
|
||||||
|
if ((insn.i_format.opcode == blez_op) &&
|
||||||
|
((!insn.i_format.rs && insn.i_format.rt) ||
|
||||||
|
(insn.i_format.rs == insn.i_format.rt)))
|
||||||
|
regs->regs[31] = regs->cp0_epc +
|
||||||
|
dec_insn.pc_inc;
|
||||||
|
*contpc = regs->cp0_epc + dec_insn.pc_inc +
|
||||||
|
dec_insn.next_pc_inc;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if ((long)regs->regs[insn.i_format.rs] <= 0)
|
if ((long)regs->regs[insn.i_format.rs] <= 0)
|
||||||
*contpc = regs->cp0_epc +
|
*contpc = regs->cp0_epc +
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
|
@ -540,8 +586,35 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
dec_insn.next_pc_inc;
|
dec_insn.next_pc_inc;
|
||||||
return 1;
|
return 1;
|
||||||
case bgtz_op:
|
|
||||||
case bgtzl_op:
|
case bgtzl_op:
|
||||||
|
if (NO_R6EMU)
|
||||||
|
break;
|
||||||
|
case bgtz_op:
|
||||||
|
/*
|
||||||
|
* Compact branches for R6 for the
|
||||||
|
* bgtz and bgtzl opcodes.
|
||||||
|
* BGTZ | rs = 0 | rt != 0 == BGTZALC
|
||||||
|
* BGTZ | rs = rt != 0 == BLTZALC
|
||||||
|
* BGTZ | rs != 0 | rt != 0 == BLTUC
|
||||||
|
* BGTZL | rs = 0 | rt != 0 == BGTZC
|
||||||
|
* BGTZL | rs = rt != 0 == BLTZC
|
||||||
|
* BGTZL | rs != 0 | rt != 0 == BLTC
|
||||||
|
*
|
||||||
|
* *ZALC varint for BGTZ &&& rt != 0
|
||||||
|
* For real GTZ{,L}, rt is always 0.
|
||||||
|
*/
|
||||||
|
if (cpu_has_mips_r6 && insn.i_format.rt) {
|
||||||
|
if ((insn.i_format.opcode == blez_op) &&
|
||||||
|
((!insn.i_format.rs && insn.i_format.rt) ||
|
||||||
|
(insn.i_format.rs == insn.i_format.rt)))
|
||||||
|
regs->regs[31] = regs->cp0_epc +
|
||||||
|
dec_insn.pc_inc;
|
||||||
|
*contpc = regs->cp0_epc + dec_insn.pc_inc +
|
||||||
|
dec_insn.next_pc_inc;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((long)regs->regs[insn.i_format.rs] > 0)
|
if ((long)regs->regs[insn.i_format.rs] > 0)
|
||||||
*contpc = regs->cp0_epc +
|
*contpc = regs->cp0_epc +
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
|
@ -551,6 +624,16 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
dec_insn.pc_inc +
|
dec_insn.pc_inc +
|
||||||
dec_insn.next_pc_inc;
|
dec_insn.next_pc_inc;
|
||||||
return 1;
|
return 1;
|
||||||
|
case cbcond0_op:
|
||||||
|
case cbcond1_op:
|
||||||
|
if (!cpu_has_mips_r6)
|
||||||
|
break;
|
||||||
|
if (insn.i_format.rt && !insn.i_format.rs)
|
||||||
|
regs->regs[31] = regs->cp0_epc + 4;
|
||||||
|
*contpc = regs->cp0_epc + dec_insn.pc_inc +
|
||||||
|
dec_insn.next_pc_inc;
|
||||||
|
|
||||||
|
return 1;
|
||||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||||
case lwc2_op: /* This is bbit0 on Octeon */
|
case lwc2_op: /* This is bbit0 on Octeon */
|
||||||
if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
|
if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
|
||||||
|
@ -576,9 +659,73 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||||
else
|
else
|
||||||
*contpc = regs->cp0_epc + 8;
|
*contpc = regs->cp0_epc + 8;
|
||||||
return 1;
|
return 1;
|
||||||
|
#else
|
||||||
|
case bc6_op:
|
||||||
|
/*
|
||||||
|
* Only valid for MIPS R6 but we can still end up
|
||||||
|
* here from a broken userland so just tell emulator
|
||||||
|
* this is not a branch and let it break later on.
|
||||||
|
*/
|
||||||
|
if (!cpu_has_mips_r6)
|
||||||
|
break;
|
||||||
|
*contpc = regs->cp0_epc + dec_insn.pc_inc +
|
||||||
|
dec_insn.next_pc_inc;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
case balc6_op:
|
||||||
|
if (!cpu_has_mips_r6)
|
||||||
|
break;
|
||||||
|
regs->regs[31] = regs->cp0_epc + 4;
|
||||||
|
*contpc = regs->cp0_epc + dec_insn.pc_inc +
|
||||||
|
dec_insn.next_pc_inc;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
case beqzcjic_op:
|
||||||
|
if (!cpu_has_mips_r6)
|
||||||
|
break;
|
||||||
|
*contpc = regs->cp0_epc + dec_insn.pc_inc +
|
||||||
|
dec_insn.next_pc_inc;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
case bnezcjialc_op:
|
||||||
|
if (!cpu_has_mips_r6)
|
||||||
|
break;
|
||||||
|
if (!insn.i_format.rs)
|
||||||
|
regs->regs[31] = regs->cp0_epc + 4;
|
||||||
|
*contpc = regs->cp0_epc + dec_insn.pc_inc +
|
||||||
|
dec_insn.next_pc_inc;
|
||||||
|
|
||||||
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
case cop0_op:
|
case cop0_op:
|
||||||
case cop1_op:
|
case cop1_op:
|
||||||
|
/* Need to check for R6 bc1nez and bc1eqz branches */
|
||||||
|
if (cpu_has_mips_r6 &&
|
||||||
|
((insn.i_format.rs == bc1eqz_op) ||
|
||||||
|
(insn.i_format.rs == bc1nez_op))) {
|
||||||
|
bit = 0;
|
||||||
|
switch (insn.i_format.rs) {
|
||||||
|
case bc1eqz_op:
|
||||||
|
if (get_fpr32(¤t->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1)
|
||||||
|
bit = 1;
|
||||||
|
break;
|
||||||
|
case bc1nez_op:
|
||||||
|
if (!(get_fpr32(¤t->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1))
|
||||||
|
bit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (bit)
|
||||||
|
*contpc = regs->cp0_epc +
|
||||||
|
dec_insn.pc_inc +
|
||||||
|
(insn.i_format.simmediate << 2);
|
||||||
|
else
|
||||||
|
*contpc = regs->cp0_epc +
|
||||||
|
dec_insn.pc_inc +
|
||||||
|
dec_insn.next_pc_inc;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* R2/R6 compatible cop1 instruction. Fall through */
|
||||||
case cop2_op:
|
case cop2_op:
|
||||||
case cop1x_op:
|
case cop1x_op:
|
||||||
if (insn.i_format.rs == bc_op) {
|
if (insn.i_format.rs == bc_op) {
|
||||||
|
@ -1414,14 +1561,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
* achieve full IEEE-754 accuracy - however this emulator does.
|
* achieve full IEEE-754 accuracy - however this emulator does.
|
||||||
*/
|
*/
|
||||||
case frsqrt_op:
|
case frsqrt_op:
|
||||||
if (!cpu_has_mips_4_5_r2)
|
if (!cpu_has_mips_4_5_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_sp_rsqrt;
|
handler.u = fpemu_sp_rsqrt;
|
||||||
goto scopuop;
|
goto scopuop;
|
||||||
|
|
||||||
case frecip_op:
|
case frecip_op:
|
||||||
if (!cpu_has_mips_4_5_r2)
|
if (!cpu_has_mips_4_5_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_sp_recip;
|
handler.u = fpemu_sp_recip;
|
||||||
|
@ -1616,13 +1763,13 @@ copcsr:
|
||||||
* achieve full IEEE-754 accuracy - however this emulator does.
|
* achieve full IEEE-754 accuracy - however this emulator does.
|
||||||
*/
|
*/
|
||||||
case frsqrt_op:
|
case frsqrt_op:
|
||||||
if (!cpu_has_mips_4_5_r2)
|
if (!cpu_has_mips_4_5_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_dp_rsqrt;
|
handler.u = fpemu_dp_rsqrt;
|
||||||
goto dcopuop;
|
goto dcopuop;
|
||||||
case frecip_op:
|
case frecip_op:
|
||||||
if (!cpu_has_mips_4_5_r2)
|
if (!cpu_has_mips_4_5_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_dp_recip;
|
handler.u = fpemu_dp_recip;
|
||||||
|
|
|
@ -794,7 +794,7 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
".set push\n\t"
|
".set push\n\t"
|
||||||
".set noat\n\t"
|
".set noat\n\t"
|
||||||
".set mips3\n\t"
|
".set "MIPS_ISA_LEVEL"\n\t"
|
||||||
#ifdef CONFIG_32BIT
|
#ifdef CONFIG_32BIT
|
||||||
"la $at,1f\n\t"
|
"la $at,1f\n\t"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1255,6 +1255,7 @@ static void probe_pcache(void)
|
||||||
case CPU_P5600:
|
case CPU_P5600:
|
||||||
case CPU_PROAPTIV:
|
case CPU_PROAPTIV:
|
||||||
case CPU_M5150:
|
case CPU_M5150:
|
||||||
|
case CPU_QEMU_GENERIC:
|
||||||
if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
|
if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
|
||||||
(c->icache.waysize > PAGE_SIZE))
|
(c->icache.waysize > PAGE_SIZE))
|
||||||
c->icache.flags |= MIPS_CACHE_ALIASES;
|
c->icache.flags |= MIPS_CACHE_ALIASES;
|
||||||
|
@ -1472,7 +1473,8 @@ static void setup_scache(void)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
|
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
|
||||||
MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
|
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
|
||||||
|
MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)) {
|
||||||
#ifdef CONFIG_MIPS_CPU_SCACHE
|
#ifdef CONFIG_MIPS_CPU_SCACHE
|
||||||
if (mips_sc_init ()) {
|
if (mips_sc_init ()) {
|
||||||
scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
|
scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/mman.h>
|
#include <linux/mman.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
|
@ -28,6 +29,8 @@
|
||||||
#include <asm/highmem.h> /* For VMALLOC_END */
|
#include <asm/highmem.h> /* For VMALLOC_END */
|
||||||
#include <linux/kdebug.h>
|
#include <linux/kdebug.h>
|
||||||
|
|
||||||
|
int show_unhandled_signals = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine handles page faults. It determines the address,
|
* This routine handles page faults. It determines the address,
|
||||||
* and the problem, and then passes it off to one of the appropriate
|
* and the problem, and then passes it off to one of the appropriate
|
||||||
|
@ -44,6 +47,8 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
|
||||||
int fault;
|
int fault;
|
||||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||||
|
|
||||||
|
static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(),
|
printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(),
|
||||||
current->comm, current->pid, field, address, write,
|
current->comm, current->pid, field, address, write,
|
||||||
|
@ -203,15 +208,21 @@ bad_area_nosemaphore:
|
||||||
if (user_mode(regs)) {
|
if (user_mode(regs)) {
|
||||||
tsk->thread.cp0_badvaddr = address;
|
tsk->thread.cp0_badvaddr = address;
|
||||||
tsk->thread.error_code = write;
|
tsk->thread.error_code = write;
|
||||||
#if 0
|
if (show_unhandled_signals &&
|
||||||
printk("do_page_fault() #2: sending SIGSEGV to %s for "
|
unhandled_signal(tsk, SIGSEGV) &&
|
||||||
"invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
|
__ratelimit(&ratelimit_state)) {
|
||||||
|
pr_info("\ndo_page_fault(): sending SIGSEGV to %s for invalid %s %0*lx",
|
||||||
tsk->comm,
|
tsk->comm,
|
||||||
write ? "write access to" : "read access from",
|
write ? "write access to" : "read access from",
|
||||||
field, address,
|
field, address);
|
||||||
field, (unsigned long) regs->cp0_epc,
|
pr_info("epc = %0*lx in", field,
|
||||||
field, (unsigned long) regs->regs[31]);
|
(unsigned long) regs->cp0_epc);
|
||||||
#endif
|
print_vma_addr(" ", regs->cp0_epc);
|
||||||
|
pr_info("ra = %0*lx in", field,
|
||||||
|
(unsigned long) regs->regs[31]);
|
||||||
|
print_vma_addr(" ", regs->regs[31]);
|
||||||
|
pr_info("\n");
|
||||||
|
}
|
||||||
info.si_signo = SIGSEGV;
|
info.si_signo = SIGSEGV;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
/* info.si_code has been set above */
|
/* info.si_code has been set above */
|
||||||
|
|
|
@ -72,6 +72,20 @@ static struct uasm_reloc relocs[5];
|
||||||
#define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x00002010)
|
#define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x00002010)
|
||||||
#define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x00002020)
|
#define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x00002020)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* R6 has a limited offset of the pref instruction.
|
||||||
|
* Skip it if the offset is more than 9 bits.
|
||||||
|
*/
|
||||||
|
#define _uasm_i_pref(a, b, c, d) \
|
||||||
|
do { \
|
||||||
|
if (cpu_has_mips_r6) { \
|
||||||
|
if (c <= 0xff && c >= -0x100) \
|
||||||
|
uasm_i_pref(a, b, c, d);\
|
||||||
|
} else { \
|
||||||
|
uasm_i_pref(a, b, c, d); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
static int pref_bias_clear_store;
|
static int pref_bias_clear_store;
|
||||||
static int pref_bias_copy_load;
|
static int pref_bias_copy_load;
|
||||||
static int pref_bias_copy_store;
|
static int pref_bias_copy_store;
|
||||||
|
@ -178,6 +192,14 @@ static void set_prefetch_parameters(void)
|
||||||
pref_bias_copy_load = 256;
|
pref_bias_copy_load = 256;
|
||||||
pref_bias_copy_store = 128;
|
pref_bias_copy_store = 128;
|
||||||
pref_src_mode = Pref_LoadStreamed;
|
pref_src_mode = Pref_LoadStreamed;
|
||||||
|
if (cpu_has_mips_r6)
|
||||||
|
/*
|
||||||
|
* Bit 30 (Pref_PrepareForStore) has been
|
||||||
|
* removed from MIPS R6. Use bit 5
|
||||||
|
* (Pref_StoreStreamed).
|
||||||
|
*/
|
||||||
|
pref_dst_mode = Pref_StoreStreamed;
|
||||||
|
else
|
||||||
pref_dst_mode = Pref_PrepareForStore;
|
pref_dst_mode = Pref_PrepareForStore;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +236,7 @@ static inline void build_clear_pref(u32 **buf, int off)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pref_bias_clear_store) {
|
if (pref_bias_clear_store) {
|
||||||
uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
|
_uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
|
||||||
A0);
|
A0);
|
||||||
} else if (cache_line_size == (half_clear_loop_size << 1)) {
|
} else if (cache_line_size == (half_clear_loop_size << 1)) {
|
||||||
if (cpu_has_cache_cdex_s) {
|
if (cpu_has_cache_cdex_s) {
|
||||||
|
@ -357,7 +379,7 @@ static inline void build_copy_load_pref(u32 **buf, int off)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pref_bias_copy_load)
|
if (pref_bias_copy_load)
|
||||||
uasm_i_pref(buf, pref_src_mode, pref_bias_copy_load + off, A1);
|
_uasm_i_pref(buf, pref_src_mode, pref_bias_copy_load + off, A1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void build_copy_store_pref(u32 **buf, int off)
|
static inline void build_copy_store_pref(u32 **buf, int off)
|
||||||
|
@ -366,7 +388,7 @@ static inline void build_copy_store_pref(u32 **buf, int off)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pref_bias_copy_store) {
|
if (pref_bias_copy_store) {
|
||||||
uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
|
_uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
|
||||||
A0);
|
A0);
|
||||||
} else if (cache_line_size == (half_copy_loop_size << 1)) {
|
} else if (cache_line_size == (half_copy_loop_size << 1)) {
|
||||||
if (cpu_has_cache_cdex_s) {
|
if (cpu_has_cache_cdex_s) {
|
||||||
|
|
|
@ -81,6 +81,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
|
||||||
case CPU_PROAPTIV:
|
case CPU_PROAPTIV:
|
||||||
case CPU_P5600:
|
case CPU_P5600:
|
||||||
case CPU_BMIPS5000:
|
case CPU_BMIPS5000:
|
||||||
|
case CPU_QEMU_GENERIC:
|
||||||
if (config2 & (1 << 12))
|
if (config2 & (1 << 12))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +105,8 @@ static inline int __init mips_sc_probe(void)
|
||||||
|
|
||||||
/* Ignore anything but MIPSxx processors */
|
/* Ignore anything but MIPSxx processors */
|
||||||
if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
|
if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
|
||||||
MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)))
|
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
|
||||||
|
MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M64R6)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Does this MIPS32/MIPS64 CPU have a config2 register? */
|
/* Does this MIPS32/MIPS64 CPU have a config2 register? */
|
||||||
|
|
|
@ -485,13 +485,11 @@ static void r4k_tlb_configure(void)
|
||||||
* Enable the no read, no exec bits, and enable large virtual
|
* Enable the no read, no exec bits, and enable large virtual
|
||||||
* address.
|
* address.
|
||||||
*/
|
*/
|
||||||
u32 pg = PG_RIE | PG_XIE;
|
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
pg |= PG_ELPA;
|
set_c0_pagegrain(PG_RIE | PG_XIE | PG_ELPA);
|
||||||
|
#else
|
||||||
|
set_c0_pagegrain(PG_RIE | PG_XIE);
|
||||||
#endif
|
#endif
|
||||||
if (cpu_has_rixiex)
|
|
||||||
pg |= PG_IEC;
|
|
||||||
write_c0_pagegrain(pg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_tlb_entry = current_cpu_data.tlbsize - 1;
|
temp_tlb_entry = current_cpu_data.tlbsize - 1;
|
||||||
|
|
|
@ -501,7 +501,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
|
||||||
case tlb_indexed: tlbw = uasm_i_tlbwi; break;
|
case tlb_indexed: tlbw = uasm_i_tlbwi; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu_has_mips_r2) {
|
if (cpu_has_mips_r2_exec_hazard) {
|
||||||
/*
|
/*
|
||||||
* The architecture spec says an ehb is required here,
|
* The architecture spec says an ehb is required here,
|
||||||
* but a number of cores do not have the hazard and
|
* but a number of cores do not have the hazard and
|
||||||
|
@ -514,6 +514,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
|
||||||
case CPU_PROAPTIV:
|
case CPU_PROAPTIV:
|
||||||
case CPU_P5600:
|
case CPU_P5600:
|
||||||
case CPU_M5150:
|
case CPU_M5150:
|
||||||
|
case CPU_QEMU_GENERIC:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1952,7 +1953,7 @@ static void build_r4000_tlb_load_handler(void)
|
||||||
|
|
||||||
switch (current_cpu_type()) {
|
switch (current_cpu_type()) {
|
||||||
default:
|
default:
|
||||||
if (cpu_has_mips_r2) {
|
if (cpu_has_mips_r2_exec_hazard) {
|
||||||
uasm_i_ehb(&p);
|
uasm_i_ehb(&p);
|
||||||
|
|
||||||
case CPU_CAVIUM_OCTEON:
|
case CPU_CAVIUM_OCTEON:
|
||||||
|
@ -2019,7 +2020,7 @@ static void build_r4000_tlb_load_handler(void)
|
||||||
|
|
||||||
switch (current_cpu_type()) {
|
switch (current_cpu_type()) {
|
||||||
default:
|
default:
|
||||||
if (cpu_has_mips_r2) {
|
if (cpu_has_mips_r2_exec_hazard) {
|
||||||
uasm_i_ehb(&p);
|
uasm_i_ehb(&p);
|
||||||
|
|
||||||
case CPU_CAVIUM_OCTEON:
|
case CPU_CAVIUM_OCTEON:
|
||||||
|
|
|
@ -38,14 +38,6 @@
|
||||||
| (e) << RE_SH \
|
| (e) << RE_SH \
|
||||||
| (f) << FUNC_SH)
|
| (f) << FUNC_SH)
|
||||||
|
|
||||||
/* Define these when we are not the ISA the kernel is being compiled with. */
|
|
||||||
#ifndef CONFIG_CPU_MICROMIPS
|
|
||||||
#define MM_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off)
|
|
||||||
#define MM_uasm_i_beqz(buf, rs, off) ISAOPC(_beq)(buf, rs, 0, off)
|
|
||||||
#define MM_uasm_i_beqzl(buf, rs, off) ISAOPC(_beql)(buf, rs, 0, off)
|
|
||||||
#define MM_uasm_i_bnez(buf, rs, off) ISAOPC(_bne)(buf, rs, 0, off)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "uasm.c"
|
#include "uasm.c"
|
||||||
|
|
||||||
static struct insn insn_table_MM[] = {
|
static struct insn insn_table_MM[] = {
|
||||||
|
|
|
@ -38,13 +38,13 @@
|
||||||
| (e) << RE_SH \
|
| (e) << RE_SH \
|
||||||
| (f) << FUNC_SH)
|
| (f) << FUNC_SH)
|
||||||
|
|
||||||
/* Define these when we are not the ISA the kernel is being compiled with. */
|
/* This macro sets the non-variable bits of an R6 instruction. */
|
||||||
#ifdef CONFIG_CPU_MICROMIPS
|
#define M6(a, b, c, d, e) \
|
||||||
#define CL_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off)
|
((a) << OP_SH \
|
||||||
#define CL_uasm_i_beqz(buf, rs, off) ISAOPC(_beq)(buf, rs, 0, off)
|
| (b) << RS_SH \
|
||||||
#define CL_uasm_i_beqzl(buf, rs, off) ISAOPC(_beql)(buf, rs, 0, off)
|
| (c) << RT_SH \
|
||||||
#define CL_uasm_i_bnez(buf, rs, off) ISAOPC(_bne)(buf, rs, 0, off)
|
| (d) << SIMM9_SH \
|
||||||
#endif
|
| (e) << FUNC_SH)
|
||||||
|
|
||||||
#include "uasm.c"
|
#include "uasm.c"
|
||||||
|
|
||||||
|
@ -62,7 +62,11 @@ static struct insn insn_table[] = {
|
||||||
{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
|
{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
|
||||||
{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
|
{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
|
||||||
{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
{ insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
|
#else
|
||||||
|
{ insn_cache, M6(cache_op, 0, 0, 0, cache6_op), RS | RT | SIMM9 },
|
||||||
|
#endif
|
||||||
{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
|
{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
|
||||||
{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
|
{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
|
||||||
|
@ -85,13 +89,22 @@ static struct insn insn_table[] = {
|
||||||
{ insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
|
{ insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
|
||||||
{ insn_jalr, M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD },
|
{ insn_jalr, M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD },
|
||||||
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
|
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
{ insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
|
{ insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
|
||||||
|
#else
|
||||||
|
{ insn_jr, M(spec_op, 0, 0, 0, 0, jalr_op), RS },
|
||||||
|
#endif
|
||||||
{ insn_lb, M(lb_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_lb, M(lb_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
{ insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
|
{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
|
||||||
{ insn_lh, M(lh_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_lh, M(lh_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
{ insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
{ insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
|
#else
|
||||||
|
{ insn_lld, M6(spec3_op, 0, 0, 0, lld6_op), RS | RT | SIMM9 },
|
||||||
|
{ insn_ll, M6(spec3_op, 0, 0, 0, ll6_op), RS | RT | SIMM9 },
|
||||||
|
#endif
|
||||||
{ insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
|
{ insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
|
||||||
{ insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
|
{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
|
||||||
|
@ -104,11 +117,20 @@ static struct insn insn_table[] = {
|
||||||
{ insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
|
{ insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD},
|
||||||
{ insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
|
{ insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
|
||||||
{ insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
|
{ insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
{ insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
|
#else
|
||||||
|
{ insn_pref, M6(spec3_op, 0, 0, 0, pref6_op), RS | RT | SIMM9 },
|
||||||
|
#endif
|
||||||
{ insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
|
{ insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
|
||||||
{ insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE },
|
{ insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE },
|
||||||
|
#ifndef CONFIG_CPU_MIPSR6
|
||||||
{ insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
{ insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
|
#else
|
||||||
|
{ insn_scd, M6(spec3_op, 0, 0, 0, scd6_op), RS | RT | SIMM9 },
|
||||||
|
{ insn_sc, M6(spec3_op, 0, 0, 0, sc6_op), RS | RT | SIMM9 },
|
||||||
|
#endif
|
||||||
{ insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
{ insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
||||||
{ insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
|
{ insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
|
||||||
{ insn_sllv, M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD },
|
{ insn_sllv, M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD },
|
||||||
|
@ -198,6 +220,8 @@ static void build_insn(u32 **buf, enum opcode opc, ...)
|
||||||
op |= build_set(va_arg(ap, u32));
|
op |= build_set(va_arg(ap, u32));
|
||||||
if (ip->fields & SCIMM)
|
if (ip->fields & SCIMM)
|
||||||
op |= build_scimm(va_arg(ap, u32));
|
op |= build_scimm(va_arg(ap, u32));
|
||||||
|
if (ip->fields & SIMM9)
|
||||||
|
op |= build_scimm9(va_arg(ap, u32));
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
**buf = op;
|
**buf = op;
|
||||||
|
|
|
@ -24,7 +24,8 @@ enum fields {
|
||||||
JIMM = 0x080,
|
JIMM = 0x080,
|
||||||
FUNC = 0x100,
|
FUNC = 0x100,
|
||||||
SET = 0x200,
|
SET = 0x200,
|
||||||
SCIMM = 0x400
|
SCIMM = 0x400,
|
||||||
|
SIMM9 = 0x800,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OP_MASK 0x3f
|
#define OP_MASK 0x3f
|
||||||
|
@ -41,6 +42,8 @@ enum fields {
|
||||||
#define FUNC_SH 0
|
#define FUNC_SH 0
|
||||||
#define SET_MASK 0x7
|
#define SET_MASK 0x7
|
||||||
#define SET_SH 0
|
#define SET_SH 0
|
||||||
|
#define SIMM9_SH 7
|
||||||
|
#define SIMM9_MASK 0x1ff
|
||||||
|
|
||||||
enum opcode {
|
enum opcode {
|
||||||
insn_invalid,
|
insn_invalid,
|
||||||
|
@ -116,6 +119,14 @@ static inline u32 build_scimm(u32 arg)
|
||||||
return (arg & SCIMM_MASK) << SCIMM_SH;
|
return (arg & SCIMM_MASK) << SCIMM_SH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32 build_scimm9(s32 arg)
|
||||||
|
{
|
||||||
|
WARN((arg > 0xff || arg < -0x100),
|
||||||
|
KERN_WARNING "Micro-assembler field overflow\n");
|
||||||
|
|
||||||
|
return (arg & SIMM9_MASK) << SIMM9_SH;
|
||||||
|
}
|
||||||
|
|
||||||
static inline u32 build_func(u32 arg)
|
static inline u32 build_func(u32 arg)
|
||||||
{
|
{
|
||||||
WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n");
|
WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n");
|
||||||
|
@ -330,7 +341,7 @@ I_u3u1u2(_ldx)
|
||||||
void ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b,
|
void ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b,
|
||||||
unsigned int c)
|
unsigned int c)
|
||||||
{
|
{
|
||||||
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5)
|
if (CAVIUM_OCTEON_DCACHE_PREFETCH_WAR && a <= 24 && a != 5)
|
||||||
/*
|
/*
|
||||||
* As per erratum Core-14449, replace prefetches 0-4,
|
* As per erratum Core-14449, replace prefetches 0-4,
|
||||||
* 6-24 with 'pref 28'.
|
* 6-24 with 'pref 28'.
|
||||||
|
|
|
@ -72,7 +72,7 @@ void read_persistent_clock(struct timespec *ts)
|
||||||
int get_c0_perfcount_int(void)
|
int get_c0_perfcount_int(void)
|
||||||
{
|
{
|
||||||
if (gic_present)
|
if (gic_present)
|
||||||
return gic_get_c0_compare_int();
|
return gic_get_c0_perfcount_int();
|
||||||
if (cp0_perfcount_irq >= 0)
|
if (cp0_perfcount_irq >= 0)
|
||||||
return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
|
return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue