mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'loongarch-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch updates from Huacai Chen: - Switch to relative exception tables - Add unaligned access support - Add alternative runtime patching mechanism - Add FDT booting support from efi system table - Add suspend/hibernation (ACPI S3/S4) support - Add basic STACKPROTECTOR support - Add ftrace (function tracer) support - Update the default config file * tag 'loongarch-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: (24 commits) LoongArch: Update Loongson-3 default config file LoongArch: modules/ftrace: Initialize PLT at load time LoongArch/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support LoongArch/ftrace: Add HAVE_DYNAMIC_FTRACE_WITH_ARGS support LoongArch/ftrace: Add HAVE_DYNAMIC_FTRACE_WITH_REGS support LoongArch/ftrace: Add dynamic function graph tracer support LoongArch/ftrace: Add dynamic function tracer support LoongArch/ftrace: Add recordmcount support LoongArch/ftrace: Add basic support LoongArch: module: Use got/plt section indices for relocations LoongArch: Add basic STACKPROTECTOR support LoongArch: Add hibernation (ACPI S4) support LoongArch: Add suspend (ACPI S3) support LoongArch: Add processing ISA Node in DeviceTree LoongArch: Add FDT booting support from efi system table LoongArch: Use alternative to optimize libraries LoongArch: Add alternative runtime patching mechanism LoongArch: Add unaligned access support LoongArch: BPF: Add BPF exception tables LoongArch: Remove the .fixup section usage ...
This commit is contained in:
@@ -436,8 +436,8 @@ ignore-unaligned-usertrap
|
||||
|
||||
On architectures where unaligned accesses cause traps, and where this
|
||||
feature is supported (``CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN``;
|
||||
currently, ``arc`` and ``ia64``), controls whether all unaligned traps
|
||||
are logged.
|
||||
currently, ``arc``, ``ia64`` and ``loongarch``), controls whether all
|
||||
unaligned traps are logged.
|
||||
|
||||
= =============================================================
|
||||
0 Log all unaligned accesses.
|
||||
@@ -1492,8 +1492,8 @@ unaligned-trap
|
||||
|
||||
On architectures where unaligned accesses cause traps, and where this
|
||||
feature is supported (``CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW``; currently,
|
||||
``arc`` and ``parisc``), controls whether unaligned traps are caught
|
||||
and emulated (instead of failing).
|
||||
``arc``, ``parisc`` and ``loongarch``), controls whether unaligned traps
|
||||
are caught and emulated (instead of failing).
|
||||
|
||||
= ========================================================
|
||||
0 Do not emulate unaligned accesses.
|
||||
|
||||
@@ -58,6 +58,7 @@ config LOONGARCH
|
||||
select ARCH_WANTS_NO_INSTR
|
||||
select BUILDTIME_TABLE_SORT
|
||||
select COMMON_CLK
|
||||
select CPU_PM
|
||||
select EFI
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_CMOS_UPDATE
|
||||
@@ -86,11 +87,18 @@ config LOONGARCH
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select HAVE_ASM_MODVERSIONS
|
||||
select HAVE_CONTEXT_TRACKING_USER
|
||||
select HAVE_C_RECORDMCOUNT
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
select HAVE_DMA_CONTIGUOUS
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_ARGS
|
||||
select HAVE_DYNAMIC_FTRACE_WITH_REGS
|
||||
select HAVE_EBPF_JIT
|
||||
select HAVE_EXIT_THREAD
|
||||
select HAVE_FAST_GUP
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_GENERIC_VDSO
|
||||
select HAVE_IOREMAP_PROT
|
||||
select HAVE_IRQ_EXIT_ON_IRQ_STACK
|
||||
@@ -104,6 +112,7 @@ config LOONGARCH
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_RSEQ
|
||||
select HAVE_SETUP_PER_CPU_AREA if NUMA
|
||||
select HAVE_STACKPROTECTOR
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select HAVE_TIF_NOHZ
|
||||
select HAVE_VIRT_CPU_ACCOUNTING_GEN if !SMP
|
||||
@@ -113,6 +122,8 @@ config LOONGARCH
|
||||
select MODULES_USE_ELF_RELA if MODULES
|
||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
select NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
select OF
|
||||
select OF_EARLY_FLATTREE
|
||||
select PCI
|
||||
select PCI_DOMAINS_GENERIC
|
||||
select PCI_ECAM if ACPI
|
||||
@@ -123,6 +134,8 @@ config LOONGARCH
|
||||
select RTC_LIB
|
||||
select SMP
|
||||
select SPARSE_IRQ
|
||||
select SYSCTL_ARCH_UNALIGN_ALLOW
|
||||
select SYSCTL_ARCH_UNALIGN_NO_WARN
|
||||
select SYSCTL_EXCEPTION_TRACE
|
||||
select SWIOTLB
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
@@ -516,6 +529,13 @@ config ARCH_MMAP_RND_BITS_MAX
|
||||
|
||||
menu "Power management options"
|
||||
|
||||
config ARCH_SUSPEND_POSSIBLE
|
||||
def_bool y
|
||||
|
||||
config ARCH_HIBERNATION_POSSIBLE
|
||||
def_bool y
|
||||
|
||||
source "kernel/power/Kconfig"
|
||||
source "drivers/acpi/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -25,6 +25,11 @@ endif
|
||||
32bit-emul = elf32loongarch
|
||||
64bit-emul = elf64loongarch
|
||||
|
||||
ifdef CONFIG_DYNAMIC_FTRACE
|
||||
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
|
||||
CC_FLAGS_FTRACE := -fpatchable-function-entry=2
|
||||
endif
|
||||
|
||||
ifdef CONFIG_64BIT
|
||||
tool-archpref = $(64bit-tool-archpref)
|
||||
UTS_MACHINE := loongarch64
|
||||
@@ -104,6 +109,9 @@ endif
|
||||
libs-y += arch/loongarch/lib/
|
||||
libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
|
||||
|
||||
# suspend and hibernation support
|
||||
drivers-$(CONFIG_PM) += arch/loongarch/power/
|
||||
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
prepare: vdso_prepare
|
||||
vdso_prepare: prepare0
|
||||
|
||||
@@ -34,12 +34,13 @@ CONFIG_SYSFS_DEPRECATED=y
|
||||
CONFIG_RELAY=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_EXPERT=y
|
||||
CONFIG_USERFAULTFD=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_PERF_EVENTS=y
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_LOONGARCH=y
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_MACH_LOONGSON64=y
|
||||
CONFIG_PAGE_SIZE_16KB=y
|
||||
CONFIG_HZ_250=y
|
||||
CONFIG_DMI=y
|
||||
CONFIG_EFI=y
|
||||
CONFIG_SMP=y
|
||||
@@ -47,14 +48,14 @@ CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_NR_CPUS=64
|
||||
CONFIG_NUMA=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_PAGE_SIZE_16KB=y
|
||||
CONFIG_HZ_250=y
|
||||
CONFIG_SUSPEND=y
|
||||
CONFIG_HIBERNATION=y
|
||||
CONFIG_ACPI=y
|
||||
CONFIG_ACPI_SPCR_TABLE=y
|
||||
CONFIG_ACPI_HOTPLUG_CPU=y
|
||||
CONFIG_ACPI_TAD=y
|
||||
CONFIG_ACPI_DOCK=y
|
||||
CONFIG_ACPI_IPMI=m
|
||||
CONFIG_ACPI_HOTPLUG_CPU=y
|
||||
CONFIG_ACPI_PCI_SLOT=y
|
||||
CONFIG_ACPI_HOTPLUG_MEMORY=y
|
||||
CONFIG_EFI_ZBOOT=y
|
||||
@@ -73,17 +74,19 @@ CONFIG_UNIXWARE_DISKLABEL=y
|
||||
CONFIG_IOSCHED_BFQ=y
|
||||
CONFIG_BFQ_GROUP_IOSCHED=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_ZPOOL=y
|
||||
CONFIG_ZSWAP=y
|
||||
CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y
|
||||
CONFIG_ZBUD=y
|
||||
CONFIG_Z3FOLD=y
|
||||
CONFIG_ZSMALLOC=m
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_ZSWAP=y
|
||||
CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y
|
||||
CONFIG_ZPOOL=y
|
||||
CONFIG_ZBUD=y
|
||||
CONFIG_Z3FOLD=y
|
||||
CONFIG_ZSMALLOC=m
|
||||
CONFIG_USERFAULTFD=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
@@ -118,7 +121,6 @@ CONFIG_NETFILTER=y
|
||||
CONFIG_BRIDGE_NETFILTER=m
|
||||
CONFIG_NETFILTER_NETLINK_LOG=m
|
||||
CONFIG_NF_CONNTRACK=m
|
||||
CONFIG_NF_LOG_NETDEV=m
|
||||
CONFIG_NF_CONNTRACK_AMANDA=m
|
||||
CONFIG_NF_CONNTRACK_FTP=m
|
||||
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
|
||||
@@ -416,6 +418,7 @@ CONFIG_SCSI_VIRTIO=m
|
||||
CONFIG_ATA=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
CONFIG_SATA_AHCI_PLATFORM=y
|
||||
CONFIG_AHCI_DWC=y
|
||||
CONFIG_PATA_ATIIXP=y
|
||||
CONFIG_PATA_PCMCIA=m
|
||||
CONFIG_MD=y
|
||||
@@ -469,13 +472,11 @@ CONFIG_VIRTIO_NET=m
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||
CONFIG_BNX2=y
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_CAVIUM is not set
|
||||
CONFIG_CHELSIO_T1=m
|
||||
CONFIG_CHELSIO_T1_1G=y
|
||||
CONFIG_CHELSIO_T3=m
|
||||
CONFIG_CHELSIO_T4=m
|
||||
# CONFIG_NET_VENDOR_CIRRUS is not set
|
||||
# CONFIG_NET_VENDOR_CISCO is not set
|
||||
# CONFIG_NET_VENDOR_DEC is not set
|
||||
# CONFIG_NET_VENDOR_DLINK is not set
|
||||
@@ -496,6 +497,7 @@ CONFIG_IXGBE=y
|
||||
# CONFIG_NET_VENDOR_NVIDIA is not set
|
||||
# CONFIG_NET_VENDOR_OKI is not set
|
||||
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||
# CONFIG_NET_VENDOR_QUALCOMM is not set
|
||||
# CONFIG_NET_VENDOR_RDC is not set
|
||||
CONFIG_8139CP=m
|
||||
@@ -505,9 +507,9 @@ CONFIG_R8169=y
|
||||
# CONFIG_NET_VENDOR_ROCKER is not set
|
||||
# CONFIG_NET_VENDOR_SAMSUNG is not set
|
||||
# CONFIG_NET_VENDOR_SEEQ is not set
|
||||
# CONFIG_NET_VENDOR_SOLARFLARE is not set
|
||||
# CONFIG_NET_VENDOR_SILAN is not set
|
||||
# CONFIG_NET_VENDOR_SIS is not set
|
||||
# CONFIG_NET_VENDOR_SOLARFLARE is not set
|
||||
# CONFIG_NET_VENDOR_SMSC is not set
|
||||
CONFIG_STMMAC_ETH=y
|
||||
# CONFIG_NET_VENDOR_SUN is not set
|
||||
@@ -588,6 +590,7 @@ CONFIG_SERIAL_8250_EXTENDED=y
|
||||
CONFIG_SERIAL_8250_MANY_PORTS=y
|
||||
CONFIG_SERIAL_8250_SHARE_IRQ=y
|
||||
CONFIG_SERIAL_8250_RSA=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
CONFIG_SERIAL_NONSTANDARD=y
|
||||
CONFIG_PRINTER=m
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
@@ -602,6 +605,11 @@ CONFIG_I2C_GPIO=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_GPIO_LOONGSON=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_RESET_RESTART=y
|
||||
CONFIG_POWER_RESET_SYSCON=y
|
||||
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
|
||||
CONFIG_SYSCON_REBOOT_MODE=y
|
||||
CONFIG_SENSORS_LM75=m
|
||||
CONFIG_SENSORS_LM93=m
|
||||
CONFIG_SENSORS_W83795=m
|
||||
@@ -609,16 +617,16 @@ CONFIG_SENSORS_W83627HF=m
|
||||
CONFIG_RC_CORE=m
|
||||
CONFIG_LIRC=y
|
||||
CONFIG_RC_DECODERS=y
|
||||
CONFIG_IR_IMON_DECODER=m
|
||||
CONFIG_IR_JVC_DECODER=m
|
||||
CONFIG_IR_MCE_KBD_DECODER=m
|
||||
CONFIG_IR_NEC_DECODER=m
|
||||
CONFIG_IR_RC5_DECODER=m
|
||||
CONFIG_IR_RC6_DECODER=m
|
||||
CONFIG_IR_JVC_DECODER=m
|
||||
CONFIG_IR_SONY_DECODER=m
|
||||
CONFIG_IR_SANYO_DECODER=m
|
||||
CONFIG_IR_SHARP_DECODER=m
|
||||
CONFIG_IR_MCE_KBD_DECODER=m
|
||||
CONFIG_IR_SONY_DECODER=m
|
||||
CONFIG_IR_XMP_DECODER=m
|
||||
CONFIG_IR_IMON_DECODER=m
|
||||
CONFIG_MEDIA_SUPPORT=m
|
||||
CONFIG_MEDIA_USB_SUPPORT=y
|
||||
CONFIG_USB_VIDEO_CLASS=m
|
||||
@@ -638,6 +646,7 @@ CONFIG_DRM_VIRTIO_GPU=m
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_EFI=y
|
||||
CONFIG_FB_RADEON=y
|
||||
CONFIG_LCD_CLASS_DEVICE=y
|
||||
CONFIG_LCD_PLATFORM=m
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
@@ -647,7 +656,6 @@ CONFIG_SOUND=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_SND_SEQUENCER=m
|
||||
CONFIG_SND_SEQ_DUMMY=m
|
||||
# CONFIG_SND_ISA is not set
|
||||
CONFIG_SND_BT87X=m
|
||||
CONFIG_SND_BT87X_OVERCLOCK=y
|
||||
CONFIG_SND_HDA_INTEL=y
|
||||
@@ -818,10 +826,6 @@ CONFIG_CRYPTO_USER=m
|
||||
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
||||
CONFIG_CRYPTO_PCRYPT=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_CHACHA20POLY1305=m
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPTO_VMAC=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_ANUBIS=m
|
||||
CONFIG_CRYPTO_BLOWFISH=m
|
||||
CONFIG_CRYPTO_CAST5=m
|
||||
@@ -831,6 +835,9 @@ CONFIG_CRYPTO_SEED=m
|
||||
CONFIG_CRYPTO_SERPENT=m
|
||||
CONFIG_CRYPTO_TEA=m
|
||||
CONFIG_CRYPTO_TWOFISH=m
|
||||
CONFIG_CRYPTO_CHACHA20POLY1305=m
|
||||
CONFIG_CRYPTO_VMAC=m
|
||||
CONFIG_CRYPTO_WP512=m
|
||||
CONFIG_CRYPTO_DEFLATE=m
|
||||
CONFIG_CRYPTO_LZO=m
|
||||
CONFIG_CRYPTO_842=m
|
||||
@@ -844,6 +851,7 @@ CONFIG_CRYPTO_DEV_VIRTIO=m
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_STRIP_ASM_SYMS=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_SCHEDSTATS=y
|
||||
# CONFIG_DEBUG_PREEMPT is not set
|
||||
|
||||
@@ -35,4 +35,14 @@ extern struct list_head acpi_wakeup_device_list;
|
||||
|
||||
#define ACPI_TABLE_UPGRADE_MAX_PHYS ARCH_LOW_ADDRESS_LIMIT
|
||||
|
||||
extern int loongarch_acpi_suspend(void);
|
||||
extern int (*acpi_suspend_lowlevel)(void);
|
||||
extern void loongarch_suspend_enter(void);
|
||||
|
||||
static inline unsigned long acpi_get_wakeup_address(void)
|
||||
{
|
||||
extern void loongarch_wakeup_start(void);
|
||||
return (unsigned long)loongarch_wakeup_start;
|
||||
}
|
||||
|
||||
#endif /* _ASM_LOONGARCH_ACPI_H */
|
||||
|
||||
82
arch/loongarch/include/asm/alternative-asm.h
Normal file
82
arch/loongarch/include/asm/alternative-asm.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_ALTERNATIVE_ASM_H
|
||||
#define _ASM_ALTERNATIVE_ASM_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#include <asm/asm.h>
|
||||
|
||||
/*
|
||||
* Issue one struct alt_instr descriptor entry (need to put it into
|
||||
* the section .altinstructions, see below). This entry contains
|
||||
* enough information for the alternatives patching code to patch an
|
||||
* instruction. See apply_alternatives().
|
||||
*/
|
||||
.macro altinstruction_entry orig alt feature orig_len alt_len
|
||||
.long \orig - .
|
||||
.long \alt - .
|
||||
.short \feature
|
||||
.byte \orig_len
|
||||
.byte \alt_len
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Define an alternative between two instructions. If @feature is
|
||||
* present, early code in apply_alternatives() replaces @oldinstr with
|
||||
* @newinstr. ".fill" directive takes care of proper instruction padding
|
||||
* in case @newinstr is longer than @oldinstr.
|
||||
*/
|
||||
.macro ALTERNATIVE oldinstr, newinstr, feature
|
||||
140 :
|
||||
\oldinstr
|
||||
141 :
|
||||
.fill - (((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)) / 4, 4, 0x03400000
|
||||
142 :
|
||||
|
||||
.pushsection .altinstructions, "a"
|
||||
altinstruction_entry 140b, 143f, \feature, 142b-140b, 144f-143f
|
||||
.popsection
|
||||
|
||||
.subsection 1
|
||||
143 :
|
||||
\newinstr
|
||||
144 :
|
||||
.previous
|
||||
.endm
|
||||
|
||||
#define old_len (141b-140b)
|
||||
#define new_len1 (144f-143f)
|
||||
#define new_len2 (145f-144f)
|
||||
|
||||
#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
|
||||
|
||||
/*
|
||||
* Same as ALTERNATIVE macro above but for two alternatives. If CPU
|
||||
* has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
|
||||
* @feature2, it replaces @oldinstr with @feature2.
|
||||
*/
|
||||
.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
|
||||
140 :
|
||||
\oldinstr
|
||||
141 :
|
||||
.fill - ((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \
|
||||
(alt_max_short(new_len1, new_len2) - (old_len)) / 4, 4, 0x03400000
|
||||
142 :
|
||||
|
||||
.pushsection .altinstructions, "a"
|
||||
altinstruction_entry 140b, 143f, \feature1, 142b-140b, 144f-143f, 142b-141b
|
||||
altinstruction_entry 140b, 144f, \feature2, 142b-140b, 145f-144f, 142b-141b
|
||||
.popsection
|
||||
|
||||
.subsection 1
|
||||
143 :
|
||||
\newinstr1
|
||||
144 :
|
||||
\newinstr2
|
||||
145 :
|
||||
.previous
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_ALTERNATIVE_ASM_H */
|
||||
111
arch/loongarch/include/asm/alternative.h
Normal file
111
arch/loongarch/include/asm/alternative.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_ALTERNATIVE_H
|
||||
#define _ASM_ALTERNATIVE_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
struct alt_instr {
|
||||
s32 instr_offset; /* offset to original instruction */
|
||||
s32 replace_offset; /* offset to replacement instruction */
|
||||
u16 feature; /* feature bit set for replacement */
|
||||
u8 instrlen; /* length of original instruction */
|
||||
u8 replacementlen; /* length of new instruction */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Debug flag that can be tested to see whether alternative
|
||||
* instructions were patched in already:
|
||||
*/
|
||||
extern int alternatives_patched;
|
||||
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
||||
|
||||
extern void alternative_instructions(void);
|
||||
extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
|
||||
#define b_replacement(num) "664"#num
|
||||
#define e_replacement(num) "665"#num
|
||||
|
||||
#define alt_end_marker "663"
|
||||
#define alt_slen "662b-661b"
|
||||
#define alt_total_slen alt_end_marker"b-661b"
|
||||
#define alt_rlen(num) e_replacement(num)"f-"b_replacement(num)"f"
|
||||
|
||||
#define __OLDINSTR(oldinstr, num) \
|
||||
"661:\n\t" oldinstr "\n662:\n" \
|
||||
".fill -(((" alt_rlen(num) ")-(" alt_slen ")) > 0) * " \
|
||||
"((" alt_rlen(num) ")-(" alt_slen ")) / 4, 4, 0x03400000\n"
|
||||
|
||||
#define OLDINSTR(oldinstr, num) \
|
||||
__OLDINSTR(oldinstr, num) \
|
||||
alt_end_marker ":\n"
|
||||
|
||||
#define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") < (" b ")))))"
|
||||
|
||||
/*
|
||||
* Pad the second replacement alternative with additional NOPs if it is
|
||||
* additionally longer than the first replacement alternative.
|
||||
*/
|
||||
#define OLDINSTR_2(oldinstr, num1, num2) \
|
||||
"661:\n\t" oldinstr "\n662:\n" \
|
||||
".fill -((" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) > 0) * " \
|
||||
"(" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) / 4, " \
|
||||
"4, 0x03400000\n" \
|
||||
alt_end_marker ":\n"
|
||||
|
||||
#define ALTINSTR_ENTRY(feature, num) \
|
||||
" .long 661b - .\n" /* label */ \
|
||||
" .long " b_replacement(num)"f - .\n" /* new instruction */ \
|
||||
" .short " __stringify(feature) "\n" /* feature bit */ \
|
||||
" .byte " alt_total_slen "\n" /* source len */ \
|
||||
" .byte " alt_rlen(num) "\n" /* replacement len */
|
||||
|
||||
#define ALTINSTR_REPLACEMENT(newinstr, feature, num) /* replacement */ \
|
||||
b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n\t"
|
||||
|
||||
/* alternative assembly primitive: */
|
||||
#define ALTERNATIVE(oldinstr, newinstr, feature) \
|
||||
OLDINSTR(oldinstr, 1) \
|
||||
".pushsection .altinstructions,\"a\"\n" \
|
||||
ALTINSTR_ENTRY(feature, 1) \
|
||||
".popsection\n" \
|
||||
".subsection 1\n" \
|
||||
ALTINSTR_REPLACEMENT(newinstr, feature, 1) \
|
||||
".previous\n"
|
||||
|
||||
#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\
|
||||
OLDINSTR_2(oldinstr, 1, 2) \
|
||||
".pushsection .altinstructions,\"a\"\n" \
|
||||
ALTINSTR_ENTRY(feature1, 1) \
|
||||
ALTINSTR_ENTRY(feature2, 2) \
|
||||
".popsection\n" \
|
||||
".subsection 1\n" \
|
||||
ALTINSTR_REPLACEMENT(newinstr1, feature1, 1) \
|
||||
ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \
|
||||
".previous\n"
|
||||
|
||||
/*
|
||||
* Alternative instructions for different CPU types or capabilities.
|
||||
*
|
||||
* This allows to use optimized instructions even on generic binary
|
||||
* kernels.
|
||||
*
|
||||
* length of oldinstr must be longer or equal the length of newinstr
|
||||
* It can be padded with nops as needed.
|
||||
*
|
||||
* For non barrier like inlines please define new variants
|
||||
* without volatile and memory clobber.
|
||||
*/
|
||||
#define alternative(oldinstr, newinstr, feature) \
|
||||
(asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory"))
|
||||
|
||||
#define alternative_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
|
||||
(asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory"))
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_ALTERNATIVE_H */
|
||||
65
arch/loongarch/include/asm/asm-extable.h
Normal file
65
arch/loongarch/include/asm/asm-extable.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __ASM_ASM_EXTABLE_H
|
||||
#define __ASM_ASM_EXTABLE_H
|
||||
|
||||
#define EX_TYPE_NONE 0
|
||||
#define EX_TYPE_FIXUP 1
|
||||
#define EX_TYPE_UACCESS_ERR_ZERO 2
|
||||
#define EX_TYPE_BPF 3
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
|
||||
.pushsection __ex_table, "a"; \
|
||||
.balign 4; \
|
||||
.long ((insn) - .); \
|
||||
.long ((fixup) - .); \
|
||||
.short (type); \
|
||||
.short (data); \
|
||||
.popsection;
|
||||
|
||||
.macro _asm_extable, insn, fixup
|
||||
__ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_FIXUP, 0)
|
||||
.endm
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/gpr-num.h>
|
||||
|
||||
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
|
||||
".pushsection __ex_table, \"a\"\n" \
|
||||
".balign 4\n" \
|
||||
".long ((" insn ") - .)\n" \
|
||||
".long ((" fixup ") - .)\n" \
|
||||
".short (" type ")\n" \
|
||||
".short (" data ")\n" \
|
||||
".popsection\n"
|
||||
|
||||
#define _ASM_EXTABLE(insn, fixup) \
|
||||
__ASM_EXTABLE_RAW(#insn, #fixup, __stringify(EX_TYPE_FIXUP), "0")
|
||||
|
||||
#define EX_DATA_REG_ERR_SHIFT 0
|
||||
#define EX_DATA_REG_ERR GENMASK(4, 0)
|
||||
#define EX_DATA_REG_ZERO_SHIFT 5
|
||||
#define EX_DATA_REG_ZERO GENMASK(9, 5)
|
||||
|
||||
#define EX_DATA_REG(reg, gpr) \
|
||||
"((.L__gpr_num_" #gpr ") << " __stringify(EX_DATA_REG_##reg##_SHIFT) ")"
|
||||
|
||||
#define _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) \
|
||||
__DEFINE_ASM_GPR_NUMS \
|
||||
__ASM_EXTABLE_RAW(#insn, #fixup, \
|
||||
__stringify(EX_TYPE_UACCESS_ERR_ZERO), \
|
||||
"(" \
|
||||
EX_DATA_REG(ERR, err) " | " \
|
||||
EX_DATA_REG(ZERO, zero) \
|
||||
")")
|
||||
|
||||
#define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \
|
||||
_ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_ASM_EXTABLE_H */
|
||||
@@ -32,6 +32,7 @@ struct loongson_system_configuration {
|
||||
int cores_per_node;
|
||||
int cores_per_package;
|
||||
unsigned long cores_io_master;
|
||||
unsigned long suspend_addr;
|
||||
const char *cpuname;
|
||||
};
|
||||
|
||||
|
||||
15
arch/loongarch/include/asm/bugs.h
Normal file
15
arch/loongarch/include/asm/bugs.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* This is included by init/main.c to check for architecture-dependent bugs.
|
||||
*
|
||||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#ifndef _ASM_BUGS_H
|
||||
#define _ASM_BUGS_H
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpu-info.h>
|
||||
|
||||
extern void check_bugs(void);
|
||||
|
||||
#endif /* _ASM_BUGS_H */
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
void __init efi_init(void);
|
||||
void __init efi_runtime_init(void);
|
||||
void __init *efi_fdt_pointer(void);
|
||||
void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
|
||||
|
||||
#define ARCH_EFI_IRQ_FLAGS_MASK 0x00000004 /* Bit 2: CSR.CRMD.IE */
|
||||
|
||||
47
arch/loongarch/include/asm/extable.h
Normal file
47
arch/loongarch/include/asm/extable.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_LOONGARCH_EXTABLE_H
|
||||
#define _ASM_LOONGARCH_EXTABLE_H
|
||||
|
||||
/*
|
||||
* The exception table consists of pairs of relative offsets: the first
|
||||
* is the relative offset to an instruction that is allowed to fault,
|
||||
* and the second is the relative offset at which the program should
|
||||
* continue. No registers are modified, so it is entirely up to the
|
||||
* continuation code to figure out what to do.
|
||||
*
|
||||
* All the routines below use bits of fixup code that are out of line
|
||||
* with the main instruction path. This means when everything is well,
|
||||
* we don't even have to jump over them. Further, they do not intrude
|
||||
* on our cache or tlb entries.
|
||||
*/
|
||||
|
||||
struct exception_table_entry {
|
||||
int insn, fixup;
|
||||
short type, data;
|
||||
};
|
||||
|
||||
#define ARCH_HAS_RELATIVE_EXTABLE
|
||||
|
||||
#define swap_ex_entry_fixup(a, b, tmp, delta) \
|
||||
do { \
|
||||
(a)->fixup = (b)->fixup + (delta); \
|
||||
(b)->fixup = (tmp).fixup - (delta); \
|
||||
(a)->type = (b)->type; \
|
||||
(b)->type = (tmp).type; \
|
||||
(a)->data = (b)->data; \
|
||||
(b)->data = (tmp).data; \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_BPF_JIT
|
||||
bool ex_handler_bpf(const struct exception_table_entry *ex, struct pt_regs *regs);
|
||||
#else
|
||||
static inline
|
||||
bool ex_handler_bpf(const struct exception_table_entry *ex, struct pt_regs *regs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* !CONFIG_BPF_JIT */
|
||||
|
||||
bool fixup_exception(struct pt_regs *regs);
|
||||
|
||||
#endif
|
||||
68
arch/loongarch/include/asm/ftrace.h
Normal file
68
arch/loongarch/include/asm/ftrace.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef _ASM_LOONGARCH_FTRACE_H
|
||||
#define _ASM_LOONGARCH_FTRACE_H
|
||||
|
||||
#define FTRACE_PLT_IDX 0
|
||||
#define FTRACE_REGS_PLT_IDX 1
|
||||
#define NR_FTRACE_PLTS 2
|
||||
|
||||
#define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_regs, regs[1]))
|
||||
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
|
||||
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifndef CONFIG_DYNAMIC_FTRACE
|
||||
|
||||
#define mcount _mcount
|
||||
extern void _mcount(void);
|
||||
extern void prepare_ftrace_return(unsigned long self_addr, unsigned long callsite_sp, unsigned long old);
|
||||
|
||||
#else
|
||||
|
||||
struct dyn_ftrace;
|
||||
struct dyn_arch_ftrace { };
|
||||
|
||||
#define ARCH_SUPPORTS_FTRACE_OPS 1
|
||||
#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
|
||||
|
||||
#define ftrace_init_nop ftrace_init_nop
|
||||
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
|
||||
|
||||
static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent);
|
||||
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
|
||||
struct ftrace_ops;
|
||||
|
||||
struct ftrace_regs {
|
||||
struct pt_regs regs;
|
||||
};
|
||||
|
||||
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
|
||||
{
|
||||
return &fregs->regs;
|
||||
}
|
||||
|
||||
#define ftrace_graph_func ftrace_graph_func
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs);
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* CONFIG_FUNCTION_TRACER */
|
||||
|
||||
#endif /* _ASM_LOONGARCH_FTRACE_H */
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/asm-extable.h>
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
@@ -18,18 +19,11 @@
|
||||
"2: sc.w $t0, %2 \n" \
|
||||
" beqz $t0, 1b \n" \
|
||||
"3: \n" \
|
||||
" .section .fixup,\"ax\" \n" \
|
||||
"4: li.w %0, %6 \n" \
|
||||
" b 3b \n" \
|
||||
" .previous \n" \
|
||||
" .section __ex_table,\"a\" \n" \
|
||||
" "__UA_ADDR "\t1b, 4b \n" \
|
||||
" "__UA_ADDR "\t2b, 4b \n" \
|
||||
" .previous \n" \
|
||||
_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0) \
|
||||
_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0) \
|
||||
: "=r" (ret), "=&r" (oldval), \
|
||||
"=ZC" (*uaddr) \
|
||||
: "0" (0), "ZC" (*uaddr), "Jr" (oparg), \
|
||||
"i" (-EFAULT) \
|
||||
: "0" (0), "ZC" (*uaddr), "Jr" (oparg) \
|
||||
: "memory", "t0"); \
|
||||
}
|
||||
|
||||
@@ -86,17 +80,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, u32 newv
|
||||
" beqz $t0, 1b \n"
|
||||
"3: \n"
|
||||
__WEAK_LLSC_MB
|
||||
" .section .fixup,\"ax\" \n"
|
||||
"4: li.d %0, %6 \n"
|
||||
" b 3b \n"
|
||||
" .previous \n"
|
||||
" .section __ex_table,\"a\" \n"
|
||||
" "__UA_ADDR "\t1b, 4b \n"
|
||||
" "__UA_ADDR "\t2b, 4b \n"
|
||||
" .previous \n"
|
||||
_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0)
|
||||
_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0)
|
||||
: "+r" (ret), "=&r" (val), "=ZC" (*uaddr)
|
||||
: "ZC" (*uaddr), "Jr" (oldval), "Jr" (newval),
|
||||
"i" (-EFAULT)
|
||||
: "ZC" (*uaddr), "Jr" (oldval), "Jr" (newval)
|
||||
: "memory", "t0");
|
||||
|
||||
*uval = val;
|
||||
|
||||
22
arch/loongarch/include/asm/gpr-num.h
Normal file
22
arch/loongarch/include/asm/gpr-num.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __ASM_GPR_NUM_H
|
||||
#define __ASM_GPR_NUM_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
.equ .L__gpr_num_zero, 0
|
||||
.irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
|
||||
.equ .L__gpr_num_$r\num, \num
|
||||
.endr
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#define __DEFINE_ASM_GPR_NUMS \
|
||||
" .equ .L__gpr_num_zero, 0\n" \
|
||||
" .irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31\n" \
|
||||
" .equ .L__gpr_num_$r\\num, \\num\n" \
|
||||
" .endr\n" \
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_GPR_NUM_H */
|
||||
@@ -8,14 +8,17 @@
|
||||
#include <linux/types.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
#define INSN_NOP 0x03400000
|
||||
#define INSN_BREAK 0x002a0000
|
||||
|
||||
#define ADDR_IMMMASK_LU52ID 0xFFF0000000000000
|
||||
#define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000
|
||||
#define ADDR_IMMMASK_LU12IW 0x00000000FFFFF000
|
||||
#define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000
|
||||
|
||||
#define ADDR_IMMSHIFT_LU52ID 52
|
||||
#define ADDR_IMMSHIFT_LU32ID 32
|
||||
#define ADDR_IMMSHIFT_LU12IW 12
|
||||
#define ADDR_IMMSHIFT_ADDU16ID 16
|
||||
|
||||
#define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN)
|
||||
@@ -28,6 +31,7 @@ enum reg0i26_op {
|
||||
enum reg1i20_op {
|
||||
lu12iw_op = 0x0a,
|
||||
lu32id_op = 0x0b,
|
||||
pcaddi_op = 0x0c,
|
||||
pcaddu12i_op = 0x0e,
|
||||
pcaddu18i_op = 0x0f,
|
||||
};
|
||||
@@ -35,6 +39,8 @@ enum reg1i20_op {
|
||||
enum reg1i21_op {
|
||||
beqz_op = 0x10,
|
||||
bnez_op = 0x11,
|
||||
bceqz_op = 0x12, /* bits[9:8] = 0x00 */
|
||||
bcnez_op = 0x12, /* bits[9:8] = 0x01 */
|
||||
};
|
||||
|
||||
enum reg2_op {
|
||||
@@ -76,6 +82,10 @@ enum reg2i12_op {
|
||||
ldbu_op = 0xa8,
|
||||
ldhu_op = 0xa9,
|
||||
ldwu_op = 0xaa,
|
||||
flds_op = 0xac,
|
||||
fsts_op = 0xad,
|
||||
fldd_op = 0xae,
|
||||
fstd_op = 0xaf,
|
||||
};
|
||||
|
||||
enum reg2i14_op {
|
||||
@@ -146,6 +156,10 @@ enum reg3_op {
|
||||
ldxbu_op = 0x7040,
|
||||
ldxhu_op = 0x7048,
|
||||
ldxwu_op = 0x7050,
|
||||
fldxs_op = 0x7060,
|
||||
fldxd_op = 0x7068,
|
||||
fstxs_op = 0x7070,
|
||||
fstxd_op = 0x7078,
|
||||
amswapw_op = 0x70c0,
|
||||
amswapd_op = 0x70c1,
|
||||
amaddw_op = 0x70c2,
|
||||
@@ -307,6 +321,12 @@ static inline bool is_imm_negative(unsigned long val, unsigned int bit)
|
||||
return val & (1UL << (bit - 1));
|
||||
}
|
||||
|
||||
static inline bool is_pc_ins(union loongarch_instruction *ip)
|
||||
{
|
||||
return ip->reg1i20_format.opcode >= pcaddi_op &&
|
||||
ip->reg1i20_format.opcode <= pcaddu18i_op;
|
||||
}
|
||||
|
||||
static inline bool is_branch_ins(union loongarch_instruction *ip)
|
||||
{
|
||||
return ip->reg1i21_format.opcode >= beqz_op &&
|
||||
@@ -331,6 +351,18 @@ static inline bool is_stack_alloc_ins(union loongarch_instruction *ip)
|
||||
is_imm12_negative(ip->reg2i12_format.immediate);
|
||||
}
|
||||
|
||||
int larch_insn_read(void *addr, u32 *insnp);
|
||||
int larch_insn_write(void *addr, u32 insn);
|
||||
int larch_insn_patch_text(void *addr, u32 insn);
|
||||
|
||||
u32 larch_insn_gen_nop(void);
|
||||
u32 larch_insn_gen_b(unsigned long pc, unsigned long dest);
|
||||
u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest);
|
||||
|
||||
u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk);
|
||||
u32 larch_insn_gen_move(enum loongarch_gpr rd, enum loongarch_gpr rj);
|
||||
|
||||
u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm);
|
||||
u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm);
|
||||
u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
|
||||
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest);
|
||||
@@ -345,6 +377,14 @@ static inline bool unsigned_imm_check(unsigned long val, unsigned int bit)
|
||||
return val < (1UL << bit);
|
||||
}
|
||||
|
||||
static inline unsigned long sign_extend(unsigned long val, unsigned int idx)
|
||||
{
|
||||
if (!is_imm_negative(val, idx + 1))
|
||||
return ((1UL << idx) - 1) & val;
|
||||
else
|
||||
return ~((1UL << idx) - 1) | val;
|
||||
}
|
||||
|
||||
#define DEF_EMIT_REG0I26_FORMAT(NAME, OP) \
|
||||
static inline void emit_##NAME(union loongarch_instruction *insn, \
|
||||
int offset) \
|
||||
@@ -566,4 +606,10 @@ static inline void emit_##NAME(union loongarch_instruction *insn, \
|
||||
|
||||
DEF_EMIT_REG3SA2_FORMAT(alsld, alsld_op)
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
void emulate_load_store_insn(struct pt_regs *regs, void __user *addr, unsigned int *pc);
|
||||
unsigned long unaligned_read(void __user *addr, void *value, unsigned long n, bool sign);
|
||||
unsigned long unaligned_write(void __user *addr, unsigned long value, unsigned long n);
|
||||
|
||||
#endif /* _ASM_INST_H */
|
||||
|
||||
@@ -136,4 +136,7 @@ typedef enum {
|
||||
#define ls7a_writel(val, addr) *(volatile unsigned int *)TO_UNCACHE(addr) = (val)
|
||||
#define ls7a_writeq(val, addr) *(volatile unsigned long *)TO_UNCACHE(addr) = (val)
|
||||
|
||||
void enable_gpe_wakeup(void);
|
||||
void enable_pci_wakeup(void);
|
||||
|
||||
#endif /* __ASM_LOONGSON_H */
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define RELA_STACK_DEPTH 16
|
||||
|
||||
struct mod_section {
|
||||
Elf_Shdr *shdr;
|
||||
int shndx;
|
||||
int num_entries;
|
||||
int max_entries;
|
||||
};
|
||||
@@ -20,6 +20,9 @@ struct mod_arch_specific {
|
||||
struct mod_section got;
|
||||
struct mod_section plt;
|
||||
struct mod_section plt_idx;
|
||||
|
||||
/* For CONFIG_DYNAMIC_FTRACE */
|
||||
struct plt_entry *ftrace_trampolines;
|
||||
};
|
||||
|
||||
struct got_entry {
|
||||
@@ -37,8 +40,8 @@ struct plt_idx_entry {
|
||||
Elf_Addr symbol_addr;
|
||||
};
|
||||
|
||||
Elf_Addr module_emit_got_entry(struct module *mod, Elf_Addr val);
|
||||
Elf_Addr module_emit_plt_entry(struct module *mod, Elf_Addr val);
|
||||
Elf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val);
|
||||
Elf_Addr module_emit_plt_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val);
|
||||
|
||||
static inline struct got_entry emit_got_entry(Elf_Addr val)
|
||||
{
|
||||
@@ -49,7 +52,7 @@ static inline struct plt_entry emit_plt_entry(unsigned long val)
|
||||
{
|
||||
u32 lu12iw, lu32id, lu52id, jirl;
|
||||
|
||||
lu12iw = (lu12iw_op << 25 | (((val >> 12) & 0xfffff) << 5) | LOONGARCH_GPR_T1);
|
||||
lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW));
|
||||
lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID));
|
||||
lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID));
|
||||
jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, 0, (val & 0xfff));
|
||||
@@ -62,10 +65,10 @@ static inline struct plt_idx_entry emit_plt_idx_entry(unsigned long val)
|
||||
return (struct plt_idx_entry) { val };
|
||||
}
|
||||
|
||||
static inline int get_plt_idx(unsigned long val, const struct mod_section *sec)
|
||||
static inline int get_plt_idx(unsigned long val, Elf_Shdr *sechdrs, const struct mod_section *sec)
|
||||
{
|
||||
int i;
|
||||
struct plt_idx_entry *plt_idx = (struct plt_idx_entry *)sec->shdr->sh_addr;
|
||||
struct plt_idx_entry *plt_idx = (struct plt_idx_entry *)sechdrs[sec->shndx].sh_addr;
|
||||
|
||||
for (i = 0; i < sec->num_entries; i++) {
|
||||
if (plt_idx[i].symbol_addr == val)
|
||||
@@ -76,11 +79,12 @@ static inline int get_plt_idx(unsigned long val, const struct mod_section *sec)
|
||||
}
|
||||
|
||||
static inline struct plt_entry *get_plt_entry(unsigned long val,
|
||||
const struct mod_section *sec_plt,
|
||||
const struct mod_section *sec_plt_idx)
|
||||
Elf_Shdr *sechdrs,
|
||||
const struct mod_section *sec_plt,
|
||||
const struct mod_section *sec_plt_idx)
|
||||
{
|
||||
int plt_idx = get_plt_idx(val, sec_plt_idx);
|
||||
struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr;
|
||||
int plt_idx = get_plt_idx(val, sechdrs, sec_plt_idx);
|
||||
struct plt_entry *plt = (struct plt_entry *)sechdrs[sec_plt->shndx].sh_addr;
|
||||
|
||||
if (plt_idx < 0)
|
||||
return NULL;
|
||||
@@ -89,10 +93,11 @@ static inline struct plt_entry *get_plt_entry(unsigned long val,
|
||||
}
|
||||
|
||||
static inline struct got_entry *get_got_entry(Elf_Addr val,
|
||||
Elf_Shdr *sechdrs,
|
||||
const struct mod_section *sec)
|
||||
{
|
||||
struct got_entry *got = (struct got_entry *)sec->shdr->sh_addr;
|
||||
int i;
|
||||
struct got_entry *got = (struct got_entry *)sechdrs[sec->shndx].sh_addr;
|
||||
|
||||
for (i = 0; i < sec->num_entries; i++)
|
||||
if (got[i].symbol_addr == val)
|
||||
|
||||
@@ -5,4 +5,5 @@ SECTIONS {
|
||||
.got : { BYTE(0) }
|
||||
.plt : { BYTE(0) }
|
||||
.plt.idx : { BYTE(0) }
|
||||
.ftrace_trampoline : { BYTE(0) }
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
extern unsigned long eentry;
|
||||
extern unsigned long tlbrentry;
|
||||
extern char init_command_line[COMMAND_LINE_SIZE];
|
||||
extern void tlb_init(int cpu);
|
||||
extern void cpu_cache_init(void);
|
||||
extern void cache_error_setup(void);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user