summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig8
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/board-qemu-virt28/Kconfig2
-rw-r--r--arch/arm/machine/cpu.c43
-rw-r--r--arch/arm/machine/cpu.h4
-rw-r--r--arch/arm/machine/cpu_armv7.h97
-rw-r--r--arch/arm/machine/ssp.c40
-rw-r--r--arch/arm/machine/tcb.c7
-rw-r--r--arch/arm/machine/tcb.h7
-rw-r--r--kern/Kconfig1
-rw-r--r--kern/macros.h11
-rw-r--r--kern/panic.c1
-rw-r--r--kern/percpu.h1
-rw-r--r--test/test_mutex.c1
-rwxr-xr-xtools/qemu_arm.sh1
15 files changed, 207 insertions, 18 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 86b6478e..bf71867f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -18,6 +18,14 @@ config SUBARCH
string
default "armv7a" if ARMV7A
+config ARCH_SMP
+ bool
+ default y if ARMV7A
+
+config CPU_CORTEX_A15
+ bool
+ select ARMV7A
+
choice
prompt "Board"
default BOARD_SELECT_QEMU_VIRT_2_8
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 95a2e503..88bff587 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -7,6 +7,7 @@ x15_SOURCES-y += \
arch/arm/machine/boot.c \
arch/arm/machine/cpu.c \
arch/arm/machine/pmap.c \
+ arch/arm/machine/ssp.c \
arch/arm/machine/strace.c \
arch/arm/machine/tcb_asm.S \
arch/arm/machine/tcb.c
diff --git a/arch/arm/board-qemu-virt28/Kconfig b/arch/arm/board-qemu-virt28/Kconfig
index 1ecb40b7..c07fa17c 100644
--- a/arch/arm/board-qemu-virt28/Kconfig
+++ b/arch/arm/board-qemu-virt28/Kconfig
@@ -2,6 +2,6 @@ if BOARD_SELECT_QEMU_VIRT_2_8
config BOARD_QEMU_VIRT_2_8
def_bool y
- select ARMV7A
+ select CPU_CORTEX_A15
endif
diff --git a/arch/arm/machine/cpu.c b/arch/arm/machine/cpu.c
index a79200fe..1e7dcb3b 100644
--- a/arch/arm/machine/cpu.c
+++ b/arch/arm/machine/cpu.c
@@ -16,8 +16,14 @@
*/
#include <kern/init.h>
+#include <kern/percpu.h>
#include <machine/cpu.h>
+/*
+ * Processor descriptor, one per CPU.
+ */
+struct cpu cpu_desc __percpu;
+
void cpu_halt_broadcast(void)
{
}
@@ -31,13 +37,48 @@ void cpu_mp_setup(void)
{
}
+static void __init
+cpu_init(struct cpu *cpu, unsigned int id)
+{
+ cpu->id = id;
+}
+
+static void __init
+cpu_set_percpu_area(void *area)
+{
+#ifdef CONFIG_SMP
+ cpu_set_tpidrprw((uintptr_t)area);
+#else /* CONFIG_SMP */
+ /* TODO Single-processor support */
+ cpu_halt();
+#endif /* CONFIG_SMP */
+}
+
+/*
+ * Initialize the given cpu structure for the current processor.
+ */
+static void __init
+cpu_init_local(struct cpu *cpu)
+{
+ cpu_set_percpu_area(percpu_area(cpu->id));
+}
+
static int __init
cpu_setup(void)
{
+ struct cpu *cpu;
+
+ cpu = percpu_ptr(cpu_desc, 0);
+ cpu_init(cpu, 0);
+ cpu_init_local(cpu);
+
+ /* TODO Provide cpu_delay() */
+
return 0;
}
-INIT_OP_DEFINE(cpu_setup);
+INIT_OP_DEFINE(cpu_setup,
+ INIT_OP_DEP(percpu_bootstrap, true));
static int __init
cpu_mp_probe(void)
diff --git a/arch/arm/machine/cpu.h b/arch/arm/machine/cpu.h
index c2124ad1..665ed632 100644
--- a/arch/arm/machine/cpu.h
+++ b/arch/arm/machine/cpu.h
@@ -21,6 +21,7 @@
#include <limits.h>
#include <machine/cpu_armv6.h>
+#include <machine/cpu_armv7.h>
/*
* L1 cache line size.
@@ -62,6 +63,7 @@
#include <kern/init.h>
struct cpu {
+ unsigned int id;
};
/*
@@ -118,8 +120,6 @@ cpu_intr_enabled(void)
void cpu_halt_broadcast(void);
-#define cpu_local_ptr(var) (&(var))
-
static inline struct cpu *
cpu_current(void)
{
diff --git a/arch/arm/machine/cpu_armv7.h b/arch/arm/machine/cpu_armv7.h
new file mode 100644
index 00000000..1bd5f742
--- /dev/null
+++ b/arch/arm/machine/cpu_armv7.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017 Richard Braun.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ARM_CPU_ARMV7_H
+#define _ARM_CPU_ARMV7_H
+
+#if CONFIG_ARM_ARCH >= 7
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#include <kern/macros.h>
+
+/*
+ * Get the value of the TPIDRPRW register.
+ */
+static inline uintptr_t
+cpu_get_tpidrprw(void)
+{
+ uintptr_t value;
+
+ asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (value));
+ return value;
+}
+
+/*
+ * Set the value of the TPIDRPRW register.
+ *
+ * Implies a compiler barrier.
+ */
+static inline void
+cpu_set_tpidrprw(uintptr_t value)
+{
+ asm volatile("mcr p15, 0, %0, c13, c0, 4" : : "r" (value) : "memory");
+}
+
+/* TODO Rework into common code */
+#define cpu_local_ptr(var) \
+MACRO_BEGIN \
+ uintptr_t ___percpu_area; \
+ uintptr_t ___offset; \
+ typeof(var) *___ptr; \
+ \
+ ___percpu_area = cpu_get_tpidrprw(); \
+ ___offset = (uintptr_t)(&(var)); \
+ ___ptr = (typeof(var) *)(___percpu_area + ___offset); \
+ ___ptr; \
+MACRO_END
+
+/* TODO Rework into common code */
+#define cpu_local_var(var) (*cpu_local_ptr(var))
+
+/* Interrupt-safe percpu accessors for basic types */
+
+/* TODO Rework into common code */
+#define cpu_local_assign(var, val) \
+MACRO_BEGIN \
+ unsigned long ___flags; \
+ \
+ cpu_intr_save(&___flags); \
+ cpu_local_var(var) = val; \
+ cpu_intr_restore(___flags); \
+MACRO_END
+
+/* TODO Rework into common code */
+#define cpu_local_read(var) \
+MACRO_BEGIN \
+ unsigned long ___flags; \
+ typeof(var) ___val; \
+ \
+ cpu_intr_save(&___flags); \
+ ___val = cpu_local_var(var); \
+ cpu_intr_restore(___flags); \
+ \
+ ___val; \
+MACRO_END
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* ARM_ARCH >= 7 */
+
+#endif /* _ARM_CPU_ARMV7_H */
diff --git a/arch/arm/machine/ssp.c b/arch/arm/machine/ssp.c
new file mode 100644
index 00000000..eb923dd8
--- /dev/null
+++ b/arch/arm/machine/ssp.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 Richard Braun.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+
+#include <kern/macros.h>
+#include <kern/panic.h>
+
+#ifdef __LP64__
+#define SSP_GUARD_WORD 0xdeadd00ddeadd00d
+#else
+#define SSP_GUARD_WORD 0xdeadd00d
+#endif
+
+__used uintptr_t ssp_guard_word = SSP_GUARD_WORD;
+__used extern uintptr_t __stack_chk_guard __attribute__((alias("ssp_guard_word")));
+
+void ssp_panic(void);
+
+__used void
+ssp_panic(void)
+{
+ panic("ssp: stack corruption detected");
+}
+
+__used void __stack_chk_fail(void) __attribute__((alias("ssp_panic")));
diff --git a/arch/arm/machine/tcb.c b/arch/arm/machine/tcb.c
index dea2a1db..b8b6433a 100644
--- a/arch/arm/machine/tcb.c
+++ b/arch/arm/machine/tcb.c
@@ -17,9 +17,12 @@
#include <kern/error.h>
#include <kern/init.h>
+#include <kern/percpu.h>
#include <machine/cpu.h>
#include <machine/tcb.h>
+struct tcb *tcb_current_ptr __percpu;
+
int
tcb_build(struct tcb *tcb, void *stack, void (*fn)(void *), void *arg)
{
@@ -39,8 +42,8 @@ tcb_cleanup(struct tcb *tcb)
static int __init
tcb_setup(void)
{
- cpu_halt();
return 0;
}
-INIT_OP_DEFINE(tcb_setup);
+INIT_OP_DEFINE(tcb_setup,
+ INIT_OP_DEP(cpu_setup, true));
diff --git a/arch/arm/machine/tcb.h b/arch/arm/machine/tcb.h
index fc0ae372..8dca13cc 100644
--- a/arch/arm/machine/tcb.h
+++ b/arch/arm/machine/tcb.h
@@ -24,6 +24,7 @@
#include <stdnoreturn.h>
#include <kern/init.h>
+#include <machine/cpu.h>
#include <machine/page.h>
/*
@@ -41,13 +42,15 @@ void tcb_cleanup(struct tcb *tcb);
static inline struct tcb *
tcb_current(void)
{
- return NULL;
+ extern struct tcb *tcb_current_ptr;
+ return cpu_local_read(tcb_current_ptr);
}
static inline void
tcb_set_current(struct tcb *tcb)
{
- (void)tcb;
+ extern struct tcb *tcb_current_ptr;
+ cpu_local_assign(tcb_current_ptr, tcb);
}
noreturn void tcb_load(struct tcb *tcb);
diff --git a/kern/Kconfig b/kern/Kconfig
index 7c718d4c..dce9ed0a 100644
--- a/kern/Kconfig
+++ b/kern/Kconfig
@@ -3,6 +3,7 @@ menu "General setup"
config SMP
bool "Multiprocessor support"
default y
+ depends on ARCH_SMP
---help---
Enable support for machines with multiple processors.
diff --git a/kern/macros.h b/kern/macros.h
index 23ad4d22..7435b79c 100644
--- a/kern/macros.h
+++ b/kern/macros.h
@@ -43,16 +43,7 @@
#define DECL_CONST(x, s) x
#else /* __ASSEMBLER__ */
#define __DECL_CONST(x, s) x##s
-void cga_putc(char c);
-
-static inline void
-moo_print(const char *s)
-{
- while (*s != '\0') {
- cga_putc(*s);
- s++;
- }
-}
+
#define DECL_CONST(x, s) __DECL_CONST(x, s)
#endif /* __ASSEMBLER__ */
diff --git a/kern/panic.c b/kern/panic.c
index c610e3fa..6c94f87a 100644
--- a/kern/panic.c
+++ b/kern/panic.c
@@ -29,6 +29,7 @@ static unsigned int panic_done;
void
panic(const char *format, ...)
{
+cpu_halt();
va_list list;
unsigned long already_done;
diff --git a/kern/percpu.h b/kern/percpu.h
index 87d14703..1620f96f 100644
--- a/kern/percpu.h
+++ b/kern/percpu.h
@@ -37,6 +37,7 @@
* percpu variables from the local processor :
* - cpu_local_ptr()
* - cpu_local_var()
+ * TODO Document cpu_local_assign() and cpu_local_read().
*
* These accessors may generate optimized code.
*
diff --git a/test/test_mutex.c b/test/test_mutex.c
index d5cc5d13..e74d09f6 100644
--- a/test/test_mutex.c
+++ b/test/test_mutex.c
@@ -80,6 +80,7 @@ test_run(void *arg)
}
if ((counter % 2) == 0) {
+ /* TODO Rework active-waiting interface */
cpu_delay(clock_ticks_to_ms(1) * 1000);
} else {
thread_delay(1, false);
diff --git a/tools/qemu_arm.sh b/tools/qemu_arm.sh
index 9a69d0f1..bcc634ce 100755
--- a/tools/qemu_arm.sh
+++ b/tools/qemu_arm.sh
@@ -19,6 +19,7 @@ dd if=$BIN of=$IMG conv=notrunc
$QEMU_EXE \
-M virt-2.8 \
+ -cpu cortex-a15 \
-ctrl-grab \
-gdb tcp::1234 \
-m $RAM \