Skip to content

Commit 0603839

Browse files
committed
LoongArch: Add exception/interrupt handling
Add the exception and interrupt handling machanism for basic LoongArch support. Reviewed-by: WANG Xuerui <[email protected]> Reviewed-by: Jiaxun Yang <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 628c3bb commit 0603839

File tree

16 files changed

+1575
-0
lines changed

16 files changed

+1575
-0
lines changed

arch/loongarch/include/asm/branch.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_BRANCH_H
6+
#define _ASM_BRANCH_H
7+
8+
#include <asm/ptrace.h>
9+
10+
static inline unsigned long exception_era(struct pt_regs *regs)
11+
{
12+
return regs->csr_era;
13+
}
14+
15+
static inline int compute_return_era(struct pt_regs *regs)
16+
{
17+
regs->csr_era += 4;
18+
return 0;
19+
}
20+
21+
#endif /* _ASM_BRANCH_H */

arch/loongarch/include/asm/bug.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __ASM_BUG_H
3+
#define __ASM_BUG_H
4+
5+
#include <linux/compiler.h>
6+
7+
#ifdef CONFIG_BUG
8+
9+
#include <asm/break.h>
10+
11+
static inline void __noreturn BUG(void)
12+
{
13+
__asm__ __volatile__("break %0" : : "i" (BRK_BUG));
14+
unreachable();
15+
}
16+
17+
#define HAVE_ARCH_BUG
18+
19+
#endif
20+
21+
#include <asm-generic/bug.h>
22+
23+
#endif /* __ASM_BUG_H */
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef ARCH_LOONGARCH_ENTRY_COMMON_H
3+
#define ARCH_LOONGARCH_ENTRY_COMMON_H
4+
5+
#include <linux/sched.h>
6+
#include <linux/processor.h>
7+
8+
static inline bool on_thread_stack(void)
9+
{
10+
return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
11+
}
12+
13+
#endif

arch/loongarch/include/asm/hardirq.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_HARDIRQ_H
6+
#define _ASM_HARDIRQ_H
7+
8+
#include <linux/cache.h>
9+
#include <linux/threads.h>
10+
#include <linux/irq.h>
11+
12+
extern void ack_bad_irq(unsigned int irq);
13+
#define ack_bad_irq ack_bad_irq
14+
15+
#define NR_IPI 2
16+
17+
typedef struct {
18+
unsigned int ipi_irqs[NR_IPI];
19+
unsigned int __softirq_pending;
20+
} ____cacheline_aligned irq_cpustat_t;
21+
22+
DECLARE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat);
23+
24+
#endif /* _ASM_HARDIRQ_H */

arch/loongarch/include/asm/hw_irq.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef __ASM_HW_IRQ_H
6+
#define __ASM_HW_IRQ_H
7+
8+
#include <linux/atomic.h>
9+
10+
extern atomic_t irq_err_count;
11+
12+
/*
13+
* interrupt-retrigger: NOP for now. This may not be appropriate for all
14+
* machines, we'll see ...
15+
*/
16+
17+
#endif /* __ASM_HW_IRQ_H */

