diff options
| author | Mark Brown <broonie@kernel.org> | 2026-10-27 13:26:07 +0000 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-10-27 13:26:07 +0000 |
| commit | c863dee9cf208fbd124be3468346d9eb557c242a (patch) | |
| tree | 5c5cbbadacb811bea525b10aca96aa871ef088a0 | |
| parent | 804e4955ac7d4ec75c6ec4414ec51d3e2125362f (diff) | |
| parent | ecb531544804101cb6ca0b124b5a446ee2db2f9f (diff) | |
| download | linux-next-c863dee9cf208fbd124be3468346d9eb557c242a.tar.gz linux-next-c863dee9cf208fbd124be3468346d9eb557c242a.zip | |
Merge branch 'loongarch-next' of https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git
37 files changed, 524 insertions, 79 deletions
diff --git a/Documentation/admin-guide/kdump/vmcoreinfo.rst b/Documentation/admin-guide/kdump/vmcoreinfo.rst index 5f1df6d08050..0fc4294b90a4 100644 --- a/Documentation/admin-guide/kdump/vmcoreinfo.rst +++ b/Documentation/admin-guide/kdump/vmcoreinfo.rst @@ -594,3 +594,39 @@ va_kernel_pa_offset Indicates the offset between the kernel virtual and physical mappings. Used to translate virtual to physical addresses. + +LOONGARCH64 +=========== + +VA_BITS +------- + +The maximum number of bits for virtual addresses. Used to compute the +virtual memory ranges. + +PHYS_OFFSET +----------- + +Indicates the physical address of the start of memory. Used to translate +virtual to physical addresses. + +PAGE_OFFSET +----------- + +Indicates the virtual kernel start address of the direct-mapped RAM region. +Used together with PHYS_OFFSET to translate between virtual and physical +addresses. + +KERNELOFFSET +------------ + +The kernel randomization offset. Used to locate the kernel text in virtual +memory. If KASLR is disabled, this value is zero. + +MODULES_VADDR|MODULES_END|VMALLOC_START|VMALLOC_END|VMEMMAP_START|VMEMMAP_END +----------------------------------------------------------------------------- + +Used to get the correct ranges: + MODULES_VADDR ~ MODULES_END-1 : Kernel module space. + VMALLOC_START ~ VMALLOC_END-1 : vmalloc() / ioremap() space. + VMEMMAP_START ~ VMEMMAP_END-1 : vmemmap region, used for struct page array. diff --git a/MAINTAINERS b/MAINTAINERS index ff54bf2d87a9..2efe7f9361c0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -350,6 +350,15 @@ S: Maintained F: drivers/acpi/arm64 F: include/linux/acpi_iort.h +ACPI FOR LOONGARCH (ACPI/LoongArch) +M: Bibo Mao <maobibo@loongson.cn> +M: Huacai Chen <chenhuacai@kernel.org> +L: linux-acpi@vger.kernel.org +L: loongarch@lists.linux.dev +S: Maintained +F: drivers/acpi/loongarch/ +F: include/linux/acpi_iovt.h + ACPI FOR RISC-V (ACPI/riscv) M: Sunil V L <sunilvl@ventanamicro.com> L: linux-acpi@vger.kernel.org diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 0aad0004b010..b5ed4881d3c0 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -6,6 +6,7 @@ config LOONGARCH select ACPI_GENERIC_GSI if ACPI select ACPI_MCFG if ACPI select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU + select ACPI_IOVT if ACPI select ACPI_PPTT if ACPI select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI select ARCH_BINFMT_ELF_STATE diff --git a/arch/loongarch/boot/dts/loongson-2k0500-ref.dts b/arch/loongarch/boot/dts/loongson-2k0500-ref.dts index 7ace54c84244..d2a3ed9fa578 100644 --- a/arch/loongarch/boot/dts/loongson-2k0500-ref.dts +++ b/arch/loongarch/boot/dts/loongson-2k0500-ref.dts @@ -73,14 +73,12 @@ status = "okay"; phy-mode = "rgmii-id"; - bus_id = <0x0>; }; &gmac1 { status = "okay"; phy-mode = "rgmii-id"; - bus_id = <0x1>; }; &i2c0 { diff --git a/arch/loongarch/include/asm/barrier.h b/arch/loongarch/include/asm/barrier.h index 4b663f197706..84c6d739119d 100644 --- a/arch/loongarch/include/asm/barrier.h +++ b/arch/loongarch/include/asm/barrier.h @@ -57,9 +57,6 @@ #define __WEAK_LLSC_MB " \n" #endif -#define __smp_mb__before_atomic() barrier() -#define __smp_mb__after_atomic() barrier() - /** * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise * @index: array element index diff --git a/arch/loongarch/include/asm/cpu-features.h b/arch/loongarch/include/asm/cpu-features.h index 62059c5551b9..f587cdd1acab 100644 --- a/arch/loongarch/include/asm/cpu-features.h +++ b/arch/loongarch/include/asm/cpu-features.h @@ -36,6 +36,7 @@ #define cpu_has_cpucfg cpu_opt(LOONGARCH_CPU_CPUCFG) #define cpu_has_lam cpu_opt(LOONGARCH_CPU_LAM) #define cpu_has_lam_bh cpu_opt(LOONGARCH_CPU_LAM_BH) +#define cpu_has_lamcas cpu_opt(LOONGARCH_CPU_LAMCAS) #define cpu_has_scq cpu_opt(LOONGARCH_CPU_SCQ) #define cpu_has_ual cpu_opt(LOONGARCH_CPU_UAL) #define cpu_has_fpu cpu_opt(LOONGARCH_CPU_FPU) @@ -44,6 +45,7 @@ #define cpu_has_crc32 cpu_opt(LOONGARCH_CPU_CRC32) #define cpu_has_complex cpu_opt(LOONGARCH_CPU_COMPLEX) #define cpu_has_crypto cpu_opt(LOONGARCH_CPU_CRYPTO) +#define cpu_has_div32 cpu_opt(LOONGARCH_CPU_DIV32) #define cpu_has_lvz cpu_opt(LOONGARCH_CPU_LVZ) #define cpu_has_lbt_x86 cpu_opt(LOONGARCH_CPU_LBT_X86) #define cpu_has_lbt_arm cpu_opt(LOONGARCH_CPU_LBT_ARM) diff --git a/arch/loongarch/include/asm/cpu.h b/arch/loongarch/include/asm/cpu.h index 91b96938861e..8d389bb49421 100644 --- a/arch/loongarch/include/asm/cpu.h +++ b/arch/loongarch/include/asm/cpu.h @@ -96,41 +96,44 @@ static inline char *id_to_core_name(unsigned int id) #define CPU_FEATURE_CPUCFG 0 /* CPU has CPUCFG */ #define CPU_FEATURE_LAM 1 /* CPU has Atomic instructions */ #define CPU_FEATURE_LAM_BH 2 /* CPU has AM{SWAP/ADD}[_DB].{B/H} instructions */ -#define CPU_FEATURE_SCQ 3 /* CPU has SC.Q instruction */ -#define CPU_FEATURE_UAL 4 /* CPU supports unaligned access */ -#define CPU_FEATURE_FPU 5 /* CPU has FPU */ -#define CPU_FEATURE_LSX 6 /* CPU has LSX (128-bit SIMD) */ -#define CPU_FEATURE_LASX 7 /* CPU has LASX (256-bit SIMD) */ -#define CPU_FEATURE_CRC32 8 /* CPU has CRC32 instructions */ -#define CPU_FEATURE_COMPLEX 9 /* CPU has Complex instructions */ -#define CPU_FEATURE_CRYPTO 10 /* CPU has Crypto instructions */ -#define CPU_FEATURE_LVZ 11 /* CPU has Virtualization extension */ -#define CPU_FEATURE_LBT_X86 12 /* CPU has X86 Binary Translation */ -#define CPU_FEATURE_LBT_ARM 13 /* CPU has ARM Binary Translation */ -#define CPU_FEATURE_LBT_MIPS 14 /* CPU has MIPS Binary Translation */ -#define CPU_FEATURE_TLB 15 /* CPU has TLB */ -#define CPU_FEATURE_CSR 16 /* CPU has CSR */ -#define CPU_FEATURE_IOCSR 17 /* CPU has IOCSR */ -#define CPU_FEATURE_WATCH 18 /* CPU has watchpoint registers */ -#define CPU_FEATURE_VINT 19 /* CPU has vectored interrupts */ -#define CPU_FEATURE_CSRIPI 20 /* CPU has CSR-IPI */ -#define CPU_FEATURE_EXTIOI 21 /* CPU has EXT-IOI */ -#define CPU_FEATURE_PREFETCH 22 /* CPU has prefetch instructions */ -#define CPU_FEATURE_PMP 23 /* CPU has perfermance counter */ -#define CPU_FEATURE_SCALEFREQ 24 /* CPU supports cpufreq scaling */ -#define CPU_FEATURE_FLATMODE 25 /* CPU has flat mode */ -#define CPU_FEATURE_EIODECODE 26 /* CPU has EXTIOI interrupt pin decode mode */ -#define CPU_FEATURE_GUESTID 27 /* CPU has GuestID feature */ -#define CPU_FEATURE_HYPERVISOR 28 /* CPU has hypervisor (running in VM) */ -#define CPU_FEATURE_PTW 29 /* CPU has hardware page table walker */ -#define CPU_FEATURE_LSPW 30 /* CPU has LSPW (lddir/ldpte instructions) */ -#define CPU_FEATURE_MSGINT 31 /* CPU has MSG interrupt */ -#define CPU_FEATURE_AVECINT 32 /* CPU has AVEC interrupt */ -#define CPU_FEATURE_REDIRECTINT 33 /* CPU has interrupt remapping */ +#define CPU_FEATURE_LAMCAS 3 /* CPU has AMCAS[_DB].{B/H/W/D} instructions */ +#define CPU_FEATURE_SCQ 4 /* CPU has SC.Q instruction */ +#define CPU_FEATURE_UAL 5 /* CPU supports unaligned access */ +#define CPU_FEATURE_FPU 6 /* CPU has FPU */ +#define CPU_FEATURE_LSX 7 /* CPU has LSX (128-bit SIMD) */ +#define CPU_FEATURE_LASX 8 /* CPU has LASX (256-bit SIMD) */ +#define CPU_FEATURE_CRC32 9 /* CPU has CRC32 instructions */ +#define CPU_FEATURE_COMPLEX 10 /* CPU has Complex instructions */ +#define CPU_FEATURE_CRYPTO 11 /* CPU has Crypto instructions */ +#define CPU_FEATURE_DIV32 12 /* CPU has DIV32 feature */ +#define CPU_FEATURE_LVZ 13 /* CPU has Virtualization extension */ +#define CPU_FEATURE_LBT_X86 14 /* CPU has X86 Binary Translation */ +#define CPU_FEATURE_LBT_ARM 15 /* CPU has ARM Binary Translation */ +#define CPU_FEATURE_LBT_MIPS 16 /* CPU has MIPS Binary Translation */ +#define CPU_FEATURE_TLB 17 /* CPU has TLB */ +#define CPU_FEATURE_CSR 18 /* CPU has CSR */ +#define CPU_FEATURE_IOCSR 19 /* CPU has IOCSR */ +#define CPU_FEATURE_WATCH 20 /* CPU has watchpoint registers */ +#define CPU_FEATURE_VINT 21 /* CPU has vectored interrupts */ +#define CPU_FEATURE_CSRIPI 22 /* CPU has CSR-IPI */ +#define CPU_FEATURE_EXTIOI 23 /* CPU has EXT-IOI */ +#define CPU_FEATURE_PREFETCH 24 /* CPU has prefetch instructions */ +#define CPU_FEATURE_PMP 25 /* CPU has perfermance counter */ +#define CPU_FEATURE_SCALEFREQ 26 /* CPU supports cpufreq scaling */ +#define CPU_FEATURE_FLATMODE 27 /* CPU has flat mode */ +#define CPU_FEATURE_EIODECODE 28 /* CPU has EXTIOI interrupt pin decode mode */ +#define CPU_FEATURE_GUESTID 29 /* CPU has GuestID feature */ +#define CPU_FEATURE_HYPERVISOR 30 /* CPU has hypervisor (running in VM) */ +#define CPU_FEATURE_PTW 31 /* CPU has hardware page table walker */ +#define CPU_FEATURE_LSPW 32 /* CPU has LSPW (lddir/ldpte instructions) */ +#define CPU_FEATURE_MSGINT 33 /* CPU has MSG interrupt */ +#define CPU_FEATURE_AVECINT 34 /* CPU has AVEC interrupt */ +#define CPU_FEATURE_REDIRECTINT 35 /* CPU has interrupt remapping */ #define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG) #define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM) #define LOONGARCH_CPU_LAM_BH BIT_ULL(CPU_FEATURE_LAM_BH) +#define LOONGARCH_CPU_LAMCAS BIT_ULL(CPU_FEATURE_LAMCAS) #define LOONGARCH_CPU_SCQ BIT_ULL(CPU_FEATURE_SCQ) #define LOONGARCH_CPU_UAL BIT_ULL(CPU_FEATURE_UAL) #define LOONGARCH_CPU_FPU BIT_ULL(CPU_FEATURE_FPU) @@ -139,6 +142,7 @@ static inline char *id_to_core_name(unsigned int id) #define LOONGARCH_CPU_CRC32 BIT_ULL(CPU_FEATURE_CRC32) #define LOONGARCH_CPU_COMPLEX BIT_ULL(CPU_FEATURE_COMPLEX) #define LOONGARCH_CPU_CRYPTO BIT_ULL(CPU_FEATURE_CRYPTO) +#define LOONGARCH_CPU_DIV32 BIT_ULL(CPU_FEATURE_DIV32) #define LOONGARCH_CPU_LVZ BIT_ULL(CPU_FEATURE_LVZ) #define LOONGARCH_CPU_LBT_X86 BIT_ULL(CPU_FEATURE_LBT_X86) #define LOONGARCH_CPU_LBT_ARM BIT_ULL(CPU_FEATURE_LBT_ARM) diff --git a/arch/loongarch/include/asm/hw_breakpoint.h b/arch/loongarch/include/asm/hw_breakpoint.h index 5faa97a87a9e..f4478936787d 100644 --- a/arch/loongarch/include/asm/hw_breakpoint.h +++ b/arch/loongarch/include/asm/hw_breakpoint.h @@ -116,17 +116,17 @@ extern void arch_uninstall_hw_breakpoint(struct perf_event *bp); extern int hw_breakpoint_slots(int type); extern void hw_breakpoint_pmu_read(struct perf_event *bp); -void breakpoint_handler(struct pt_regs *regs); -void watchpoint_handler(struct pt_regs *regs); +bool breakpoint_handler(struct pt_regs *regs); +bool watchpoint_handler(struct pt_regs *regs); #ifdef CONFIG_HAVE_HW_BREAKPOINT extern void ptrace_hw_copy_thread(struct task_struct *task); -extern void hw_breakpoint_thread_switch(struct task_struct *next); +extern void hw_breakpoint_thread_switch(struct task_struct *prev, struct task_struct *next); #else static inline void ptrace_hw_copy_thread(struct task_struct *task) { } -static inline void hw_breakpoint_thread_switch(struct task_struct *next) +static inline void hw_breakpoint_thread_switch(struct task_struct *prev, struct task_struct *next) { } #endif diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index 88e3bdfd4971..b26d0e1b2634 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -1135,8 +1135,11 @@ #define LOONGARCH_CSR_DERA 0x501 /* debug era */ #define LOONGARCH_CSR_DESAVE 0x502 /* debug save */ -#define CSR_FWPC_SKIP_SHIFT 16 -#define CSR_FWPC_SKIP (_ULCAST_(1) << CSR_FWPC_SKIP_SHIFT) +#define CSR_FWPS_SKIP_SHIFT 16 +#define CSR_FWPS_SKIP (_ULCAST_(1) << CSR_FWPS_SKIP_SHIFT) + +#define CSR_MWPS_SKIP_SHIFT 16 +#define CSR_MWPS_SKIP (_ULCAST_(1) << CSR_MWPS_SKIP_SHIFT) /* * CSR_ECFG IM diff --git a/arch/loongarch/include/asm/numa.h b/arch/loongarch/include/asm/numa.h index bbf9f70bd25f..c9654ff900a3 100644 --- a/arch/loongarch/include/asm/numa.h +++ b/arch/loongarch/include/asm/numa.h @@ -14,7 +14,7 @@ #define NODE_ADDRSPACE_SHIFT 44 #define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT) -#define nid_to_addrbase(nid) (_ULCAST_(nid) << NODE_ADDRSPACE_SHIFT) +#define nid_to_addrbase(nid) (_U64CAST_(nid) << NODE_ADDRSPACE_SHIFT) #ifdef CONFIG_NUMA diff --git a/arch/loongarch/include/asm/processor.h b/arch/loongarch/include/asm/processor.h index ce8b953f8c79..a884f964ec98 100644 --- a/arch/loongarch/include/asm/processor.h +++ b/arch/loongarch/include/asm/processor.h @@ -138,6 +138,7 @@ struct thread_struct { struct loongarch_lbt lbt; /* Also conditionally copied */ /* Hardware breakpoints pinned to this task. */ + bool hbp_break_skip, hbp_watch_skip; struct perf_event *hbp_break[LOONGARCH_MAX_BRP]; struct perf_event *hbp_watch[LOONGARCH_MAX_WRP]; }; diff --git a/arch/loongarch/include/asm/switch_to.h b/arch/loongarch/include/asm/switch_to.h index 27acbf913774..ab9e0292c7f3 100644 --- a/arch/loongarch/include/asm/switch_to.h +++ b/arch/loongarch/include/asm/switch_to.h @@ -34,7 +34,7 @@ extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev, do { \ lose_fpu_inatomic(1, prev); \ lose_lbt_inatomic(1, prev); \ - hw_breakpoint_thread_switch(next); \ + hw_breakpoint_thread_switch(prev, next); \ set_current(next); \ (last) = __switch_to(prev, next, \ __builtin_return_address(0), __builtin_frame_address(0)); \ diff --git a/arch/loongarch/include/uapi/asm/hwcap.h b/arch/loongarch/include/uapi/asm/hwcap.h index 90e96113ba51..cc609e3486bc 100644 --- a/arch/loongarch/include/uapi/asm/hwcap.h +++ b/arch/loongarch/include/uapi/asm/hwcap.h @@ -20,5 +20,7 @@ #define HWCAP_LOONGARCH_LSPW (1 << 14) #define HWCAP_LOONGARCH_SCQ (1 << 15) #define HWCAP_LOONGARCH_LAM_BH (1 << 16) +#define HWCAP_LOONGARCH_LAMCAS (1 << 17) +#define HWCAP_LOONGARCH_DIV32 (1 << 18) #endif /* _UAPI_ASM_HWCAP_H */ diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile index 001924877772..6260c15adaba 100644 --- a/arch/loongarch/kernel/Makefile +++ b/arch/loongarch/kernel/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_RELOCATABLE) += relocate.o obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_efi.o kexec_elf.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o +obj-$(CONFIG_VMCORE_INFO) += vmcore_info.o obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o obj-$(CONFIG_UNWINDER_PROLOGUE) += unwind_prologue.o diff --git a/arch/loongarch/kernel/cpu-probe.c b/arch/loongarch/kernel/cpu-probe.c index 7121e7483498..692bf7c85090 100644 --- a/arch/loongarch/kernel/cpu-probe.c +++ b/arch/loongarch/kernel/cpu-probe.c @@ -93,7 +93,7 @@ static int __init cpu_final_simd(void) return 0; } -arch_initcall(cpu_final_simd); +pure_initcall(cpu_final_simd); static inline void set_elf_platform(int cpu, const char *plat) { @@ -182,6 +182,10 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) c->options |= LOONGARCH_CPU_LAM_BH; elf_hwcap |= HWCAP_LOONGARCH_LAM_BH; } + if (config & CPUCFG2_LAMCAS) { + c->options |= LOONGARCH_CPU_LAMCAS; + elf_hwcap |= HWCAP_LOONGARCH_LAMCAS; + } if (config & CPUCFG2_SCQ) { c->options |= LOONGARCH_CPU_SCQ; elf_hwcap |= HWCAP_LOONGARCH_SCQ; @@ -210,6 +214,10 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) c->options |= LOONGARCH_CPU_CRYPTO; elf_hwcap |= HWCAP_LOONGARCH_CRYPTO; } + if (config & CPUCFG2_DIV32) { + c->options |= LOONGARCH_CPU_DIV32; + elf_hwcap |= HWCAP_LOONGARCH_DIV32; + } if (config & CPUCFG2_PTW) { c->options |= LOONGARCH_CPU_PTW; elf_hwcap |= HWCAP_LOONGARCH_PTW; diff --git a/arch/loongarch/kernel/efi-header.S b/arch/loongarch/kernel/efi-header.S index 6df56241cb95..c041dad5bbb6 100644 --- a/arch/loongarch/kernel/efi-header.S +++ b/arch/loongarch/kernel/efi-header.S @@ -51,7 +51,7 @@ .long .Lefi_header_end - _head /* SizeOfHeaders */ .long 0 /* CheckSum */ .short IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */ - .short 0 /* DllCharacteristics */ + .short IMAGE_DLLCHARACTERISTICS_NX_COMPAT /* DllCharacteristics */ .quad 0 /* SizeOfStackReserve */ .quad 0 /* SizeOfStackCommit */ .quad 0 /* SizeOfHeapReserve */ diff --git a/arch/loongarch/kernel/env.c b/arch/loongarch/kernel/env.c index 652456768b55..c529a14deb18 100644 --- a/arch/loongarch/kernel/env.c +++ b/arch/loongarch/kernel/env.c @@ -25,10 +25,7 @@ void __init init_environ(void) int efi_boot = fw_arg0; char *cmdline = early_memremap_ro(fw_arg1, COMMAND_LINE_SIZE); - if (efi_boot) - set_bit(EFI_BOOT, &efi.flags); - else - clear_bit(EFI_BOOT, &efi.flags); + assign_bit(EFI_BOOT, &efi.flags, efi_boot); strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE); strscpy(init_command_line, cmdline, COMMAND_LINE_SIZE); diff --git a/arch/loongarch/kernel/hw_breakpoint.c b/arch/loongarch/kernel/hw_breakpoint.c index c35f9bf38033..df149ff06dd5 100644 --- a/arch/loongarch/kernel/hw_breakpoint.c +++ b/arch/loongarch/kernel/hw_breakpoint.c @@ -156,6 +156,9 @@ static int hw_breakpoint_slot_setup(struct perf_event **slots, int max_slots, void ptrace_hw_copy_thread(struct task_struct *tsk) { + tsk->thread.hbp_break_skip = 0; + tsk->thread.hbp_watch_skip = 0; + memset(tsk->thread.hbp_break, 0, sizeof(tsk->thread.hbp_break)); memset(tsk->thread.hbp_watch, 0, sizeof(tsk->thread.hbp_watch)); } @@ -233,7 +236,7 @@ static int hw_breakpoint_control(struct perf_event *bp, } enable = csr_read64(LOONGARCH_CSR_CRMD); csr_write64(CSR_CRMD_WE | enable, LOONGARCH_CSR_CRMD); - if (bp->hw.target && test_tsk_thread_flag(bp->hw.target, TIF_LOAD_WATCH)) + if (bp->hw.target) regs->csr_prmd |= CSR_PRMD_PWE; break; case HW_BREAKPOINT_UNINSTALL: @@ -453,7 +456,6 @@ static void update_bp_registers(struct pt_regs *regs, int enable, int type) if (enable) { if ((info->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) && (type == 0)) { write_wb_reg(CSR_CFG_CTRL, i, 0, CTRL_PLV_ENABLE); - write_wb_reg(CSR_CFG_CTRL, i, 0, CTRL_PLV_ENABLE); } else { ctrl = read_wb_reg(CSR_CFG_CTRL, i, 1); if (info->ctrl.type == LOONGARCH_BREAKPOINT_LOAD) @@ -469,9 +471,9 @@ static void update_bp_registers(struct pt_regs *regs, int enable, int type) } else { ctrl = read_wb_reg(CSR_CFG_CTRL, i, 1); if (info->ctrl.type == LOONGARCH_BREAKPOINT_LOAD) - ctrl &= ~0x1 << MWPnCFG3_LoadEn; + ctrl &= ~(0x1 << MWPnCFG3_LoadEn); if (info->ctrl.type == LOONGARCH_BREAKPOINT_STORE) - ctrl &= ~0x1 << MWPnCFG3_StoreEn; + ctrl &= ~(0x1 << MWPnCFG3_StoreEn); write_wb_reg(CSR_CFG_CTRL, i, 1, ctrl); } regs->csr_prmd &= ~CSR_PRMD_PWE; @@ -483,9 +485,11 @@ NOKPROBE_SYMBOL(update_bp_registers); /* * Debug exception handlers. */ -void breakpoint_handler(struct pt_regs *regs) +bool breakpoint_handler(struct pt_regs *regs) { int i; + unsigned int clear_mask = 0; + bool need_sigtrap = false; struct perf_event *bp, **slots; slots = this_cpu_ptr(bp_on_reg); @@ -495,17 +499,27 @@ void breakpoint_handler(struct pt_regs *regs) bp = slots[i]; if (bp == NULL) continue; + perf_bp_event(bp, regs); - csr_write32(0x1 << i, LOONGARCH_CSR_FWPS); - update_bp_registers(regs, 0, 0); + if (bp->attr.sigtrap) + need_sigtrap = true; + + clear_mask |= (0x1 << i); } } + + if (clear_mask) + csr_write32(clear_mask | CSR_FWPS_SKIP, LOONGARCH_CSR_FWPS); + + return need_sigtrap; } NOKPROBE_SYMBOL(breakpoint_handler); -void watchpoint_handler(struct pt_regs *regs) +bool watchpoint_handler(struct pt_regs *regs) { int i; + unsigned int clear_mask = 0; + bool need_sigtrap = false; struct perf_event *wp, **slots; slots = this_cpu_ptr(wp_on_reg); @@ -515,11 +529,19 @@ void watchpoint_handler(struct pt_regs *regs) wp = slots[i]; if (wp == NULL) continue; + perf_bp_event(wp, regs); - csr_write32(0x1 << i, LOONGARCH_CSR_MWPS); - update_bp_registers(regs, 0, 1); + if (wp->attr.sigtrap) + need_sigtrap = true; + + clear_mask |= (0x1 << i); } } + + if (clear_mask) + csr_write32(clear_mask | CSR_MWPS_SKIP, LOONGARCH_CSR_MWPS); + + return need_sigtrap; } NOKPROBE_SYMBOL(watchpoint_handler); @@ -542,7 +564,7 @@ static int __init arch_hw_breakpoint_init(void) } arch_initcall(arch_hw_breakpoint_init); -void hw_breakpoint_thread_switch(struct task_struct *next) +void hw_breakpoint_thread_switch(struct task_struct *prev, struct task_struct *next) { u64 addr, mask; struct pt_regs *regs = task_pt_regs(next); @@ -551,9 +573,29 @@ void hw_breakpoint_thread_switch(struct task_struct *next) addr = read_wb_reg(CSR_CFG_ADDR, 0, 0); mask = read_wb_reg(CSR_CFG_MASK, 0, 0); if (!((regs->csr_era ^ addr) & ~mask)) - csr_write32(CSR_FWPC_SKIP, LOONGARCH_CSR_FWPS); + csr_write32(CSR_FWPS_SKIP, LOONGARCH_CSR_FWPS); regs->csr_prmd |= CSR_PRMD_PWE; } else { + unsigned int fwps = csr_read32(LOONGARCH_CSR_FWPS); + unsigned int mwps = csr_read32(LOONGARCH_CSR_MWPS); + + prev->thread.hbp_break_skip = !!(fwps & CSR_FWPS_SKIP); + prev->thread.hbp_watch_skip = !!(mwps & CSR_MWPS_SKIP); + + if (!next->thread.hbp_break_skip) + csr_write32(0, LOONGARCH_CSR_FWPS); + else { + csr_write32(CSR_FWPS_SKIP, LOONGARCH_CSR_FWPS); + next->thread.hbp_break_skip = 0; + } + + if (!next->thread.hbp_watch_skip) + csr_write32(0, LOONGARCH_CSR_MWPS); + else { + csr_write32(CSR_MWPS_SKIP, LOONGARCH_CSR_MWPS); + next->thread.hbp_watch_skip = 0; + } + /* Update breakpoints */ update_bp_registers(regs, 1, 0); /* Update watchpoints */ diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index 7bf68a7a5f4b..29e0f2baaa8c 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -20,6 +20,7 @@ #include <asm/irq.h> #include <asm/loongson.h> +#include <asm/numa.h> #include <asm/setup.h> DEFINE_PER_CPU(unsigned long, irq_stack); @@ -69,7 +70,7 @@ static int __init early_pci_mcfg_parse(struct acpi_table_header *header) for (i = 0; i < n; i++, mptr++) { msi_group[i].pci_segment = mptr->pci_segment; - pch_group[i].node = msi_group[i].node = (mptr->address >> 44) & 0xf; + pch_group[i].node = msi_group[i].node = pa_to_nid(mptr->address); } return 0; diff --git a/arch/loongarch/kernel/numa.c b/arch/loongarch/kernel/numa.c index c96c53623715..7dedc134ddfe 100644 --- a/arch/loongarch/kernel/numa.c +++ b/arch/loongarch/kernel/numa.c @@ -216,6 +216,8 @@ static int __init fake_numa_init(void) phys_addr_t start = memblock_start_of_DRAM(); phys_addr_t end = memblock_end_of_DRAM() - 1; + set_cpuid_to_node(0, 0); + early_numa_add_cpu(0, 0); pr_info("Faking a node at [mem %pap-%pap]\n", &start, &end); return numa_add_memblk(0, start, end + 1); @@ -244,8 +246,10 @@ int __init init_numa_memory(void) return -EINVAL; for_each_node_mask(node, node_possible_map) { - node_mem_init(node); - node_set_online(node); + if (!cpumask_empty(&cpus_on_node[node])) { + node_mem_init(node); + node_set_online(node); + } } max_pfn = PFN_DOWN(memblock_end_of_DRAM()); max_low_pfn = min(PFN_DOWN(HIGHMEM_START), max_pfn); diff --git a/arch/loongarch/kernel/proc.c b/arch/loongarch/kernel/proc.c index d4ce5b585453..37e9b144ec09 100644 --- a/arch/loongarch/kernel/proc.c +++ b/arch/loongarch/kernel/proc.c @@ -66,6 +66,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_puts(m, " lam"); if (cpu_has_lam_bh) seq_puts(m, " lam_bh"); + if (cpu_has_lamcas) + seq_puts(m, " lamcas"); if (cpu_has_scq) seq_puts(m, " scq"); if (cpu_has_ual) @@ -82,6 +84,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_puts(m, " complex"); if (cpu_has_crypto) seq_puts(m, " crypto"); + if (cpu_has_div32) + seq_puts(m, " div32"); if (cpu_has_ptw) seq_puts(m, " ptw"); if (cpu_has_lspw) diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c index 776523747ea3..20ce2c8d77a1 100644 --- a/arch/loongarch/kernel/traps.c +++ b/arch/loongarch/kernel/traps.c @@ -815,6 +815,8 @@ asmlinkage void noinstr do_watch(struct pt_regs *regs) #ifndef CONFIG_HAVE_HW_BREAKPOINT pr_warn("Hardware watch point handler not implemented!\n"); #else + bool need_sigtrap = !!current->ptrace; + if (kgdb_breakpoint_handler(regs)) goto out; @@ -829,7 +831,7 @@ asmlinkage void noinstr do_watch(struct pt_regs *regs) * instruction. So don't clear llbit and reset CSR.FWPS.Skip until * the llsc execution is completed. */ - csr_write32(CSR_FWPC_SKIP, LOONGARCH_CSR_FWPS); + csr_write32(CSR_FWPS_SKIP, LOONGARCH_CSR_FWPS); csr_write32(CSR_LLBCTL_KLO, LOONGARCH_CSR_LLBCTL); goto out; } @@ -846,16 +848,17 @@ asmlinkage void noinstr do_watch(struct pt_regs *regs) * current pc, If yes, then we should not set the CSR.FWPS.SKIP * bit to break the original instruction stream. */ - csr_write32(CSR_FWPC_SKIP, LOONGARCH_CSR_FWPS); + csr_write32(CSR_FWPS_SKIP, LOONGARCH_CSR_FWPS); goto out; } } } else { - breakpoint_handler(regs); - watchpoint_handler(regs); + need_sigtrap |= breakpoint_handler(regs); + need_sigtrap |= watchpoint_handler(regs); } - force_sig(SIGTRAP); + if (need_sigtrap) + force_sig(SIGTRAP); out: #endif irqentry_exit(regs, state); diff --git a/arch/loongarch/kernel/vmcore_info.c b/arch/loongarch/kernel/vmcore_info.c new file mode 100644 index 000000000000..e4efc35165b1 --- /dev/null +++ b/arch/loongarch/kernel/vmcore_info.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/vmcore_info.h> +#include <asm/addrspace.h> +#include <asm/pgtable.h> +#include <asm/setup.h> + +void arch_crash_save_vmcoreinfo(void) +{ + VMCOREINFO_NUMBER(VA_BITS); + /* NUMBER(VMALLOC_START) is exported by the generic code */ + vmcoreinfo_append_str("NUMBER(VMALLOC_END)=0x%lx\n", VMALLOC_END); +#ifdef CONFIG_64BIT + vmcoreinfo_append_str("NUMBER(MODULES_VADDR)=0x%lx\n", MODULES_VADDR); + vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END); + vmcoreinfo_append_str("NUMBER(VMEMMAP_START)=0x%lx\n", (unsigned long)vmemmap); + vmcoreinfo_append_str("NUMBER(VMEMMAP_END)=0x%lx\n", VMEMMAP_END + 1); +#endif + vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%lx\n", PHYS_OFFSET); + vmcoreinfo_append_str("NUMBER(PAGE_OFFSET)=0x%lx\n", PAGE_OFFSET); + vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset()); +} diff --git a/arch/loongarch/pci/pci.c b/arch/loongarch/pci/pci.c index f33c7ea1443d..0b99b32110a5 100644 --- a/arch/loongarch/pci/pci.c +++ b/arch/loongarch/pci/pci.c @@ -12,6 +12,7 @@ #include <linux/io-64-nonatomic-lo-hi.h> #include <asm/cacheflush.h> #include <asm/loongson.h> +#include <asm/numa.h> #define PCI_DEVICE_ID_LOONGSON_HOST 0x7a00 #define PCI_DEVICE_ID_LOONGSON_DC1 0x7a06 @@ -43,7 +44,7 @@ int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, phys_addr_t mcfg_addr_init(int node) { - return (((u64)node << 44) | MCFG_EXT_PCICFG_BASE); + return (nid_to_addrbase(node) | MCFG_EXT_PCICFG_BASE); } static int __init pcibios_init(void) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index f165d14cf61a..192e6f18eda1 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -550,6 +550,10 @@ if ARM64 source "drivers/acpi/arm64/Kconfig" endif +if LOONGARCH +source "drivers/acpi/loongarch/Kconfig" +endif + if RISCV source "drivers/acpi/riscv/Kconfig" endif diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d1b0affb844f..91584a3c1e01 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -131,6 +131,6 @@ obj-y += dptf/ obj-$(CONFIG_ARM64) += arm64/ obj-$(CONFIG_ACPI_VIOT) += viot.o - +obj-$(CONFIG_LOONGARCH) += loongarch/ obj-$(CONFIG_RISCV) += riscv/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d5d234dfa9a2..1d6867dec925 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1449,6 +1449,7 @@ struct kobject *acpi_kobj; EXPORT_SYMBOL_GPL(acpi_kobj); void __weak __init acpi_arch_init(void) { } +void __weak __init acpi_arch_late_init(void) { } static int __init acpi_init(void) { @@ -1487,6 +1488,7 @@ static int __init acpi_init(void) acpi_wakeup_device_init(); acpi_debugger_init(); acpi_setup_sb_notify_handler(); + acpi_arch_late_init(); acpi_viot_init(); return 0; } diff --git a/drivers/acpi/loongarch/Kconfig b/drivers/acpi/loongarch/Kconfig new file mode 100644 index 000000000000..91ba3c35b9bf --- /dev/null +++ b/drivers/acpi/loongarch/Kconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# ACPI Configuration for LOONGARCH +# + +config ACPI_IOVT + bool diff --git a/drivers/acpi/loongarch/Makefile b/drivers/acpi/loongarch/Makefile new file mode 100644 index 000000000000..d0cb177294a6 --- /dev/null +++ b/drivers/acpi/loongarch/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-y += init.o +obj-$(CONFIG_ACPI_IOVT) += iovt.o diff --git a/drivers/acpi/loongarch/init.c b/drivers/acpi/loongarch/init.c new file mode 100644 index 000000000000..e7272ee197c7 --- /dev/null +++ b/drivers/acpi/loongarch/init.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/acpi.h> +#include "init.h" + +void __init acpi_arch_init(void) +{ + if (IS_ENABLED(CONFIG_ACPI_IOVT)) + acpi_iovt_init(); +} + +void __init acpi_arch_late_init(void) +{ + if (IS_ENABLED(CONFIG_ACPI_IOVT)) + acpi_iovt_late_init(); +} diff --git a/drivers/acpi/loongarch/init.h b/drivers/acpi/loongarch/init.h new file mode 100644 index 000000000000..85e5197553ad --- /dev/null +++ b/drivers/acpi/loongarch/init.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <linux/init.h> + +void __init acpi_iovt_init(void); +void __init acpi_iovt_late_init(void); diff --git a/drivers/acpi/loongarch/iovt.c b/drivers/acpi/loongarch/iovt.c new file mode 100644 index 000000000000..87cee4f0fc80 --- /dev/null +++ b/drivers/acpi/loongarch/iovt.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/acpi.h> +#include <linux/acpi_iovt.h> +#include <linux/pci.h> +#include "init.h" + +struct iovt_device_entry { + struct list_head list; + int start_devid, end_devid; +}; + +struct iovt_fwnode { + struct list_head list; + struct fwnode_handle *fwnode; + int flag; + int nid, segment, devid; + struct list_head ep_list; +}; + +static LIST_HEAD(iovt_fwnode_list); +static DEFINE_SPINLOCK(iovt_fwnode_lock); + +#ifdef CONFIG_PCI +static void __init iovt_enable_acs(struct acpi_iovt_iommu *iommu) +{ + static bool acs_enabled __initdata; + + if (acs_enabled) + return; + + /* IOMMU V1 only supports PCI device management */ + if ((iommu->header.type == ACPI_IOVT_IOMMU_V1) || + (iommu->flags & (ACPI_IOVT_IOMMU_PCI_DEVICE | ACPI_IOVT_IOMMU_MAGAGE_BY_SEGMENT))) { + pci_request_acs(); + acs_enabled = true; + } +} +#else +static inline void iovt_enable_acs(struct acpi_iovt_iommu *iommu) { } +#endif + +static int __init iovt_get_pci_iommu_fwnode(struct iovt_fwnode *np, u16 segment, u16 bdf) +{ + struct pci_dev *pdev; + struct fwnode_handle *fwnode; + + pdev = pci_get_domain_bus_and_slot(segment, PCI_BUS_NUM(bdf), bdf & 0xff); + if (!pdev) { + pr_err("No PCI IOMMU found for segment 0x%x bdf 0x%x\n", segment, bdf); + return -ENODEV; + } + + fwnode = dev_fwnode(&pdev->dev); + if (!fwnode) { + /* + * PCI devices aren't necessarily described by ACPI. Create + * a fwnode so the IOMMU subsystem can identify this device. + */ + fwnode = acpi_alloc_fwnode_static(); + if (!fwnode) { + pci_dev_put(pdev); + return -ENOMEM; + } + set_primary_fwnode(&pdev->dev, fwnode); + } + + np->fwnode = dev_fwnode(&pdev->dev); + if (np->flag & ACPI_IOVT_IOMMU_PXM_VALID) + set_dev_node(&pdev->dev, np->nid); + pci_dev_put(pdev); + + return 0; +} + +static int __init iovt_add_iommu(struct acpi_iovt_iommu *iommu) +{ + int i, ret; + bool is_start = false; + struct iovt_fwnode *np; + struct iovt_device_entry *entry; + struct acpi_iovt_device_entry *ep; + + np = kzalloc_obj(struct iovt_fwnode, GFP_ATOMIC); + if (WARN_ON(!np)) + return -ENOMEM; + + INIT_LIST_HEAD(&np->list); + np->flag = iommu->flags; + np->segment = iommu->segment; + if (np->flag & ACPI_IOVT_IOMMU_PXM_VALID) + np->nid = pxm_to_node(iommu->proximity_domain); + + if (np->flag & ACPI_IOVT_IOMMU_PCI_DEVICE) { + np->devid = iommu->device_id; + ret = iovt_get_pci_iommu_fwnode(np, np->segment, np->devid); + if (ret < 0) { + kfree(np); + return ret; + } + } else { + np->fwnode = acpi_alloc_fwnode_static(); + if (!np->fwnode) { + kfree(np); + return -ENOMEM; + } + } + + /* All devices in the segment are managed by this IOMMU */ + if (np->flag & ACPI_IOVT_IOMMU_MAGAGE_BY_SEGMENT) + goto skip; + + INIT_LIST_HEAD(&np->ep_list); + ep = ACPI_ADD_PTR(struct acpi_iovt_device_entry, iommu, iommu->device_entry_offset); + for (i = 0; i < iommu->device_entry_num; i++) { + switch (ep->type) { + case ACPI_IOVT_DEVICE_ENTRY_START: + is_start = true; + entry->start_devid = ep->device_id; + break; + case ACPI_IOVT_DEVICE_ENTRY_END: + if (!is_start) + break; + + entry = kzalloc_obj(struct iovt_device_entry, GFP_ATOMIC); + if (!entry) + return -ENOMEM; + + is_start = false; + entry->end_devid = ep->device_id; + list_add_tail(&entry->list, &np->ep_list); + break; + case ACPI_IOVT_DEVICE_ENTRY_SINGLE: + entry = kzalloc_obj(struct iovt_device_entry, GFP_ATOMIC); + if (!entry) + return -ENOMEM; + + is_start = false; + entry->start_devid = ep->device_id; + entry->end_devid = ep->device_id; + list_add_tail(&entry->list, &np->ep_list); + break; + default: + break; + } + ep = ACPI_ADD_PTR(struct acpi_iovt_device_entry, ep, ep->length); + } + +skip: + spin_lock(&iovt_fwnode_lock); + list_add_tail(&np->list, &iovt_fwnode_list); + spin_unlock(&iovt_fwnode_lock); + return 0; +} + +static void __init iovt_init_devices(struct acpi_table_header *header) +{ + int i; + struct acpi_table_iovt *iovt; + struct acpi_iovt_iommu *iommu; + + /* Get the first IOVT node */ + iovt = (struct acpi_table_iovt *)header; + iommu = ACPI_ADD_PTR(struct acpi_iovt_iommu, iovt, iovt->iommu_offset); + for (i = 0; i < iovt->iommu_count; i++) { + iovt_add_iommu(iommu); + iommu = ACPI_ADD_PTR(struct acpi_iovt_iommu, iommu, iommu->header.length); + } +} + +void __init acpi_iovt_init(void) +{ + int i; + acpi_status status; + struct acpi_table_header *hdr; + struct acpi_table_iovt *iovt; + struct acpi_iovt_iommu *iommu; + + status = acpi_get_table(ACPI_SIG_IOVT, 0, &hdr); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + pr_err("Failed to get table, %s\n", acpi_format_exception(status)); + + return; + } + + iovt = (struct acpi_table_iovt *)&hdr; + iommu = ACPI_ADD_PTR(struct acpi_iovt_iommu, iovt, iovt->iommu_offset); + for (i = 0; i < iovt->iommu_count; i++) { + iovt_enable_acs(iommu); + iommu = ACPI_ADD_PTR(struct acpi_iovt_iommu, iommu, iommu->header.length); + } + + acpi_put_table(hdr); +} + +void __init acpi_iovt_late_init(void) +{ + acpi_status status; + struct acpi_table_header *hdr; + + status = acpi_get_table(ACPI_SIG_IOVT, 0, &hdr); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + pr_err("Failed to get table, %s\n", acpi_format_exception(status)); + + return; + } + + iovt_init_devices(hdr); + acpi_put_table(hdr); +} + +static int iovt_pci_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) +{ + struct iovt_fwnode *np; + struct iovt_device_entry *entry; + struct device *aliased_dev = data; + u32 domain = pci_domain_nr(pdev->bus); + + list_for_each_entry(np, &iovt_fwnode_list, list) { + if (domain != np->segment) + continue; + + /* We're not translating ourself */ + if (dev_id == np->devid) + return -EINVAL; + + if (np->flag & ACPI_IOVT_IOMMU_MAGAGE_BY_SEGMENT) + goto found; + + list_for_each_entry(entry, &np->ep_list, list) { + if (dev_id >= entry->start_devid && dev_id <= entry->end_devid) + goto found; + } + } + + return -ENODEV; + +found: + return acpi_iommu_fwspec_init(aliased_dev, (domain << 16) + dev_id, np->fwnode); +} + +/* + * iovt_iommu_configure_id - Set-up IOMMU configuration for a device. + * + * @dev: device to configure + * @id_in: optional input id const value pointer + * + * Returns: 0 on success, <0 on failure + */ +int iovt_iommu_configure_id(struct device *dev, const u32 *id_in) +{ + if (!dev_is_pci(dev)) + return -ENODEV; + + return pci_for_each_dma_alias(to_pci_dev(dev), iovt_pci_iommu_init, dev); +} diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0b17a7e51956..96b8b0dfe339 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/acpi.h> #include <linux/acpi_iort.h> +#include <linux/acpi_iovt.h> #include <linux/acpi_rimt.h> #include <linux/acpi_viot.h> #include <linux/iommu.h> @@ -1626,6 +1627,8 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in) if (err && err != -EPROBE_DEFER) err = rimt_iommu_configure_id(dev, id_in); if (err && err != -EPROBE_DEFER) + err = iovt_iommu_configure_id(dev, id_in); + if (err && err != -EPROBE_DEFER) err = viot_iommu_configure(dev); mutex_unlock(&iommu_probe_device_lock); diff --git a/drivers/soc/loongson/loongson2_guts.c b/drivers/soc/loongson/loongson2_guts.c index 16913c3ef65c..a2f2c1e119fe 100644 --- a/drivers/soc/loongson/loongson2_guts.c +++ b/drivers/soc/loongson/loongson2_guts.c @@ -92,8 +92,8 @@ static u32 loongson2_guts_get_svr(void) static int loongson2_guts_probe(struct platform_device *pdev) { - struct device_node *root, *np = pdev->dev.of_node; struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; const struct loongson2_soc_die_attr *soc_die; const char *machine; u32 svr; @@ -109,11 +109,8 @@ static int loongson2_guts_probe(struct platform_device *pdev) if (IS_ERR(guts->regs)) return PTR_ERR(guts->regs); - /* Register soc device */ - root = of_find_node_by_path("/"); - if (of_property_read_string(root, "model", &machine)) - of_property_read_string_index(root, "compatible", 0, &machine); - of_node_put(root); + if (of_property_read_string(of_root, "model", &machine)) + of_property_read_string_index(of_root, "compatible", 0, &machine); if (machine) { soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL); if (!soc_dev_attr.machine) diff --git a/drivers/soc/loongson/loongson2_pm.c b/drivers/soc/loongson/loongson2_pm.c index b8e5e1e3528a..1e2c897d055b 100644 --- a/drivers/soc/loongson/loongson2_pm.c +++ b/drivers/soc/loongson/loongson2_pm.c @@ -175,7 +175,7 @@ static int loongson2_pm_probe(struct platform_device *pdev) return irq; if (!device_property_read_u64(dev, "loongson,suspend-address", &suspend_addr)) - loongson_sysconf.suspend_addr = (u64)phys_to_virt(suspend_addr); + loongson_sysconf.suspend_addr = (unsigned long)phys_to_virt(suspend_addr); else dev_err(dev, "No loongson,suspend-address, could not support S3!\n"); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d7f1f3d05390..9d3f039ebd94 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1637,6 +1637,7 @@ static inline int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, #endif void acpi_arch_init(void); +void acpi_arch_late_init(void); #ifdef CONFIG_ACPI_PCC void acpi_init_pcc(void); diff --git a/include/linux/acpi_iovt.h b/include/linux/acpi_iovt.h new file mode 100644 index 000000000000..663b4c679bc5 --- /dev/null +++ b/include/linux/acpi_iovt.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ACPI_IOVT_H__ +#define __ACPI_IOVT_H__ + +#ifdef CONFIG_ACPI_IOVT +int iovt_iommu_configure_id(struct device *dev, const u32 *id_in); +#else +static inline int iovt_iommu_configure_id(struct device *dev, const u32 *id_in) +{ return -ENODEV; } +#endif + +#endif /* __ACPI_IOVT_H__ */ |
