Skip to content

Commit 0369998

Browse files
frantonynashif
authored andcommitted
arch: add MIPS architecture support
MIPS (Microprocessor without Interlocked Pipelined Stages) is a instruction set architecture (ISA) developed by MIPS Computer Systems, now MIPS Technologies. This commit provides MIPS architecture support to Zephyr. It is compatible with the MIPS32 Release 1 specification. Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
1 parent b5e749e commit 0369998

File tree

34 files changed

+1654
-5
lines changed

34 files changed

+1654
-5
lines changed

CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
/arch/arm64/core/cortex_r/ @povergoing
2626
/arch/arm64/core/xen/ @lorc @firscity
2727
/arch/common/ @ioannisg @andyross
28+
/arch/mips/ @frantony
2829
/soc/arc/snps_*/ @abrodkin @ruuddw @evgeniy-paltsev
2930
/soc/nios2/ @nashif
3031
/soc/arm/ @MaureenHelm @galak @ioannisg
@@ -533,6 +534,7 @@
533534
/include/arch/arm64/ @carlocaione
534535
/include/arch/arm64/cortex_r/ @povergoing
535536
/include/arch/arm/aarch32/irq.h @carlocaione
537+
/include/arch/mips/ @frantony
536538
/include/arch/nios2/ @nashif
537539
/include/arch/nios2/arch.h @nashif
538540
/include/arch/posix/ @aescolar @daor-oti

arch/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ config ARM64
4949
help
5050
ARM64 (AArch64) architecture
5151

52+
config MIPS
53+
bool
54+
select ARCH_IS_SET
55+
select ATOMIC_OPERATIONS_C
56+
select HAS_DTS
57+
help
58+
MIPS architecture
59+
5260
config SPARC
5361
bool
5462
select ARCH_IS_SET

arch/mips/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# Copyright (c) 2020 Antony Pavlov <antonynpavlov@gmail.com>
3+
#
4+
# based on arch/riscv/CMakeLists.txt
5+
#
6+
# SPDX-License-Identifier: Apache-2.0
7+
#
8+
9+
if(CONFIG_BIG_ENDIAN)
10+
set_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT "elf32-bigmips")
11+
else()
12+
set_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT "elf32-littlemips")
13+
endif()
14+
15+
add_subdirectory(core)
16+
zephyr_include_directories(include)

arch/mips/Kconfig

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#
2+
# Copyright (c) 2020 Antony Pavlov <antonynpavlov@gmail.com>
3+
#
4+
# based on arch/riscv/Kconfig
5+
#
6+
# SPDX-License-Identifier: Apache-2.0
7+
#
8+
9+
menu "MIPS Options"
10+
depends on MIPS
11+
12+
config ARCH
13+
string
14+
default "mips"
15+
16+
config GEN_ISR_TABLES
17+
default y
18+
19+
config GEN_IRQ_VECTOR_TABLE
20+
default n
21+
22+
config GEN_SW_ISR_TABLE
23+
default y
24+
25+
config NUM_IRQS
26+
int
27+
28+
# Bump the kernel default stack size values.
29+
config MAIN_STACK_SIZE
30+
default 4096 if COVERAGE_GCOV
31+
default 2048
32+
33+
config IDLE_STACK_SIZE
34+
default 1024
35+
36+
config ISR_STACK_SIZE
37+
default 4096
38+
39+
config TEST_EXTRA_STACKSIZE
40+
default 4096 if COVERAGE_GCOV
41+
default 2048
42+
43+
config SYSTEM_WORKQUEUE_STACK_SIZE
44+
default 4096
45+
46+
config CMSIS_THREAD_MAX_STACK_SIZE
47+
default 2048
48+
49+
config CMSIS_V2_THREAD_MAX_STACK_SIZE
50+
default 2048
51+
52+
config CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE
53+
default 2048
54+
55+
config IPM_CONSOLE_STACK_SIZE
56+
default 4096 if COVERAGE
57+
default 1024
58+
59+
endmenu

arch/mips/core/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
zephyr_library()
4+
5+
zephyr_library_sources(
6+
cpu_idle.c
7+
fatal.c
8+
irq_manage.c
9+
isr.S
10+
prep_c.c
11+
reset.S
12+
swap.S
13+
thread.c
14+
)
15+
16+
zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c)

arch/mips/core/cpu_idle.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2020 Antony Pavlov <antonynpavlov@gmail.com>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <irq.h>
8+
9+
#include <tracing/tracing.h>
10+
11+
static ALWAYS_INLINE void mips_idle(unsigned int key)
12+
{
13+
sys_trace_idle();
14+
15+
/* unlock interrupts */
16+
irq_unlock(key);
17+
18+
/* wait for interrupt */
19+
__asm__ volatile("wait");
20+
}
21+
22+
void arch_cpu_idle(void)
23+
{
24+
mips_idle(1);
25+
}
26+
27+
void arch_cpu_atomic_idle(unsigned int key)
28+
{
29+
mips_idle(key);
30+
}

arch/mips/core/fatal.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2020 Antony Pavlov <antonynpavlov@gmail.com>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <kernel.h>
8+
#include <sys/printk.h>
9+
#include <logging/log.h>
10+
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
11+
12+
FUNC_NORETURN void z_mips_fatal_error(unsigned int reason,
13+
const z_arch_esf_t *esf)
14+
{
15+
if (esf != NULL) {
16+
printk("$ 0 : (ze) %08lx(at) %08lx(v0) %08lx(v1)\n",
17+
esf->at, esf->v0, esf->v1);
18+
printk("$ 4 : %08lx(a0) %08lx(a1) %08lx(a2) %08lx(a3)\n",
19+
esf->a0, esf->a1, esf->a2, esf->a3);
20+
printk("$ 8 : %08lx(t0) %08lx(t1) %08lx(t2) %08lx(t3)\n",
21+
esf->t0, esf->t1, esf->t2, esf->t3);
22+
printk("$12 : %08lx(t4) %08lx(t5) %08lx(t6) %08lx(t7)\n",
23+
esf->t4, esf->t5, esf->t6, esf->t7);
24+
printk("...\n");
25+
printk("$24 : %08lx(t8) %08lx(t9)\n",
26+
esf->t8, esf->t9);
27+
printk("$28 : %08lx(gp) (sp) (s8) %08lx(ra)\n",
28+
esf->gp, esf->ra);
29+
30+
printk("EPC : %08lx\n", esf->epc);
31+
32+
printk("Status: %08lx\n", esf->status);
33+
printk("Cause : %08lx\n", esf->cause);
34+
printk("BadVA : %08lx\n", esf->badvaddr);
35+
}
36+
37+
z_fatal_error(reason, esf);
38+
CODE_UNREACHABLE;
39+
}
40+
41+
static char *cause_str(ulong_t cause)
42+
{
43+
switch (cause) {
44+
case 0:
45+
return "interrupt pending";
46+
case 1:
47+
return "TLB modified";
48+
case 2:
49+
return "TLB miss on load or ifetch";
50+
case 3:
51+
return "TLB miss on store";
52+
case 4:
53+
return "address error on load or ifetch";
54+
case 5:
55+
return "address error on store";
56+
case 6:
57+
return "bus error on ifetch";
58+
case 7:
59+
return "bus error on load or store";
60+
case 8:
61+
return "system call";
62+
case 9:
63+
return "breakpoint";
64+
case 10:
65+
return "reserved instruction";
66+
case 11:
67+
return "coprocessor unusable";
68+
case 12:
69+
return "arithmetic overflow";
70+
case 13:
71+
return "trap instruction";
72+
case 14:
73+
return "virtual coherency instruction";
74+
case 15:
75+
return "floating point";
76+
case 16:
77+
return "iwatch";
78+
case 23:
79+
return "dwatch";
80+
case 31:
81+
return "virtual coherency data";
82+
default:
83+
return "unknown";
84+
}
85+
}
86+
87+
void _Fault(z_arch_esf_t *esf)
88+
{
89+
ulong_t cause;
90+
91+
cause = (read_c0_cause() & CAUSE_EXP_MASK) >> CAUSE_EXP_SHIFT;
92+
93+
LOG_ERR("");
94+
LOG_ERR(" cause: %ld, %s", cause, cause_str(cause));
95+
96+
z_mips_fatal_error(K_ERR_CPU_EXCEPTION, esf);
97+
}

arch/mips/core/irq_manage.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (c) 2020 Antony Pavlov <antonynpavlov@gmail.com>
3+
*
4+
* based on arch/nios2/core/irq_manage.c
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#include <kernel.h>
10+
#include <kswap.h>
11+
#include <logging/log.h>
12+
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
13+
14+
15+
uint32_t mips_cp0_status_int_mask;
16+
17+
18+
FUNC_NORETURN void z_irq_spurious(const void *unused)
19+
{
20+
ulong_t cause;
21+
22+
ARG_UNUSED(unused);
23+
cause = (read_c0_cause() & CAUSE_EXP_MASK) >> CAUSE_EXP_SHIFT;
24+
25+
LOG_ERR("Spurious interrupt detected! CAUSE: %ld", cause);
26+
27+
z_mips_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
28+
}
29+
30+
void arch_irq_enable(unsigned int irq)
31+
{
32+
unsigned int key;
33+
uint32_t irq_mask;
34+
35+
key = irq_lock();
36+
37+
irq_mask = ST0_IP0 << irq;
38+
mips_cp0_status_int_mask |= irq_mask;
39+
write_c0_status(read_c0_status() | irq_mask);
40+
41+
irq_unlock(key);
42+
}
43+
44+
void arch_irq_disable(unsigned int irq)
45+
{
46+
unsigned int key;
47+
uint32_t irq_mask;
48+
49+
key = irq_lock();
50+
51+
irq_mask = ST0_IP0 << irq;
52+
mips_cp0_status_int_mask &= ~irq_mask;
53+
write_c0_status(read_c0_status() & ~irq_mask);
54+
55+
irq_unlock(key);
56+
};
57+
58+
int arch_irq_is_enabled(unsigned int irq)
59+
{
60+
return read_c0_status() & (ST0_IP0 << irq);
61+
}
62+
63+
void z_mips_enter_irq(uint32_t ipending)
64+
{
65+
_current_cpu->nested++;
66+
67+
#ifdef CONFIG_IRQ_OFFLOAD
68+
z_irq_do_offload();
69+
#endif
70+
71+
while (ipending) {
72+
int index;
73+
struct _isr_table_entry *ite;
74+
75+
if (IS_ENABLED(CONFIG_TRACING_ISR))
76+
sys_trace_isr_enter();
77+
78+
index = find_lsb_set(ipending) - 1;
79+
ipending &= ~BIT(index);
80+
81+
ite = &_sw_isr_table[index];
82+
83+
ite->isr(ite->arg);
84+
85+
if (IS_ENABLED(CONFIG_TRACING_ISR))
86+
sys_trace_isr_exit();
87+
}
88+
89+
_current_cpu->nested--;
90+
91+
if (IS_ENABLED(CONFIG_STACK_SENTINEL))
92+
z_check_stack_sentinel();
93+
}
94+
95+
#ifdef CONFIG_DYNAMIC_INTERRUPTS
96+
int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
97+
void (*routine)(const void *parameter),
98+
const void *parameter, uint32_t flags)
99+
{
100+
ARG_UNUSED(flags);
101+
ARG_UNUSED(priority);
102+
103+
z_isr_install(irq, routine, parameter);
104+
return irq;
105+
}
106+
#endif /* CONFIG_DYNAMIC_INTERRUPTS */

0 commit comments

Comments
 (0)