Commit a362ade8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'loongarch-6.11' of...

Merge tag 'loongarch-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson

Pull LoongArch updates from Huacai Chen:

 - Define __ARCH_WANT_NEW_STAT in unistd.h

 - Always enumerate MADT and setup logical-physical CPU mapping

 - Add irq_work support via self IPIs

 - Add RANDOMIZE_KSTACK_OFFSET support

 - Add ARCH_HAS_PTE_DEVMAP support

 - Add ARCH_HAS_DEBUG_VM_PGTABLE support

 - Add writecombine support for DMW-based ioremap()

 - Add architectural preparation for CPUFreq

 - Add ACPI standard hardware register based S3 support

 - Add support for relocating the kernel with RELR relocation

 - Some bug fixes and other small changes

* tag 'loongarch-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
  LoongArch: Make the users of larch_insn_gen_break() constant
  LoongArch: Check TIF_LOAD_WATCH to enable user space watchpoint
  LoongArch: Use rustc option -Zdirect-access-external-data
  LoongArch: Add support for relocating the kernel with RELR relocation
  LoongArch: Remove a redundant checking in relocator
  LoongArch: Use correct API to map cmdline in relocate_kernel()
  LoongArch: Automatically disable KASLR for hibernation
  LoongArch: Add ACPI standard hardware register based S3 support
  LoongArch: Add architectural preparation for CPUFreq
  LoongArch: Add writecombine support for DMW-based ioremap()
  LoongArch: Add ARCH_HAS_DEBUG_VM_PGTABLE support
  LoongArch: Add ARCH_HAS_PTE_DEVMAP support
  LoongArch: Add RANDOMIZE_KSTACK_OFFSET support
  LoongArch: Add irq_work support via self IPIs
  LoongArch: Always enumerate MADT and setup logical-physical CPU mapping
  LoongArch: Define __ARCH_WANT_NEW_STAT in unistd.h