arch/loongarch/include/asm/irq.h

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_IRQ_H
6+
#define _ASM_IRQ_H
7+
8+
#include <linux/irqdomain.h>
9+
#include <linux/irqreturn.h>
10+
11+
#define IRQ_STACK_SIZE THREAD_SIZE
12+
#define IRQ_STACK_START (IRQ_STACK_SIZE - 16)
13+
14+
DECLARE_PER_CPU(unsigned long, irq_stack);
15+
16+
/*
17+
* The highest address on the IRQ stack contains a dummy frame which is
18+
* structured as follows:
19+
*
20+
* top ------------
21+
* | task sp | <- irq_stack[cpu] + IRQ_STACK_START
22+
* ------------
23+
* | | <- First frame of IRQ context
24+
* ------------
25+
*
26+
* task sp holds a copy of the task stack pointer where the struct pt_regs
27+
* from exception entry can be found.
28+
*/
29+
30+
static inline bool on_irq_stack(int cpu, unsigned long sp)
31+
{
32+
unsigned long low = per_cpu(irq_stack, cpu);
33+
unsigned long high = low + IRQ_STACK_SIZE;
34+
35+
return (low <= sp && sp <= high);
36+
}
37+
38+
int get_ipi_irq(void);
39+
int get_pmc_irq(void);
40+
int get_timer_irq(void);
41+
void spurious_interrupt(void);
42+
43+
#define NR_IRQS_LEGACY 16
44+
45+
#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
46+
void arch_trigger_cpumask_backtrace(const struct cpumask *mask, bool exclude_self);
47+
48+
#define MAX_IO_PICS 2
49+
#define NR_IRQS (64 + (256 * MAX_IO_PICS))
50+
51+
#define CORES_PER_EIO_NODE 4
52+
53+
#define LOONGSON_CPU_UART0_VEC 10 /* CPU UART0 */
54+
#define LOONGSON_CPU_THSENS_VEC 14 /* CPU Thsens */
55+
#define LOONGSON_CPU_HT0_VEC 16 /* CPU HT0 irq vector base number */
56+
#define LOONGSON_CPU_HT1_VEC 24 /* CPU HT1 irq vector base number */
57+
58+
/* IRQ number definitions */
59+
#define LOONGSON_LPC_IRQ_BASE 0
60+
#define LOONGSON_LPC_LAST_IRQ (LOONGSON_LPC_IRQ_BASE + 15)
61+
62+
#define LOONGSON_CPU_IRQ_BASE 16
63+
#define LOONGSON_CPU_LAST_IRQ (LOONGSON_CPU_IRQ_BASE + 14)
64+
65+
#define LOONGSON_PCH_IRQ_BASE 64
66+
#define LOONGSON_PCH_ACPI_IRQ (LOONGSON_PCH_IRQ_BASE + 47)
67+
#define LOONGSON_PCH_LAST_IRQ (LOONGSON_PCH_IRQ_BASE + 64 - 1)
68+
69+
#define LOONGSON_MSI_IRQ_BASE (LOONGSON_PCH_IRQ_BASE + 64)
70+
#define LOONGSON_MSI_LAST_IRQ (LOONGSON_PCH_IRQ_BASE + 256 - 1)
71+
72+
#define GSI_MIN_LPC_IRQ LOONGSON_LPC_IRQ_BASE
73+
#define GSI_MAX_LPC_IRQ (LOONGSON_LPC_IRQ_BASE + 16 - 1)
74+
#define GSI_MIN_CPU_IRQ LOONGSON_CPU_IRQ_BASE
75+
#define GSI_MAX_CPU_IRQ (LOONGSON_CPU_IRQ_BASE + 48 - 1)
76+
#define GSI_MIN_PCH_IRQ LOONGSON_PCH_IRQ_BASE
77+
#define GSI_MAX_PCH_IRQ (LOONGSON_PCH_IRQ_BASE + 256 - 1)
78+
79+
extern int find_pch_pic(u32 gsi);
80+
extern int eiointc_get_node(int id);
81+
82+
static inline void eiointc_enable(void)
83+
{
84+
uint64_t misc;
85+
86+
misc = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC);
87+
misc |= IOCSR_MISC_FUNC_EXT_IOI_EN;
88+
iocsr_write64(misc, LOONGARCH_IOCSR_MISC_FUNC);
89+
}
90+
91+
struct acpi_madt_lio_pic;
92+
struct acpi_madt_eio_pic;
93+
struct acpi_madt_ht_pic;
94+
struct acpi_madt_bio_pic;
95+
struct acpi_madt_msi_pic;
96+
struct acpi_madt_lpc_pic;
97+
98+
struct irq_domain *loongarch_cpu_irq_init(void);
99+
100+
struct irq_domain *liointc_acpi_init(struct irq_domain *parent,
101+
struct acpi_madt_lio_pic *acpi_liointc);
102+
struct irq_domain *eiointc_acpi_init(struct irq_domain *parent,
103+
struct acpi_madt_eio_pic *acpi_eiointc);
104+
105+
struct irq_domain *htvec_acpi_init(struct irq_domain *parent,
106+
struct acpi_madt_ht_pic *acpi_htvec);
107+
struct irq_domain *pch_lpc_acpi_init(struct irq_domain *parent,
108+
struct acpi_madt_lpc_pic *acpi_pchlpc);
109+
struct irq_domain *pch_msi_acpi_init(struct irq_domain *parent,
110+
struct acpi_madt_msi_pic *acpi_pchmsi);
111+
struct irq_domain *pch_pic_acpi_init(struct irq_domain *parent,
112+
struct acpi_madt_bio_pic *acpi_pchpic);
113+
114+
extern struct acpi_madt_lio_pic *acpi_liointc;
115+
extern struct acpi_madt_eio_pic *acpi_eiointc[MAX_IO_PICS];
116+
117+
extern struct acpi_madt_ht_pic *acpi_htintc;
118+
extern struct acpi_madt_lpc_pic *acpi_pchlpc;
119+
extern struct acpi_madt_msi_pic *acpi_pchmsi[MAX_IO_PICS];
120+
extern struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS];
121+
122+
extern struct irq_domain *cpu_domain;
123+
extern struct irq_domain *liointc_domain;
124+
extern struct irq_domain *pch_lpc_domain;
125+
extern struct irq_domain *pch_msi_domain[MAX_IO_PICS];
126+
extern struct irq_domain *pch_pic_domain[MAX_IO_PICS];
127+
128+
#include <asm-generic/irq.h>
129+
130+
#endif /* _ASM_IRQ_H */

arch/loongarch/include/asm/irq_regs.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef __ASM_IRQ_REGS_H
6+
#define __ASM_IRQ_REGS_H
7+
8+
#define ARCH_HAS_OWN_IRQ_REGS
9+
10+
#include <linux/thread_info.h>
11+
12+
static inline struct pt_regs *get_irq_regs(void)
13+
{
14+
return current_thread_info()->regs;
15+
}
16+
17+
static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
18+
{
19+
struct pt_regs *old_regs;
20+
21+
old_regs = get_irq_regs();
22+
current_thread_info()->regs = new_regs;
23+
24+
return old_regs;
25+
}
26+
27+
#endif /* __ASM_IRQ_REGS_H */

arch/loongarch/include/asm/irqflags.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_IRQFLAGS_H
6+
#define _ASM_IRQFLAGS_H
7+
8+
#ifndef __ASSEMBLY__
9+
10+
#include <linux/compiler.h>
11+
#include <linux/stringify.h>
12+
#include <asm/compiler.h>
13+
#include <asm/loongarch.h>
14+
15+
static inline void arch_local_irq_enable(void)
16+
{
17+
u32 flags = CSR_CRMD_IE;
18+
__asm__ __volatile__(
19+
"csrxchg %[val], %[mask], %[reg]\n\t"
20+
: [val] "+r" (flags)
21+
: [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
22+
: "memory");
23+
}
24+
25+
static inline void arch_local_irq_disable(void)
26+
{
27+
u32 flags = 0;
28+
__asm__ __volatile__(
29+
"csrxchg %[val], %[mask], %[reg]\n\t"
30+
: [val] "+r" (flags)
31+
: [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
32+
: "memory");
33+
}
34+
35+
static inline unsigned long arch_local_irq_save(void)
36+
{
37+
u32 flags = 0;
38+
__asm__ __volatile__(
39+
"csrxchg %[val], %[mask], %[reg]\n\t"
40+
: [val] "+r" (flags)
41+
: [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
42+
: "memory");
43+
return flags;
44+
}
45+
46+
static inline void arch_local_irq_restore(unsigned long flags)
47+
{
48+
__asm__ __volatile__(
49+
"csrxchg %[val], %[mask], %[reg]\n\t"
50+
: [val] "+r" (flags)
51+
: [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
52+
: "memory");
53+
}
54+
55+
static inline unsigned long arch_local_save_flags(void)
56+
{
57+
u32 flags;
58+
__asm__ __volatile__(
59+
"csrrd %[val], %[reg]\n\t"
60+
: [val] "=r" (flags)
61+
: [reg] "i" (LOONGARCH_CSR_CRMD)
62+
: "memory");
63+
return flags;
64+
}
65+
66+
static inline int arch_irqs_disabled_flags(unsigned long flags)
67+
{
68+
return !(flags & CSR_CRMD_IE);
69+
}
70+
71+
static inline int arch_irqs_disabled(void)
72+
{
73+
return arch_irqs_disabled_flags(arch_local_save_flags());
74+
}
75+
76+
#endif /* #ifndef __ASSEMBLY__ */
77+
78+
#endif /* _ASM_IRQFLAGS_H */

arch/loongarch/include/asm/kdebug.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_LOONGARCH_KDEBUG_H
6+
#define _ASM_LOONGARCH_KDEBUG_H
7+
8+
#include <linux/notifier.h>
9+
10+
enum die_val {
11+
DIE_OOPS = 1,
12+
DIE_RI,
13+
DIE_FP,
14+
DIE_SIMD,
15+
DIE_TRAP,
16+
DIE_PAGE_FAULT,
17+
DIE_BREAK,
18+
DIE_SSTEPBP,
19+
DIE_UPROBE,
20+
DIE_UPROBE_XOL,
21+
};
22+
23+
#endif /* _ASM_LOONGARCH_KDEBUG_H */

0 commit comments

Comments
 (0)