parents 539fbb91 998b17d4
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
| arm64: | ok | | arm64: | ok |
| csky: | TODO | | csky: | TODO |
| hexagon: | TODO | | hexagon: | TODO |
| loongarch: | TODO | | loongarch: | ok |
| m68k: | TODO | | m68k: | TODO |
| microblaze: | TODO | | microblaze: | TODO |
| mips: | TODO | | mips: | TODO |
......
...@@ -16,12 +16,14 @@ config LOONGARCH ...@@ -16,12 +16,14 @@ config LOONGARCH
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
select ARCH_HAS_CPU_FINALIZE_INIT select ARCH_HAS_CPU_FINALIZE_INIT
select ARCH_HAS_CURRENT_STACK_POINTER select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_FAST_MULTIPLIER select ARCH_HAS_FAST_MULTIPLIER
select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_KCOV select ARCH_HAS_KCOV
select ARCH_HAS_KERNEL_FPU_SUPPORT if CPU_HAS_FPU select ARCH_HAS_KERNEL_FPU_SUPPORT if CPU_HAS_FPU
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
select ARCH_HAS_PTE_DEVMAP
select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_INLINE_READ_LOCK if !PREEMPTION select ARCH_INLINE_READ_LOCK if !PREEMPTION
...@@ -106,6 +108,7 @@ config LOONGARCH ...@@ -106,6 +108,7 @@ config LOONGARCH
select HAVE_ARCH_KFENCE select HAVE_ARCH_KFENCE
select HAVE_ARCH_KGDB if PERF_EVENTS select HAVE_ARCH_KGDB if PERF_EVENTS
select HAVE_ARCH_MMAP_RND_BITS if MMU select HAVE_ARCH_MMAP_RND_BITS if MMU
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
select HAVE_ARCH_SECCOMP select HAVE_ARCH_SECCOMP
select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
...@@ -607,6 +610,7 @@ config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION ...@@ -607,6 +610,7 @@ config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
config RELOCATABLE config RELOCATABLE
bool "Relocatable kernel" bool "Relocatable kernel"
select ARCH_HAS_RELR
help help
This builds the kernel as a Position Independent Executable (PIE), This builds the kernel as a Position Independent Executable (PIE),
which retains all relocation metadata required, so as to relocate which retains all relocation metadata required, so as to relocate
...@@ -710,6 +714,7 @@ config ARCH_HIBERNATION_POSSIBLE ...@@ -710,6 +714,7 @@ config ARCH_HIBERNATION_POSSIBLE
source "kernel/power/Kconfig" source "kernel/power/Kconfig"
source "drivers/acpi/Kconfig" source "drivers/acpi/Kconfig"
source "drivers/cpufreq/Kconfig"
endmenu endmenu
......
...@@ -105,7 +105,8 @@ KBUILD_CFLAGS += -fno-jump-tables ...@@ -105,7 +105,8 @@ KBUILD_CFLAGS += -fno-jump-tables
endif endif
KBUILD_RUSTFLAGS += --target=loongarch64-unknown-none-softfloat KBUILD_RUSTFLAGS += --target=loongarch64-unknown-none-softfloat
KBUILD_RUSTFLAGS_MODULE += -Crelocation-model=pic KBUILD_RUSTFLAGS_KERNEL += -Zdirect-access-external-data=yes
KBUILD_RUSTFLAGS_MODULE += -Zdirect-access-external-data=no
ifeq ($(CONFIG_RELOCATABLE),y) ifeq ($(CONFIG_RELOCATABLE),y)
KBUILD_CFLAGS_KERNEL += -fPIE KBUILD_CFLAGS_KERNEL += -fPIE
......
...@@ -37,6 +37,10 @@ extern unsigned long vm_map_base; ...@@ -37,6 +37,10 @@ extern unsigned long vm_map_base;
#define UNCACHE_BASE CSR_DMW0_BASE #define UNCACHE_BASE CSR_DMW0_BASE
#endif #endif
#ifndef WRITECOMBINE_BASE
#define WRITECOMBINE_BASE CSR_DMW2_BASE
#endif
#define DMW_PABITS 48 #define DMW_PABITS 48
#define TO_PHYS_MASK ((1ULL << DMW_PABITS) - 1) #define TO_PHYS_MASK ((1ULL << DMW_PABITS) - 1)
......
...@@ -609,6 +609,7 @@ ...@@ -609,6 +609,7 @@
lu32i.d \reg, 0 lu32i.d \reg, 0
lu52i.d \reg, \reg, 0 lu52i.d \reg, \reg, 0
.pushsection ".la_abs", "aw", %progbits .pushsection ".la_abs", "aw", %progbits
.p2align 3
.dword 766b .dword 766b
.dword \sym .dword \sym
.popsection .popsection
......
...@@ -12,11 +12,12 @@ ...@@ -12,11 +12,12 @@
extern void ack_bad_irq(unsigned int irq); extern void ack_bad_irq(unsigned int irq);
#define ack_bad_irq ack_bad_irq #define ack_bad_irq ack_bad_irq
#define NR_IPI 2 #define NR_IPI 3
enum ipi_msg_type { enum ipi_msg_type {
IPI_RESCHEDULE, IPI_RESCHEDULE,
IPI_CALL_FUNCTION, IPI_CALL_FUNCTION,
IPI_IRQ_WORK,
}; };
typedef struct { typedef struct {
......
...@@ -532,6 +532,9 @@ static inline void emit_##NAME(union loongarch_instruction *insn, \ ...@@ -532,6 +532,9 @@ static inline void emit_##NAME(union loongarch_instruction *insn, \
DEF_EMIT_REG0I15_FORMAT(break, break_op) DEF_EMIT_REG0I15_FORMAT(break, break_op)
/* like emit_break(imm) but returns a constant expression */
#define __emit_break(imm) ((u32)((imm) | (break_op << 15)))
#define DEF_EMIT_REG0I26_FORMAT(NAME, OP) \ #define DEF_EMIT_REG0I26_FORMAT(NAME, OP) \
static inline void emit_##NAME(union loongarch_instruction *insn, \ static inline void emit_##NAME(union loongarch_instruction *insn, \
int offset) \ int offset) \
......
...@@ -25,10 +25,16 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size); ...@@ -25,10 +25,16 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size);
static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size, static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
unsigned long prot_val) unsigned long prot_val)
{ {
if (prot_val & _CACHE_CC) switch (prot_val & _CACHE_MASK) {
case _CACHE_CC:
return (void __iomem *)(unsigned long)(CACHE_BASE + offset); return (void __iomem *)(unsigned long)(CACHE_BASE + offset);
else case _CACHE_SUC:
return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset); return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset);
case _CACHE_WUC:
return (void __iomem *)(unsigned long)(WRITECOMBINE_BASE + offset);
default:
return NULL;
}
} }
#define ioremap(offset, size) \ #define ioremap(offset, size) \
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_LOONGARCH_IRQ_WORK_H
#define _ASM_LOONGARCH_IRQ_WORK_H
static inline bool arch_irq_work_has_interrupt(void)
{
return IS_ENABLED(CONFIG_SMP);
}
#endif /* _ASM_LOONGARCH_IRQ_WORK_H */
...@@ -878,7 +878,7 @@ ...@@ -878,7 +878,7 @@
#define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ #define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */
#define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ #define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */
/* Direct Map window 0/1 */ /* Direct Map window 0/1/2/3 */
#define CSR_DMW0_PLV0 _CONST64_(1 << 0) #define CSR_DMW0_PLV0 _CONST64_(1 << 0)
#define CSR_DMW0_VSEG _CONST64_(0x8000) #define CSR_DMW0_VSEG _CONST64_(0x8000)
#define CSR_DMW0_BASE (CSR_DMW0_VSEG << DMW_PABITS) #define CSR_DMW0_BASE (CSR_DMW0_VSEG << DMW_PABITS)
...@@ -890,6 +890,14 @@ ...@@ -890,6 +890,14 @@
#define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS) #define CSR_DMW1_BASE (CSR_DMW1_VSEG << DMW_PABITS)
#define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0) #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0)
#define CSR_DMW2_PLV0 _CONST64_(1 << 0)
#define CSR_DMW2_MAT _CONST64_(2 << 4)
#define CSR_DMW2_VSEG _CONST64_(0xa000)
#define CSR_DMW2_BASE (CSR_DMW2_VSEG << DMW_PABITS)
#define CSR_DMW2_INIT (CSR_DMW2_BASE | CSR_DMW2_MAT | CSR_DMW2_PLV0)
#define CSR_DMW3_INIT 0x0
/* Performance Counter registers */ /* Performance Counter registers */
#define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ #define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */
#define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ #define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */
...@@ -1054,11 +1062,14 @@ ...@@ -1054,11 +1062,14 @@
#define LOONGARCH_IOCSR_NODECNT 0x408 #define LOONGARCH_IOCSR_NODECNT 0x408
#define LOONGARCH_IOCSR_MISC_FUNC 0x420 #define LOONGARCH_IOCSR_MISC_FUNC 0x420
#define IOCSR_MISC_FUNC_SOFT_INT BIT_ULL(10)
#define IOCSR_MISC_FUNC_TIMER_RESET BIT_ULL(21) #define IOCSR_MISC_FUNC_TIMER_RESET BIT_ULL(21)
#define IOCSR_MISC_FUNC_EXT_IOI_EN BIT_ULL(48) #define IOCSR_MISC_FUNC_EXT_IOI_EN BIT_ULL(48)
#define LOONGARCH_IOCSR_CPUTEMP 0x428 #define LOONGARCH_IOCSR_CPUTEMP 0x428
#define LOONGARCH_IOCSR_SMCMBX 0x51c
/* PerCore CSR, only accessible by local cores */ /* PerCore CSR, only accessible by local cores */
#define LOONGARCH_IOCSR_IPI_STATUS 0x1000 #define LOONGARCH_IOCSR_IPI_STATUS 0x1000
#define LOONGARCH_IOCSR_IPI_EN 0x1004 #define LOONGARCH_IOCSR_IPI_EN 0x1004
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define _PAGE_PFN_SHIFT 12 #define _PAGE_PFN_SHIFT 12
#define _PAGE_SWP_EXCLUSIVE_SHIFT 23 #define _PAGE_SWP_EXCLUSIVE_SHIFT 23
#define _PAGE_PFN_END_SHIFT 48 #define _PAGE_PFN_END_SHIFT 48
#define _PAGE_DEVMAP_SHIFT 59
#define _PAGE_PRESENT_INVALID_SHIFT 60 #define _PAGE_PRESENT_INVALID_SHIFT 60
#define _PAGE_NO_READ_SHIFT 61 #define _PAGE_NO_READ_SHIFT 61
#define _PAGE_NO_EXEC_SHIFT 62 #define _PAGE_NO_EXEC_SHIFT 62
...@@ -35,6 +36,7 @@ ...@@ -35,6 +36,7 @@
#define _PAGE_MODIFIED (_ULCAST_(1) << _PAGE_MODIFIED_SHIFT) #define _PAGE_MODIFIED (_ULCAST_(1) << _PAGE_MODIFIED_SHIFT)
#define _PAGE_PROTNONE (_ULCAST_(1) << _PAGE_PROTNONE_SHIFT) #define _PAGE_PROTNONE (_ULCAST_(1) << _PAGE_PROTNONE_SHIFT)
#define _PAGE_SPECIAL (_ULCAST_(1) << _PAGE_SPECIAL_SHIFT) #define _PAGE_SPECIAL (_ULCAST_(1) << _PAGE_SPECIAL_SHIFT)
#define _PAGE_DEVMAP (_ULCAST_(1) << _PAGE_DEVMAP_SHIFT)
/* We borrow bit 23 to store the exclusive marker in swap PTEs. */ /* We borrow bit 23 to store the exclusive marker in swap PTEs. */
#define _PAGE_SWP_EXCLUSIVE (_ULCAST_(1) << _PAGE_SWP_EXCLUSIVE_SHIFT) #define _PAGE_SWP_EXCLUSIVE (_ULCAST_(1) << _PAGE_SWP_EXCLUSIVE_SHIFT)
...@@ -74,8 +76,8 @@ ...@@ -74,8 +76,8 @@
#define __READABLE (_PAGE_VALID) #define __READABLE (_PAGE_VALID)
#define __WRITEABLE (_PAGE_DIRTY | _PAGE_WRITE) #define __WRITEABLE (_PAGE_DIRTY | _PAGE_WRITE)
#define _PAGE_CHG_MASK (_PAGE_MODIFIED | _PAGE_SPECIAL | _PFN_MASK | _CACHE_MASK | _PAGE_PLV) #define _PAGE_CHG_MASK (_PAGE_MODIFIED | _PAGE_SPECIAL | _PAGE_DEVMAP | _PFN_MASK | _CACHE_MASK | _PAGE_PLV)
#define _HPAGE_CHG_MASK (_PAGE_MODIFIED | _PAGE_SPECIAL | _PFN_MASK | _CACHE_MASK | _PAGE_PLV | _PAGE_HUGE) #define _HPAGE_CHG_MASK (_PAGE_MODIFIED | _PAGE_SPECIAL | _PAGE_DEVMAP | _PFN_MASK | _CACHE_MASK | _PAGE_PLV | _PAGE_HUGE)
#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_NO_READ | \ #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_NO_READ | \
_PAGE_USER | _CACHE_CC) _PAGE_USER | _CACHE_CC)
......
...@@ -424,6 +424,9 @@ static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; ...@@ -424,6 +424,9 @@ static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL;
static inline pte_t pte_mkspecial(pte_t pte) { pte_val(pte) |= _PAGE_SPECIAL; return pte; } static inline pte_t pte_mkspecial(pte_t pte) { pte_val(pte) |= _PAGE_SPECIAL; return pte; }
#endif /* CONFIG_ARCH_HAS_PTE_SPECIAL */ #endif /* CONFIG_ARCH_HAS_PTE_SPECIAL */
static inline int pte_devmap(pte_t pte) { return !!(pte_val(pte) & _PAGE_DEVMAP); }
static inline pte_t pte_mkdevmap(pte_t pte) { pte_val(pte) |= _PAGE_DEVMAP; return pte; }
#define pte_accessible pte_accessible #define pte_accessible pte_accessible
static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a) static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
{ {
...@@ -558,6 +561,17 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd) ...@@ -558,6 +561,17 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
return pmd; return pmd;
} }
static inline int pmd_devmap(pmd_t pmd)
{
return !!(pmd_val(pmd) & _PAGE_DEVMAP);
}
static inline pmd_t pmd_mkdevmap(pmd_t pmd)
{
pmd_val(pmd) |= _PAGE_DEVMAP;
return pmd;
}
static inline struct page *pmd_page(pmd_t pmd) static inline struct page *pmd_page(pmd_t pmd)
{ {
if (pmd_trans_huge(pmd)) if (pmd_trans_huge(pmd))
...@@ -613,6 +627,11 @@ static inline long pmd_protnone(pmd_t pmd) ...@@ -613,6 +627,11 @@ static inline long pmd_protnone(pmd_t pmd)
#define pmd_leaf(pmd) ((pmd_val(pmd) & _PAGE_HUGE) != 0) #define pmd_leaf(pmd) ((pmd_val(pmd) & _PAGE_HUGE) != 0)
#define pud_leaf(pud) ((pud_val(pud) & _PAGE_HUGE) != 0) #define pud_leaf(pud) ((pud_val(pud) & _PAGE_HUGE) != 0)
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define pud_devmap(pud) (0)
#define pgd_devmap(pgd) (0)
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
/* /*
* We provide our own get_unmapped area to cope with the virtual aliasing * We provide our own get_unmapped area to cope with the virtual aliasing
* constraints placed on us by the cache architecture. * constraints placed on us by the cache architecture.
......
...@@ -34,6 +34,11 @@ extern long __la_abs_end; ...@@ -34,6 +34,11 @@ extern long __la_abs_end;
extern long __rela_dyn_begin; extern long __rela_dyn_begin;
extern long __rela_dyn_end; extern long __rela_dyn_end;
#ifdef CONFIG_RELR
extern long __relr_dyn_begin;
extern long __relr_dyn_end;
#endif
extern unsigned long __init relocate_kernel(void); extern unsigned long __init relocate_kernel(void);
#endif #endif
......
...@@ -69,9 +69,11 @@ extern int __cpu_logical_map[NR_CPUS]; ...@@ -69,9 +69,11 @@ extern int __cpu_logical_map[NR_CPUS];
#define ACTION_BOOT_CPU 0 #define ACTION_BOOT_CPU 0
#define ACTION_RESCHEDULE 1 #define ACTION_RESCHEDULE 1
#define ACTION_CALL_FUNCTION 2 #define ACTION_CALL_FUNCTION 2
#define ACTION_IRQ_WORK 3
#define SMP_BOOT_CPU BIT(ACTION_BOOT_CPU) #define SMP_BOOT_CPU BIT(ACTION_BOOT_CPU)
#define SMP_RESCHEDULE BIT(ACTION_RESCHEDULE) #define SMP_RESCHEDULE BIT(ACTION_RESCHEDULE)
#define SMP_CALL_FUNCTION BIT(ACTION_CALL_FUNCTION) #define SMP_CALL_FUNCTION BIT(ACTION_CALL_FUNCTION)
#define SMP_IRQ_WORK BIT(ACTION_IRQ_WORK)
struct secondary_data { struct secondary_data {
unsigned long stack; unsigned long stack;
......
...@@ -38,6 +38,17 @@ ...@@ -38,6 +38,17 @@
cfi_restore \reg \offset \docfi cfi_restore \reg \offset \docfi
.endm .endm
.macro SETUP_DMWINS temp
li.d \temp, CSR_DMW0_INIT # WUC, PLV0, 0x8000 xxxx xxxx xxxx
csrwr \temp, LOONGARCH_CSR_DMWIN0
li.d \temp, CSR_DMW1_INIT # CAC, PLV0, 0x9000 xxxx xxxx xxxx
csrwr \temp, LOONGARCH_CSR_DMWIN1
li.d \temp, CSR_DMW2_INIT # WUC, PLV0, 0xa000 xxxx xxxx xxxx
csrwr \temp, LOONGARCH_CSR_DMWIN2
li.d \temp, CSR_DMW3_INIT # 0x0, unused
csrwr \temp, LOONGARCH_CSR_DMWIN3
.endm
/* Jump to the runtime virtual address. */ /* Jump to the runtime virtual address. */
.macro JUMP_VIRT_ADDR temp1 temp2 .macro JUMP_VIRT_ADDR temp1 temp2
li.d \temp1, CACHE_BASE li.d \temp1, CACHE_BASE
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <uapi/asm/unistd.h> #include <uapi/asm/unistd.h>
#define __ARCH_WANT_NEW_STAT
#define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_CLONE
#define NR_syscalls (__NR_syscalls) #define NR_syscalls (__NR_syscalls)
...@@ -9,10 +9,10 @@ typedef u32 uprobe_opcode_t; ...@@ -9,10 +9,10 @@ typedef u32 uprobe_opcode_t;
#define MAX_UINSN_BYTES 8 #define MAX_UINSN_BYTES 8
#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES #define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES
#define UPROBE_SWBP_INSN larch_insn_gen_break(BRK_UPROBE_BP) #define UPROBE_SWBP_INSN __emit_break(BRK_UPROBE_BP)
#define UPROBE_SWBP_INSN_SIZE LOONGARCH_INSN_SIZE #define UPROBE_SWBP_INSN_SIZE LOONGARCH_INSN_SIZE
#define UPROBE_XOLBP_INSN larch_insn_gen_break(BRK_UPROBE_XOLBP) #define UPROBE_XOLBP_INSN __emit_break(BRK_UPROBE_XOLBP)
struct arch_uprobe { struct arch_uprobe {
unsigned long resume_era; unsigned long resume_era;
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# No special ABIs on loongarch so far syscall_abis_64 += newstat
syscall_abis_64 +=
...@@ -57,15 +57,22 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) ...@@ -57,15 +57,22 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
return ioremap_cache(phys, size); return ioremap_cache(phys, size);
} }
static int cpu_enumerated = 0;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static int set_processor_mask(u32 id, u32 flags) static int set_processor_mask(u32 id, u32 flags)
{ {
int nr_cpus;
int cpu, cpuid = id; int cpu, cpuid = id;
if (num_processors >= nr_cpu_ids) { if (!cpu_enumerated)
pr_warn(PREFIX "nr_cpus/possible_cpus limit of %i reached." nr_cpus = NR_CPUS;
" processor 0x%x ignored.\n", nr_cpu_ids, cpuid); else
nr_cpus = nr_cpu_ids;
if (num_processors >= nr_cpus) {
pr_warn(PREFIX "nr_cpus limit of %i reached."
" processor 0x%x ignored.\n", nr_cpus, cpuid);
return -ENODEV; return -ENODEV;
...@@ -73,11 +80,13 @@ static int set_processor_mask(u32 id, u32 flags) ...@@ -73,11 +80,13 @@ static int set_processor_mask(u32 id, u32 flags)
if (cpuid == loongson_sysconf.boot_cpu_id) if (cpuid == loongson_sysconf.boot_cpu_id)
cpu = 0; cpu = 0;
else else
cpu = cpumask_next_zero(-1, cpu_present_mask); cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS);
if (!cpu_enumerated)
set_cpu_possible(cpu, true);
if (flags & ACPI_MADT_ENABLED) { if (flags & ACPI_MADT_ENABLED) {
num_processors++; num_processors++;
set_cpu_possible(cpu, true);
set_cpu_present(cpu, true); set_cpu_present(cpu, true);
__cpu_number_map[cpuid] = cpu; __cpu_number_map[cpuid] = cpu;
__cpu_logical_map[cpu] = cpuid; __cpu_logical_map[cpu] = cpuid;
...@@ -138,6 +147,7 @@ static void __init acpi_process_madt(void) ...@@ -138,6 +147,7 @@ static void __init acpi_process_madt(void)
acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC,
acpi_parse_eio_master, MAX_IO_PICS); acpi_parse_eio_master, MAX_IO_PICS);
cpu_enumerated = 1;
loongson_sysconf.nr_cpus = num_processors; loongson_sysconf.nr_cpus = num_processors;
} }
......
...@@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize); ...@@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize);
SYM_CODE_START(kernel_entry) # kernel entry point SYM_CODE_START(kernel_entry) # kernel entry point
/* Config direct window and set PG */ /* Config direct window and set PG */
li.d t0, CSR_DMW0_INIT # UC, PLV0, 0x8000 xxxx xxxx xxxx SETUP_DMWINS t0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0, 0x9000 xxxx xxxx xxxx
csrwr t0, LOONGARCH_CSR_DMWIN1
JUMP_VIRT_ADDR t0, t1 JUMP_VIRT_ADDR t0, t1
/* Enable PG */ /* Enable PG */
...@@ -124,11 +120,8 @@ SYM_CODE_END(kernel_entry) ...@@ -124,11 +120,8 @@ SYM_CODE_END(kernel_entry)
* function after setting up the stack and tp registers. * function after setting up the stack and tp registers.
*/ */
SYM_CODE_START(smpboot_entry) SYM_CODE_START(smpboot_entry)
li.d t0, CSR_DMW0_INIT # UC, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
SETUP_DMWINS t0
JUMP_VIRT_ADDR t0, t1 JUMP_VIRT_ADDR t0, t1
#ifdef CONFIG_PAGE_SIZE_4KB #ifdef CONFIG_PAGE_SIZE_4KB
......
...@@ -221,7 +221,7 @@ static int hw_breakpoint_control(struct perf_event *bp, ...@@ -221,7 +221,7 @@ static int hw_breakpoint_control(struct perf_event *bp,
} }
enable = csr_read64(LOONGARCH_CSR_CRMD); enable = csr_read64(LOONGARCH_CSR_CRMD);
csr_write64(CSR_CRMD_WE | enable, LOONGARCH_CSR_CRMD); csr_write64(CSR_CRMD_WE | enable, LOONGARCH_CSR_CRMD);
if (bp->hw.target) if (bp->hw.target && test_tsk_thread_flag(bp->hw.target, TIF_LOAD_WATCH))
regs->csr_prmd |= CSR_PRMD_PWE; regs->csr_prmd |= CSR_PRMD_PWE;
break; break;
case HW_BREAKPOINT_UNINSTALL: case HW_BREAKPOINT_UNINSTALL:
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#include <linux/preempt.h> #include <linux/preempt.h>
#include <asm/break.h> #include <asm/break.h>
#define KPROBE_BP_INSN larch_insn_gen_break(BRK_KPROBE_BP) #define KPROBE_BP_INSN __emit_break(BRK_KPROBE_BP)
#define KPROBE_SSTEPBP_INSN larch_insn_gen_break(BRK_KPROBE_SSTEPBP) #define KPROBE_SSTEPBP_INSN __emit_break(BRK_KPROBE_SSTEPBP)
DEFINE_PER_CPU(struct kprobe *, current_kprobe); DEFINE_PER_CPU(struct kprobe *, current_kprobe);
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq_work.h>
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/kvm_para.h> #include <linux/kvm_para.h>
#include <linux/reboot.h> #include <linux/reboot.h>
...@@ -128,6 +129,11 @@ static irqreturn_t pv_ipi_interrupt(int irq, void *dev) ...@@ -128,6 +129,11 @@ static irqreturn_t pv_ipi_interrupt(int irq, void *dev)
info->ipi_irqs[IPI_CALL_FUNCTION]++; info->ipi_irqs[IPI_CALL_FUNCTION]++;
} }
if (action & SMP_IRQ_WORK) {
irq_work_run();
info->ipi_irqs[IPI_IRQ_WORK]++;
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -589,6 +589,7 @@ static int ptrace_hbp_set_ctrl(unsigned int note_type, ...@@ -589,6 +589,7 @@ static int ptrace_hbp_set_ctrl(unsigned int note_type,
struct perf_event *bp; struct perf_event *bp;
struct perf_event_attr attr; struct perf_event_attr attr;
struct arch_hw_breakpoint_ctrl ctrl; struct arch_hw_breakpoint_ctrl ctrl;
struct thread_info *ti = task_thread_info(tsk);
bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
if (IS_ERR(bp)) if (IS_ERR(bp))
...@@ -613,8 +614,10 @@ static int ptrace_hbp_set_ctrl(unsigned int note_type, ...@@ -613,8 +614,10 @@ static int ptrace_hbp_set_ctrl(unsigned int note_type,
if (err) if (err)
return err; return err;
attr.disabled = 0; attr.disabled = 0;
set_ti_thread_flag(ti, TIF_LOAD_WATCH);
} else { } else {
attr.disabled = 1; attr.disabled = 1;
clear_ti_thread_flag(ti, TIF_LOAD_WATCH);
} }
return modify_user_hw_breakpoint(bp, &attr); return modify_user_hw_breakpoint(bp, &attr);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/early_ioremap.h> #include <asm/early_ioremap.h>
#include <asm/inst.h> #include <asm/inst.h>
#include <asm/io.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/setup.h> #include <asm/setup.h>
...@@ -34,11 +35,27 @@ static inline void __init relocate_relative(void) ...@@ -34,11 +35,27 @@ static inline void __init relocate_relative(void)
if (rela->r_info != R_LARCH_RELATIVE) if (rela->r_info != R_LARCH_RELATIVE)
continue; continue;
if (relocated_addr >= VMLINUX_LOAD_ADDRESS)
relocated_addr = (Elf64_Addr)RELOCATED(relocated_addr); relocated_addr = (Elf64_Addr)RELOCATED(relocated_addr);
*(Elf64_Addr *)RELOCATED(addr) = relocated_addr; *(Elf64_Addr *)RELOCATED(addr) = relocated_addr;
} }
#ifdef CONFIG_RELR
u64 *addr = NULL;
u64 *relr = (u64 *)&__relr_dyn_begin;
u64 *relr_end = (u64 *)&__relr_dyn_end;
for ( ; relr < relr_end; relr++) {
if ((*relr & 1) == 0) {
addr = (u64 *)(*relr + reloc_offset);
*addr++ += reloc_offset;
} else {
for (u64 *p = addr, r = *relr >> 1; r; p++, r >>= 1)
if (r & 1)
*p += reloc_offset;
addr += 63;
}
}
#endif
} }
static inline void __init relocate_absolute(long random_offset) static inline void __init relocate_absolute(long random_offset)
...@@ -123,6 +140,32 @@ static inline __init bool kaslr_disabled(void) ...@@ -123,6 +140,32 @@ static inline __init bool kaslr_disabled(void)
if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' '))
return true; return true;
#ifdef CONFIG_HIBERNATION
str = strstr(builtin_cmdline, "nohibernate");
if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' '))
return false;
str = strstr(boot_command_line, "nohibernate");
if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' '))
return false;
str = strstr(builtin_cmdline, "noresume");
if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' '))
return false;
str = strstr(boot_command_line, "noresume");
if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' '))
return false;
str = strstr(builtin_cmdline, "resume=");
if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' '))
return true;
str = strstr(boot_command_line, "resume=");
if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' '))
return true;
#endif
return false; return false;
} }
...@@ -170,7 +213,7 @@ unsigned long __init relocate_kernel(void) ...@@ -170,7 +213,7 @@ unsigned long __init relocate_kernel(void)
unsigned long kernel_length; unsigned long kernel_length;
unsigned long random_offset = 0; unsigned long random_offset = 0;
void *location_new = _text; /* Default to original kernel start */ void *location_new = _text; /* Default to original kernel start */
char *cmdline = early_ioremap(fw_arg1, COMMAND_LINE_SIZE); /* Boot command line is passed in fw_arg1 */ char *cmdline = early_memremap_ro(fw_arg1, COMMAND_LINE_SIZE); /* Boot command line is passed in fw_arg1 */
strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE); strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE);
...@@ -182,6 +225,7 @@ unsigned long __init relocate_kernel(void) ...@@ -182,6 +225,7 @@ unsigned long __init relocate_kernel(void)
random_offset = (unsigned long)location_new - (unsigned long)(_text); random_offset = (unsigned long)location_new - (unsigned long)(_text);
#endif #endif
reloc_offset = (unsigned long)_text - VMLINUX_LOAD_ADDRESS; reloc_offset = (unsigned long)_text - VMLINUX_LOAD_ADDRESS;
early_memunmap(cmdline, COMMAND_LINE_SIZE);
if (random_offset) { if (random_offset) {
kernel_length = (long)(_end) - (long)(_text); kernel_length = (long)(_end) - (long)(_text);
......
...@@ -576,8 +576,10 @@ static void __init prefill_possible_map(void) ...@@ -576,8 +576,10 @@ static void __init prefill_possible_map(void)
for (i = 0; i < possible; i++) for (i = 0; i < possible; i++)
set_cpu_possible(i, true); set_cpu_possible(i, true);
for (; i < NR_CPUS; i++) for (; i < NR_CPUS; i++) {
set_cpu_present(i, false);
set_cpu_possible(i, false); set_cpu_possible(i, false);
}
set_nr_cpu_ids(possible); set_nr_cpu_ids(possible);
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq_work.h>
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/smp.h> #include <linux/smp.h>
...@@ -70,6 +71,7 @@ static DEFINE_PER_CPU(int, cpu_state); ...@@ -70,6 +71,7 @@ static DEFINE_PER_CPU(int, cpu_state);
static const char *ipi_types[NR_IPI] __tracepoint_string = { static const char *ipi_types[NR_IPI] __tracepoint_string = {
[IPI_RESCHEDULE] = "Rescheduling interrupts", [IPI_RESCHEDULE] = "Rescheduling interrupts",
[IPI_CALL_FUNCTION] = "Function call interrupts", [IPI_CALL_FUNCTION] = "Function call interrupts",
[IPI_IRQ_WORK] = "IRQ work interrupts",
}; };
void show_ipi_list(struct seq_file *p, int prec) void show_ipi_list(struct seq_file *p, int prec)
...@@ -217,6 +219,13 @@ void arch_smp_send_reschedule(int cpu) ...@@ -217,6 +219,13 @@ void arch_smp_send_reschedule(int cpu)
} }
EXPORT_SYMBOL_GPL(arch_smp_send_reschedule); EXPORT_SYMBOL_GPL(arch_smp_send_reschedule);
#ifdef CONFIG_IRQ_WORK
void arch_irq_work_raise(void)
{
mp_ops.send_ipi_single(smp_processor_id(), ACTION_IRQ_WORK);
}
#endif
static irqreturn_t loongson_ipi_interrupt(int irq, void *dev) static irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
{ {
unsigned int action; unsigned int action;
...@@ -234,6 +243,11 @@ static irqreturn_t loongson_ipi_interrupt(int irq, void *dev) ...@@ -234,6 +243,11 @@ static irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
per_cpu(irq_stat, cpu).ipi_irqs[IPI_CALL_FUNCTION]++; per_cpu(irq_stat, cpu).ipi_irqs[IPI_CALL_FUNCTION]++;
} }
if (action & SMP_IRQ_WORK) {
irq_work_run();
per_cpu(irq_stat, cpu).ipi_irqs[IPI_IRQ_WORK]++;
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -271,11 +285,10 @@ static void __init fdt_smp_setup(void) ...@@ -271,11 +285,10 @@ static void __init fdt_smp_setup(void)
if (cpuid >= nr_cpu_ids) if (cpuid >= nr_cpu_ids)
continue; continue;
if (cpuid == loongson_sysconf.boot_cpu_id) { if (cpuid == loongson_sysconf.boot_cpu_id)
cpu = 0; cpu = 0;
} else { else
cpu = cpumask_next_zero(-1, cpu_present_mask); cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS);
}
num_processors++; num_processors++;
set_cpu_possible(cpu, true); set_cpu_possible(cpu, true);
......
...@@ -9,11 +9,14 @@ ...@@ -9,11 +9,14 @@
#include <linux/entry-common.h> #include <linux/entry-common.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/objtool.h>
#include <linux/randomize_kstack.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/exception.h> #include <asm/exception.h>
#include <asm/loongarch.h>
#include <asm/signal.h> #include <asm/signal.h>
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include <asm-generic/syscalls.h> #include <asm-generic/syscalls.h>
...@@ -39,7 +42,7 @@ void *sys_call_table[__NR_syscalls] = { ...@@ -39,7 +42,7 @@ void *sys_call_table[__NR_syscalls] = {
typedef long (*sys_call_fn)(unsigned long, unsigned long, typedef long (*sys_call_fn)(unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long, unsigned long); unsigned long, unsigned long, unsigned long, unsigned long);
void noinstr do_syscall(struct pt_regs *regs) void noinstr __no_stack_protector do_syscall(struct pt_regs *regs)
{ {
unsigned long nr; unsigned long nr;
sys_call_fn syscall_fn; sys_call_fn syscall_fn;
...@@ -55,11 +58,28 @@ void noinstr do_syscall(struct pt_regs *regs) ...@@ -55,11 +58,28 @@ void noinstr do_syscall(struct pt_regs *regs)
nr = syscall_enter_from_user_mode(regs, nr); nr = syscall_enter_from_user_mode(regs, nr);
add_random_kstack_offset();
if (nr < NR_syscalls) { if (nr < NR_syscalls) {
syscall_fn = sys_call_table[nr]; syscall_fn = sys_call_table[nr];
regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6],
regs->regs[7], regs->regs[8], regs->regs[9]); regs->regs[7], regs->regs[8], regs->regs[9]);
} }
/*
* This value will get limited by KSTACK_OFFSET_MAX(), which is 10
* bits. The actual entropy will be further reduced by the compiler
* when applying stack alignment constraints: 16-bytes (i.e. 4-bits)
* aligned, which will remove the 4 low bits from any entropy chosen
* here.
*
* The resulting 6 bits of entropy is seen in SP[9:4].
*/
choose_random_kstack_offset(drdtime());
syscall_exit_to_user_mode(regs); syscall_exit_to_user_mode(regs);
} }
#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
STACK_FRAME_NON_STANDARD(do_syscall);
#endif
...@@ -113,6 +113,14 @@ SECTIONS ...@@ -113,6 +113,14 @@ SECTIONS
__rela_dyn_end = .; __rela_dyn_end = .;
} }
#ifdef CONFIG_RELR
.relr.dyn : ALIGN(8) {
__relr_dyn_begin = .;
*(.relr.dyn)
__relr_dyn_end = .;
}
#endif
.data.rel : { *(.data.rel*) } .data.rel : { *(.data.rel*) }
#ifdef CONFIG_RELOCATABLE #ifdef CONFIG_RELOCATABLE
......
...@@ -34,22 +34,49 @@ void enable_pci_wakeup(void) ...@@ -34,22 +34,49 @@ void enable_pci_wakeup(void)
acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_DISABLE, 0); acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_DISABLE, 0);
} }
static struct platform_device loongson3_cpufreq_device = {
.name = "loongson3_cpufreq",
.id = -1,
};
static int __init loongson_cpufreq_init(void)
{
if (!cpu_has_scalefreq)
return -ENODEV;
return platform_device_register(&loongson3_cpufreq_device);
}
arch_initcall(loongson_cpufreq_init);
static void default_suspend_addr(void)
{
acpi_enter_sleep_state(ACPI_STATE_S3);
}
static int __init loongson3_acpi_suspend_init(void) static int __init loongson3_acpi_suspend_init(void)
{ {
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
acpi_status status; acpi_status status;
uint64_t suspend_addr = 0; uint64_t suspend_addr = 0;
if (acpi_disabled || acpi_gbl_reduced_hardware) if (acpi_disabled)
return 0; return 0;
if (!acpi_gbl_reduced_hardware)
acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
if (!acpi_sleep_state_supported(ACPI_STATE_S3))
return 0;
status = acpi_evaluate_integer(NULL, "\\SADR", NULL, &suspend_addr); status = acpi_evaluate_integer(NULL, "\\SADR", NULL, &suspend_addr);
if (ACPI_FAILURE(status) || !suspend_addr) { if (ACPI_FAILURE(status) || !suspend_addr) {
pr_err("ACPI S3 is not support!\n"); pr_info("ACPI S3 supported with hardware register default\n");
return -1; loongson_sysconf.suspend_addr = (u64)default_suspend_addr;
} } else {
pr_info("ACPI S3 supported with Loongson ACPI SADR extension\n");
loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr)); loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr));
}
#endif #endif
return 0; return 0;
} }
......
...@@ -66,18 +66,14 @@ SYM_FUNC_START(loongarch_suspend_enter) ...@@ -66,18 +66,14 @@ SYM_FUNC_START(loongarch_suspend_enter)
la.pcrel a0, loongarch_wakeup_start la.pcrel a0, loongarch_wakeup_start
la.pcrel t0, loongarch_suspend_addr la.pcrel t0, loongarch_suspend_addr
ld.d t0, t0, 0 ld.d t0, t0, 0
jirl a0, t0, 0 /* Call BIOS's STR sleep routine */ jirl ra, t0, 0 /* Call BIOS's STR sleep routine */
/* /*
* This is where we return upon wakeup. * This is where we return upon wakeup.
* Reload all of the registers and return. * Reload all of the registers and return.
*/ */
SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL) SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
li.d t0, CSR_DMW0_INIT # UC, PLV0 SETUP_DMWINS t0
csrwr t0, LOONGARCH_CSR_DMWIN0
li.d t0, CSR_DMW1_INIT # CA, PLV0
csrwr t0, LOONGARCH_CSR_DMWIN1
JUMP_VIRT_ADDR t0, t1 JUMP_VIRT_ADDR t0, t1
/* Enable PG */ /* Enable PG */
......
...@@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, ...@@ -74,6 +74,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
/* Config Direct Mapping */ /* Config Direct Mapping */
csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
csr_write64(CSR_DMW2_INIT, LOONGARCH_CSR_DMWIN2);
csr_write64(CSR_DMW3_INIT, LOONGARCH_CSR_DMWIN3);
real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image); real_kernel_entry = (void *)kernel_entry_address(kernel_addr, image);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment