Module: xenomai-3 Branch: next Commit: ddae18edfee5bca3f9ff261505504e0d82ebad38 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=ddae18edfee5bca3f9ff261505504e0d82ebad38
Author: Dmitriy Cherkasov <dmit...@mperpetuo.com> Date: Wed May 6 15:27:23 2015 -0700 cobalt/arm64: populate arch/arm64 with a copy of arch/arm. kernel/cobalt/arch/arm -> kernel/cobalt/arch/arm64 lib/cobalt/arch/arm -> lib/cobalt/arch/arm64 --- configure.ac | 8 + kernel/cobalt/arch/arm64/Kconfig | 40 +++ kernel/cobalt/arch/arm64/Makefile | 5 + .../arch/arm64/include/asm/xenomai/calibration.h | 59 ++++ .../arch/arm64/include/asm/xenomai/features.h | 30 ++ .../cobalt/arch/arm64/include/asm/xenomai/fptest.h | 52 +++ .../arch/arm64/include/asm/xenomai/machine.h | 85 +++++ .../arch/arm64/include/asm/xenomai/syscall.h | 74 ++++ .../arch/arm64/include/asm/xenomai/syscall32.h | 24 ++ .../cobalt/arch/arm64/include/asm/xenomai/thread.h | 123 +++++++ .../arch/arm64/include/asm/xenomai/uapi/arith.h | 142 ++++++++ .../arch/arm64/include/asm/xenomai/uapi/features.h | 43 +++ .../arch/arm64/include/asm/xenomai/uapi/fptest.h | 61 ++++ .../arch/arm64/include/asm/xenomai/uapi/syscall.h | 34 ++ .../arch/arm64/include/asm/xenomai/uapi/tsc.h | 25 ++ .../arch/arm64/include/asm/xenomai/wrappers.h | 27 ++ kernel/cobalt/arch/arm64/machine.c | 119 +++++++ kernel/cobalt/arch/arm64/mayday.c | 146 ++++++++ kernel/cobalt/arch/arm64/switch.S | 167 +++++++++ kernel/cobalt/arch/arm64/syscall.c | 53 +++ kernel/cobalt/arch/arm64/thread.c | 355 ++++++++++++++++++++ lib/cobalt/arch/Makefile.am | 2 +- lib/cobalt/arch/arm64/Makefile.am | 13 + lib/cobalt/arch/arm64/features.c | 102 ++++++ lib/cobalt/arch/arm64/include/Makefile.am | 2 + lib/cobalt/arch/arm64/include/asm/Makefile.am | 2 + .../arch/arm64/include/asm/xenomai/Makefile.am | 5 + .../arch/arm64/include/asm/xenomai/features.h | 62 ++++ .../arch/arm64/include/asm/xenomai/syscall.h | 138 ++++++++ lib/cobalt/arch/arm64/include/asm/xenomai/tsc.h | 48 +++ 30 files changed, 2045 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 38a1749..ac9b252 100644 --- a/configure.ac +++ b/configure.ac @@ -139,6 +139,10 @@ case "$build_for" in XENO_TARGET_ARCH=arm CONFIG_XENO_DEFAULT_PERIOD=1000000 ;; + aarch64-*) + XENO_TARGET_ARCH=arm64 + CONFIG_XENO_DEFAULT_PERIOD=1000000 + ;; x86_64-*|amd64-*) use_tls=yes XENO_TARGET_ARCH=x86 @@ -854,6 +858,10 @@ AC_CONFIG_FILES([ \ lib/cobalt/arch/arm/include/Makefile \ lib/cobalt/arch/arm/include/asm/Makefile \ lib/cobalt/arch/arm/include/asm/xenomai/Makefile \ + lib/cobalt/arch/arm64/Makefile \ + lib/cobalt/arch/arm64/include/Makefile \ + lib/cobalt/arch/arm64/include/asm/Makefile \ + lib/cobalt/arch/arm64/include/asm/xenomai/Makefile \ lib/cobalt/arch/powerpc/Makefile \ lib/cobalt/arch/powerpc/include/Makefile \ lib/cobalt/arch/powerpc/include/asm/Makefile \ diff --git a/kernel/cobalt/arch/arm64/Kconfig b/kernel/cobalt/arch/arm64/Kconfig new file mode 100644 index 0000000..dc6485d --- /dev/null +++ b/kernel/cobalt/arch/arm64/Kconfig @@ -0,0 +1,40 @@ +source "kernel/xenomai/Kconfig" +source "drivers/xenomai/Kconfig" + +menu "Machine/platform-specific options" + +config XENO_ARCH_UNLOCKED_SWITCH + bool "Unlocked context switch" + default y + help + The Cobalt core may allow non-atomic execution of the + machine-dependent context switching code, so that other CPUs + and/or local interrupts may execute concurrently. + + This option reduces interrupt latency when costly cache and + TLB flushes are required to switch context. + + You definitely want to enable that option on low-end ARM + platforms. +endmenu + +config IPIPE_WANT_PREEMPTIBLE_SWITCH + bool + default y if XENO_ARCH_UNLOCKED_SWITCH + default n if !XENO_ARCH_UNLOCKED_SWITCH + +config IPIPE_WANT_ACTIVE_MM + def_bool y + +config XENO_ARCH_WANT_TIP + def_bool y + +config XENO_ARCH_FPU + def_bool VFP + +config XENO_ARCH_SYS3264 + def_bool n + +config XENO_ARCH_OUTOFLINE_XNLOCK + bool + default y diff --git a/kernel/cobalt/arch/arm64/Makefile b/kernel/cobalt/arch/arm64/Makefile new file mode 100644 index 0000000..f2e4e20 --- /dev/null +++ b/kernel/cobalt/arch/arm64/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_XENOMAI) += xenomai.o + +xenomai-y := machine.o mayday.o thread.o switch.o syscall.o + +ccflags-y := -Iarch/arm/xenomai/include -Iinclude/xenomai diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/calibration.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/calibration.h new file mode 100644 index 0000000..e303a04 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/calibration.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2001,2002,2003,2004,2005 Philippe Gerum <r...@xenomai.org>. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * Xenomai 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 2 of the License, or + * (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef _COBALT_ARM_ASM_CALIBRATION_H +#define _COBALT_ARM_ASM_CALIBRATION_H + +unsigned int omap_rev(void); +#define cpu_is_omap44xx() ((omap_rev() & 0xff) == 0x44) + +static inline void xnarch_get_latencies(struct xnclock_gravity *p) +{ + unsigned int ulat; +#if CONFIG_XENO_OPT_TIMING_SCHEDLAT != 0 + ulat = CONFIG_XENO_OPT_TIMING_SCHEDLAT; +#elif defined(CONFIG_ARCH_AT91RM9200) + ulat = 8500; +#elif defined(CONFIG_ARCH_AT91SAM9263) + ulat = 11000; +#elif defined(CONFIG_SOC_IMX6Q) + ulat = 6000; +#elif defined(CONFIG_ARCH_MX51) + ulat = 5000; +#elif defined(CONFIG_ARCH_MX53) + ulat = 5000; +#elif defined(CONFIG_ARCH_MX6) + ulat = 2000; +#elif defined(CONFIG_SOC_IMX7) + ulat = 2000; +#elif defined(CONFIG_SOC_LS1021A) + ulat = 2800; +#elif defined(CONFIG_ARCH_OMAP) + ulat = cpu_is_omap44xx() ? 2500 : 5000; +#else + ulat = 9500; /* XXX sane? */ +#endif + p->user = xnclock_ns_to_ticks(&nkclock, ulat); + p->kernel = xnclock_ns_to_ticks(&nkclock, CONFIG_XENO_OPT_TIMING_KSCHEDLAT); + p->irq = xnclock_ns_to_ticks(&nkclock, CONFIG_XENO_OPT_TIMING_IRQLAT); +} + +#endif /* !_COBALT_ARM_ASM_CALIBRATION_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/features.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/features.h new file mode 100644 index 0000000..d485286 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/features.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2005 Philippe Gerum <r...@xenomai.org>. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * Xenomai 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 2 of the License, + * or (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef _COBALT_ARM_ASM_FEATURES_H +#define _COBALT_ARM_ASM_FEATURES_H + +struct cobalt_featinfo; +static inline void collect_arch_features(struct cobalt_featinfo *p) { } + +#include <asm/xenomai/uapi/features.h> + +#endif /* !_COBALT_ARM_ASM_FEATURES_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/fptest.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/fptest.h new file mode 100644 index 0000000..a76f1e6 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/fptest.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2006 Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>. + * + * Xenomai 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 2 of the License, + * or (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef _COBALT_ARM_ASM_FPTEST_H +#define _COBALT_ARM_ASM_FPTEST_H + +#include <linux/errno.h> +#include <asm/hwcap.h> + +#ifdef CONFIG_VFP +#define have_vfp (elf_hwcap & HWCAP_VFP) +#else /* !CONFIG_VFP */ +#define have_vfp 0 +#endif /* !CONFIG_VFP */ + +#include <asm/xenomai/uapi/fptest.h> + +static inline int fp_kernel_supported(void) +{ + return 1; +} + +static inline int fp_linux_begin(void) +{ + return -ENOSYS; +} + +static inline void fp_linux_end(void) +{ +} + +static inline int fp_detect(void) +{ + return have_vfp ? __COBALT_HAVE_VFP : 0; +} + +#endif /* _COBALT_ARM_ASM_FPTEST_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/machine.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/machine.h new file mode 100644 index 0000000..d6e965f --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/machine.h @@ -0,0 +1,85 @@ +/** + * Copyright © 2002-2004 Philippe Gerum. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * Xenomai 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, Inc., 675 Mass Ave, + * Cambridge MA 02139, USA; either version 2 of the License, or (at + * your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef _COBALT_ARM_ASM_MACHINE_H +#define _COBALT_ARM_ASM_MACHINE_H + +#include <linux/version.h> +#include <asm/byteorder.h> + +#define XNARCH_HOST_TICK_IRQ __ipipe_hrtimer_irq + +#include <asm/barrier.h> +#include <asm/compiler.h> +#include <asm/cmpxchg.h> +#include <asm/switch_to.h> +#include <asm/system_info.h> +#include <asm/system_misc.h> +#include <asm/timex.h> +#include <asm/processor.h> +#include <asm/ipipe.h> +#include <asm/mach/irq.h> +#include <asm/cacheflush.h> + +#define xnarch_cache_aliasing() cache_is_vivt() + +#if __LINUX_ARM_ARCH__ < 5 +static inline __attribute_const__ unsigned long ffnz(unsigned long x) +{ + int r = 0; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} +#else +static inline __attribute_const__ unsigned long ffnz(unsigned long ul) +{ + int __r; + __asm__("clz\t%0, %1" : "=r" (__r) : "r"(ul & (-ul)) : "cc"); + return 31 - __r; +} +#endif + +#include <asm-generic/xenomai/machine.h> + +#endif /* !_COBALT_ARM_ASM_MACHINE_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/syscall.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/syscall.h new file mode 100644 index 0000000..d80df77 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/syscall.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2001,2002,2003,2004 Philippe Gerum <r...@xenomai.org>. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * Xenomai 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 2 of the License, + * or (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef _COBALT_ARM_ASM_SYSCALL_H +#define _COBALT_ARM_ASM_SYSCALL_H + +#include <linux/errno.h> +#include <asm/uaccess.h> +#include <asm/unistd.h> +#include <asm/ptrace.h> +#include <asm-generic/xenomai/syscall.h> + +#ifndef __ARM_NR_ipipe +/* Legacy pipelines do not define this. */ +#define __ARM_NR_ipipe (__NR_SYSCALL_BASE + XENO_ARM_SYSCALL) +#endif + +#define __xn_reg_sys(__regs) ((__regs)->ARM_ORIG_r0) +/* In OABI_COMPAT mode, handle both OABI and EABI userspace syscalls */ +#ifdef CONFIG_OABI_COMPAT +#define __xn_syscall_p(__regs) (((__regs)->ARM_r7 == __NR_OABI_SYSCALL_BASE + XENO_ARM_SYSCALL) || \ + ((__regs)->ARM_r7 == __ARM_NR_ipipe)) +#else /* !CONFIG_OABI_COMPAT */ +#define __xn_syscall_p(__regs) ((__regs)->ARM_r7 == __ARM_NR_ipipe) +#endif /* !CONFIG_OABI_COMPAT */ +#define __xn_syscall(__regs) (__xn_reg_sys(__regs) & ~__COBALT_SYSCALL_BIT) + +#define __xn_reg_rval(__regs) ((__regs)->ARM_r0) +#define __xn_reg_arg1(__regs) ((__regs)->ARM_r1) +#define __xn_reg_arg2(__regs) ((__regs)->ARM_r2) +#define __xn_reg_arg3(__regs) ((__regs)->ARM_r3) +#define __xn_reg_arg4(__regs) ((__regs)->ARM_r4) +#define __xn_reg_arg5(__regs) ((__regs)->ARM_r5) +#define __xn_reg_pc(__regs) ((__regs)->ARM_ip) +#define __xn_reg_sp(__regs) ((__regs)->ARM_sp) + +static inline void __xn_error_return(struct pt_regs *regs, int v) +{ + __xn_reg_rval(regs) = v; +} + +static inline void __xn_status_return(struct pt_regs *regs, long v) +{ + __xn_reg_rval(regs) = v; +} + +static inline int __xn_interrupted_p(struct pt_regs *regs) +{ + return __xn_reg_rval(regs) == -EINTR; +} + +int xnarch_local_syscall(unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, + unsigned long a5); + +#endif /* !_COBALT_ARM_ASM_SYSCALL_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/syscall32.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/syscall32.h new file mode 100644 index 0000000..95c5a11 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/syscall32.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2014 Philippe Gerum <r...@xenomai.org>. + * + * Xenomai 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 2 of the License, + * or (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef _COBALT_ARM_ASM_SYSCALL32_H +#define _COBALT_ARM_ASM_SYSCALL32_H + +#include <asm-generic/xenomai/syscall32.h> + +#endif /* !_COBALT_ARM_ASM_SYSCALL32_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/thread.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/thread.h new file mode 100644 index 0000000..11439a3 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/thread.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2005 Stelian Pop + * + * Xenomai 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 2 of the License, or + * (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef _COBALT_ARM_ASM_THREAD_H +#define _COBALT_ARM_ASM_THREAD_H + +#include <asm-generic/xenomai/thread.h> + +#ifdef CONFIG_XENO_ARCH_FPU +#ifdef CONFIG_VFP +#include <asm/vfp.h> +#endif /* CONFIG_VFP */ +#endif /* !CONFIG_XENO_ARCH_FPU */ + +struct xnarchtcb { + struct xntcb core; +#ifdef CONFIG_XENO_ARCH_FPU +#ifdef CONFIG_VFP + union vfp_state *fpup; +#define xnarch_fpu_ptr(tcb) ((tcb)->fpup) +#else +#define xnarch_fpu_ptr(tcb) NULL +#endif +#endif + struct { + unsigned long pc; + unsigned long r0; +#ifdef __ARM_EABI__ + unsigned long r7; +#endif +#ifdef CONFIG_ARM_THUMB + unsigned long psr; +#endif + } mayday; +}; + +#define xnarch_fault_regs(d) ((d)->regs) +#define xnarch_fault_trap(d) ((d)->exception) +#define xnarch_fault_code(d) (0) +#define xnarch_fault_pc(d) ((d)->regs->ARM_pc - (thumb_mode((d)->regs) ? 2 : 4)) /* XXX ? */ + +#define xnarch_fault_pf_p(d) ((d)->exception == IPIPE_TRAP_ACCESS) +#define xnarch_fault_bp_p(d) ((current->ptrace & PT_PTRACED) && \ + ((d)->exception == IPIPE_TRAP_BREAK || \ + (d)->exception == IPIPE_TRAP_UNDEFINSTR)) + +#define xnarch_fault_notify(d) (!xnarch_fault_bp_p(d)) + +void xnarch_switch_to(struct xnthread *out, struct xnthread *in); + +static inline void xnarch_enter_root(struct xnthread *root) { } + +int xnarch_escalate(void); + +#if defined(CONFIG_XENO_ARCH_FPU) && defined(CONFIG_VFP) + +static inline void xnarch_init_root_tcb(struct xnthread *thread) +{ + struct xnarchtcb *tcb = xnthread_archtcb(thread); + tcb->fpup = NULL; +} + +void xnarch_init_shadow_tcb(struct xnthread *thread); + +int xnarch_fault_fpu_p(struct ipipe_trap_data *d); + +void xnarch_leave_root(struct xnthread *root); + +void xnarch_save_fpu(struct xnthread *thread); + +void xnarch_switch_fpu(struct xnthread *from, struct xnthread *thread); + +int xnarch_handle_fpu_fault(struct xnthread *from, + struct xnthread *to, struct ipipe_trap_data *d); + +#else /* !CONFIG_XENO_ARCH_FPU || !CONFIG_VFP */ + +static inline void xnarch_init_root_tcb(struct xnthread *thread) { } +static inline void xnarch_init_shadow_tcb(struct xnthread *thread) { } + +/* + * Userland may raise FPU faults with FPU-enabled kernels, regardless + * of whether real-time threads actually use FPU, so we simply ignore + * these faults. + */ +static inline int xnarch_fault_fpu_p(struct ipipe_trap_data *d) +{ + return 0; +} + +static inline void xnarch_leave_root(struct xnthread *root) { } + +static inline void xnarch_save_fpu(struct xnthread *thread) { } + +static inline void xnarch_switch_fpu(struct xnthread *f, struct xnthread *t) { } + +static inline int xnarch_handle_fpu_fault(struct xnthread *from, + struct xnthread *to, struct ipipe_trap_data *d) +{ + return 0; +} +#endif /* !CONFIG_XENO_ARCH_FPU || !CONFIG_VFP */ + +static inline void xnarch_enable_kfpu(void) { } + +static inline void xnarch_disable_kfpu(void) { } + +#endif /* !_COBALT_ARM_ASM_THREAD_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/arith.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/arith.h new file mode 100644 index 0000000..cf897b4 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/arith.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2008 Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef _COBALT_ARM_ASM_UAPI_ARITH_H +#define _COBALT_ARM_ASM_UAPI_ARITH_H + +#include <asm/xenomai/uapi/features.h> + +#if __LINUX_ARM_ARCH__ >= 4 && (!defined(CONFIG_THUMB2_KERNEL) || !defined(CONFIG_FTRACE)) +static inline __attribute__((__const__)) unsigned long long +mach_arm_nodiv_ullimd(const unsigned long long op, + const unsigned long long frac, + const unsigned rhs_integ); + +#define xnarch_nodiv_ullimd(op, frac, integ) \ + mach_arm_nodiv_ullimd((op), (frac), (integ)) + +static inline __attribute__((__const__)) long long +mach_arm_nodiv_llimd(const long long op, + const unsigned long long frac, + const unsigned rhs_integ); + +#define xnarch_nodiv_llimd(op, frac, integ) \ + mach_arm_nodiv_llimd((op), (frac), (integ)) +#else /* arm <= v3 */ +#define xnarch_add96and64(l0, l1, l2, s0, s1) \ + do { \ + __asm__ ("adds %2, %2, %4\n\t" \ + "adcs %1, %1, %3\n\t" \ + "adc %0, %0, #0\n\t" \ + : "+r"(l0), "+r"(l1), "+r"(l2) \ + : "r"(s0), "r"(s1): "cc"); \ + } while (0) +#endif /* arm <= v3 */ + +#include <cobalt/uapi/asm-generic/arith.h> + +#if __LINUX_ARM_ARCH__ >= 4 && (!defined(CONFIG_THUMB2_KERNEL) || !defined(CONFIG_FTRACE)) +#define mach_arm_nodiv_ullimd_str \ + "umull %[tl], %[rl], %[opl], %[fracl]\n\t" \ + "umull %[rm], %[rh], %[oph], %[frach]\n\t" \ + "adds %[rl], %[rl], %[tl], lsr #31\n\t" \ + "adcs %[rm], %[rm], #0\n\t" \ + "adc %[rh], %[rh], #0\n\t" \ + "umull %[tl], %[th], %[oph], %[fracl]\n\t" \ + "adds %[rl], %[rl], %[tl]\n\t" \ + "adcs %[rm], %[rm], %[th]\n\t" \ + "adc %[rh], %[rh], #0\n\t" \ + "umull %[tl], %[th], %[opl], %[frach]\n\t" \ + "adds %[rl], %[rl], %[tl]\n\t" \ + "adcs %[rm], %[rm], %[th]\n\t" \ + "adc %[rh], %[rh], #0\n\t" \ + "umlal %[rm], %[rh], %[opl], %[integ]\n\t" \ + "mla %[rh], %[oph], %[integ], %[rh]\n\t" + +static inline __attribute__((__const__)) unsigned long long +mach_arm_nodiv_ullimd(const unsigned long long op, + const unsigned long long frac, + const unsigned rhs_integ) +{ + register unsigned rl __asm__("r5"); + register unsigned rm __asm__("r0"); + register unsigned rh __asm__("r1"); + register unsigned fracl __asm__ ("r2"); + register unsigned frach __asm__ ("r3"); + register unsigned integ __asm__("r4") = rhs_integ; + register unsigned opl __asm__ ("r6"); + register unsigned oph __asm__ ("r7"); + register unsigned tl __asm__("r8"); + register unsigned th __asm__("r9"); + + xnarch_u64tou32(op, oph, opl); + xnarch_u64tou32(frac, frach, fracl); + + __asm__ (mach_arm_nodiv_ullimd_str + : [rl]"=r"(rl), [rm]"=r"(rm), [rh]"=r"(rh), + [tl]"=r"(tl), [th]"=r"(th) + : [opl]"r"(opl), [oph]"r"(oph), + [fracl]"r"(fracl), [frach]"r"(frach), + [integ]"r"(integ) + : "cc"); + + return xnarch_u64fromu32(rh, rm); +} + +static inline __attribute__((__const__)) long long +mach_arm_nodiv_llimd(const long long op, + const unsigned long long frac, + const unsigned rhs_integ) +{ + register unsigned rl __asm__("r5"); + register unsigned rm __asm__("r0"); + register unsigned rh __asm__("r1"); + register unsigned fracl __asm__ ("r2"); + register unsigned frach __asm__ ("r3"); + register unsigned integ __asm__("r4") = rhs_integ; + register unsigned opl __asm__ ("r6"); + register unsigned oph __asm__ ("r7"); + register unsigned tl __asm__("r8"); + register unsigned th __asm__("r9"); + register unsigned s __asm__("r10"); + + xnarch_u64tou32(op, oph, opl); + xnarch_u64tou32(frac, frach, fracl); + + __asm__ ("movs %[s], %[oph], lsr #30\n\t" + "beq 1f\n\t" + "rsbs %[opl], %[opl], #0\n\t" + "sbc %[oph], %[oph], %[oph], lsl #1\n" + "1:\t" + mach_arm_nodiv_ullimd_str + "teq %[s], #0\n\t" + "beq 2f\n\t" + "rsbs %[rm], %[rm], #0\n\t" + "sbc %[rh], %[rh], %[rh], lsl #1\n" + "2:\t" + : [rl]"=r"(rl), [rm]"=r"(rm), [rh]"=r"(rh), + [tl]"=r"(tl), [th]"=r"(th), [s]"=r"(s) + : [opl]"r"(opl), [oph]"r"(oph), + [fracl]"r"(fracl), [frach]"r"(frach), + [integ]"r"(integ) + : "cc"); + + return xnarch_u64fromu32(rh, rm); +} +#endif /* arm >= v4 */ + +#endif /* _COBALT_ARM_ASM_UAPI_ARITH_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/features.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/features.h new file mode 100644 index 0000000..fe50182 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/features.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005 Philippe Gerum <r...@xenomai.org>. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef _COBALT_ARM_ASM_UAPI_FEATURES_H +#define _COBALT_ARM_ASM_UAPI_FEATURES_H + +/* The ABI revision level we use on this arch. */ +#define XENOMAI_ABI_REV 15UL + +#define XENOMAI_FEAT_DEP (__xn_feat_generic_mask) + +#define XENOMAI_FEAT_MAN (__xn_feat_generic_man_mask) + +#define XNARCH_HAVE_LLMULSHFT 1 +#define XNARCH_HAVE_NODIV_LLIMD 1 + +struct cobalt_featinfo_archdep { /* no arch-specific feature */ }; + +#include <cobalt/uapi/asm-generic/features.h> + +static inline const char *get_feature_label(unsigned int feature) +{ + return get_generic_feature_label(feature); +} + +#endif /* !_COBALT_ARM_ASM_UAPI_FEATURES_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/fptest.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/fptest.h new file mode 100644 index 0000000..b81d109 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/fptest.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2006 Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef _COBALT_ARM_ASM_UAPI_FPTEST_H +#define _COBALT_ARM_ASM_UAPI_FPTEST_H + +#define __COBALT_HAVE_VFP 0x1 + +static inline void fp_regs_set(int features, unsigned int val) +{ + unsigned long long e[16]; + unsigned int i; + + if (features & __COBALT_HAVE_VFP) { + for (i = 0; i < 16; i++) + e[i] = val; + + /* vldm %0!, {d0-d15}, + AKA fldmiax %0!, {d0-d15} */ + __asm__ __volatile__("ldc p11, cr0, [%0],#32*4": + "=r"(i): "0"(&e[0]): "memory"); + } +} + +static inline unsigned int fp_regs_check(int features, unsigned int val, + int (*report)(const char *fmt, ...)) +{ + unsigned int result = val, i; + unsigned long long e[16]; + + if (features & __COBALT_HAVE_VFP) { + /* vstm %0!, {d0-d15}, + AKA fstmiax %0!, {d0-d15} */ + __asm__ __volatile__("stc p11, cr0, [%0],#32*4": + "=r"(i): "0"(&e[0]): "memory"); + + for (i = 0; i < 16; i++) + if (e[i] != val) { + report("d%d: %llu != %u\n", i, e[i], val); + result = e[i]; + } + } + + return result; +} + +#endif /* !_COBALT_ARM_ASM_UAPI_FPTEST_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/syscall.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/syscall.h new file mode 100644 index 0000000..c4e3593 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/syscall.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2001,2002,2003,2004 Philippe Gerum <r...@xenomai.org>. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef _COBALT_ARM_ASM_UAPI_SYSCALL_H +#define _COBALT_ARM_ASM_UAPI_SYSCALL_H + +#define __xn_syscode(__nr) (__COBALT_SYSCALL_BIT | (__nr)) + +#define XENO_ARM_SYSCALL 0x000F0042 /* carefully chosen... */ + +#define XENOMAI_SYSARCH_ATOMIC_ADD_RETURN 0 +#define XENOMAI_SYSARCH_ATOMIC_SET_MASK 1 +#define XENOMAI_SYSARCH_ATOMIC_CLEAR_MASK 2 +#define XENOMAI_SYSARCH_XCHG 3 +#define XENOMAI_SYSARCH_TSCINFO 4 + +#endif /* !_COBALT_ARM_ASM_UAPI_SYSCALL_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/tsc.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/tsc.h new file mode 100644 index 0000000..b17cfb2 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/uapi/tsc.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2013 Gilles Chanteperdrix <g...@xenomai.org>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef _COBALT_ARM_ASM_UAPI_TSC_H +#define _COBALT_ARM_ASM_UAPI_TSC_H + +struct __xn_tscinfo { + volatile unsigned int *counter; +}; + +#endif /* !_COBALT_ARM_ASM_UAPI_TSC_H */ diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/wrappers.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/wrappers.h new file mode 100644 index 0000000..fe59896 --- /dev/null +++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/wrappers.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2005 Philippe Gerum <r...@xenomai.org>. + * + * Xenomai 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 2 of the License, + * or (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef _COBALT_ARM_ASM_WRAPPERS_H +#define _COBALT_ARM_ASM_WRAPPERS_H + +#include <asm-generic/xenomai/wrappers.h> /* Read the generic portion. */ + +#define __put_user_inatomic __put_user +#define __get_user_inatomic __get_user + +#endif /* _COBALT_ARM_ASM_WRAPPERS_H */ diff --git a/kernel/cobalt/arch/arm64/machine.c b/kernel/cobalt/arch/arm64/machine.c new file mode 100644 index 0000000..f48d4a8 --- /dev/null +++ b/kernel/cobalt/arch/arm64/machine.c @@ -0,0 +1,119 @@ +/** + * Copyright (C) 2005 Stelian Pop + * + * Xenomai 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, Inc., 675 Mass Ave, + * Cambridge MA 02139, USA; either version 2 of the License, or (at + * your option) any later version. + * + * Xenomai 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <linux/mm.h> +#include <linux/ipipe_tickdev.h> +#include <cobalt/kernel/arith.h> +#include <asm/cacheflush.h> +#include <asm/xenomai/machine.h> + +#define CALIBRATION_LOOPS 10 + +static void mach_arm_prefault(struct vm_area_struct *vma) +{ + unsigned long addr; + unsigned int flags; + + if ((vma->vm_flags & VM_MAYREAD)) { + flags = (vma->vm_flags & VM_MAYWRITE) ? FAULT_FLAG_WRITE : 0; + for (addr = vma->vm_start; + addr != vma->vm_end; addr += PAGE_SIZE) + handle_mm_fault(vma->vm_mm, vma, addr, flags); + } +} + +static unsigned long mach_arm_calibrate(void) +{ + unsigned long long start, end, sum = 0, sum_sq = 0; + volatile unsigned const_delay = 0xffffffff; + unsigned long result, flags, tsc_lat; + unsigned int delay = const_delay; + long long diff; + int i, j; + + flags = ipipe_critical_enter(NULL); + + /* + * Hw interrupts off, other CPUs quiesced, no migration + * possible. We can now fiddle with the timer chip (per-cpu + * local or global, ipipe_timer_set() will handle this + * transparently). + */ + ipipe_read_tsc(start); + barrier(); + ipipe_read_tsc(end); + tsc_lat = end - start; + barrier(); + + for (i = 0; i < CALIBRATION_LOOPS; i++) { + flush_cache_all(); + for (j = 0; j < CALIBRATION_LOOPS; j++) { + ipipe_read_tsc(start); + barrier(); + ipipe_timer_set(delay); + barrier(); + ipipe_read_tsc(end); + diff = end - start - tsc_lat; + if (diff > 0) { + sum += diff; + sum_sq += diff * diff; + } + } + } + + ipipe_critical_exit(flags); + + /* Use average + standard deviation as timer programming latency. */ + do_div(sum, CALIBRATION_LOOPS * CALIBRATION_LOOPS); + do_div(sum_sq, CALIBRATION_LOOPS * CALIBRATION_LOOPS); + result = sum + int_sqrt(sum_sq - sum * sum) + 1; + /* + * Reset the max trace, since it contains the calibration time + * now. + */ + ipipe_trace_max_reset(); + + return result; +} + +static const char *const fault_labels[] = { + [IPIPE_TRAP_ACCESS] = "Data or instruction access", + [IPIPE_TRAP_SECTION] = "Section fault", + [IPIPE_TRAP_DABT] = "Generic data abort", + [IPIPE_TRAP_UNKNOWN] = "Unknown exception", + [IPIPE_TRAP_BREAK] = "Instruction breakpoint", + [IPIPE_TRAP_FPU] = "Floating point exception", + [IPIPE_TRAP_VFP] = "VFP Floating point exception", + [IPIPE_TRAP_UNDEFINSTR] = "Undefined instruction", +#ifdef IPIPE_TRAP_ALIGNMENT + [IPIPE_TRAP_ALIGNMENT] = "Unaligned access exception", +#endif /* IPIPE_TRAP_ALIGNMENT */ + [IPIPE_NR_FAULTS] = NULL +}; + +struct cobalt_machine cobalt_machine = { + .name = "arm", + .init = NULL, + .late_init = NULL, + .cleanup = NULL, + .calibrate = mach_arm_calibrate, + .prefault = mach_arm_prefault, + .fault_labels = fault_labels, +}; diff --git a/kernel/cobalt/arch/arm64/mayday.c b/kernel/cobalt/arch/arm64/mayday.c new file mode 100644 index 0000000..20e4559 --- /dev/null +++ b/kernel/cobalt/arch/arm64/mayday.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2010 Philippe Gerum <r...@xenomai.org>. + * + * Xenomai 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 2 of the License, or + * (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#include <linux/types.h> +#include <linux/ipipe.h> +#include <linux/vmalloc.h> +#include <cobalt/kernel/thread.h> +#include <cobalt/uapi/syscall.h> +#include <asm/cacheflush.h> +#include <asm/ptrace.h> + +static void *mayday; + +static inline void setup_mayday(void *page) +{ + /* + * We want this code to appear at the top of the MAYDAY page: + * + * ifdef ARM_EABI + * + * e59f000c ldr r0, [pc, #12] + * e59f700c ldr r7, [pc, #12] + * ef000000 svc 0x00000000 + * e3a00000 mov r0, #0 + * e5800000 str r0, [r0] ; <bug> + * 1000005e .word 0x1000005e ; sc_cobalt_mayday | __COBALT_SYSCALL_BIT + * 000f0042 .word 0x000f0042 + * + * elif ARM_OABI + * + * e59f0008 ldr r0, [pc, #8] + * ef9f0042 swi 0x009f0042 + * e3a00000 mov r0, #0 + * e5800000 str r0, [r0] ; <bug> + * 1000005e .word 0x1000005e ; sc_cobalt_mayday | __COBALT_SYSCALL_BIT + * + * endif + * + * 32bit instruction words will be laid out by the compiler as + * the target endianness requires. + * + * We don't mess with CPSR here, so no need to save/restore it + * in handle/fixup code. + */ +#ifdef __ARM_EABI__ + static const struct { + u32 ldr_r0; + u32 ldr_r7; + u32 swi_0; + u32 mov_r0; + u32 str_r0; + u32 cst_r0; + u32 cst_r7; + } code = { + .ldr_r0 = 0xe59f000c, + .ldr_r7 = 0xe59f700c, + .swi_0 = 0xef000000, + .mov_r0 = 0xe3a00000, + .str_r0 = 0xe5800000, + .cst_r0 = __xn_syscode(sc_cobalt_mayday), + .cst_r7 = 0x000f0042, + }; +#else /* OABI */ + static const struct { + u32 ldr_r0; + u32 swi_syscall; + u32 mov_r0; + u32 str_r0; + u32 cst_r0; + } code = { + .ldr_r0 = 0xe59f0008, + .swi_syscall = 0xef9f0042, + .mov_r0 = 0xe3a00000, + .str_r0 = 0xe5800000, + .cst_r0 = __xn_syscode(sc_cobalt_mayday), + }; +#endif /* OABI */ + + memcpy(page, &code, sizeof(code)); + + flush_dcache_page(vmalloc_to_page(page)); +} + +int xnarch_init_mayday(void) +{ + mayday = vmalloc(PAGE_SIZE); + if (mayday == NULL) + return -ENOMEM; + + setup_mayday(mayday); + + return 0; +} + +void xnarch_cleanup_mayday(void) +{ + vfree(mayday); +} + +void *xnarch_get_mayday_page(void) +{ + return mayday; +} + +void xnarch_handle_mayday(struct xnarchtcb *tcb, struct pt_regs *regs, + unsigned long tramp) +{ + tcb->mayday.pc = regs->ARM_pc; + tcb->mayday.r0 = regs->ARM_r0; +#ifdef __ARM_EABI__ + tcb->mayday.r7 = regs->ARM_r7; +#endif +#ifdef CONFIG_ARM_THUMB + /* The code on the mayday page must be run in ARM mode */ + tcb->mayday.psr = regs->ARM_cpsr; + regs->ARM_cpsr &= ~PSR_T_BIT; +#endif + regs->ARM_pc = tramp; +} + +void xnarch_fixup_mayday(struct xnarchtcb *tcb, struct pt_regs *regs) +{ + regs->ARM_pc = tcb->mayday.pc; + regs->ARM_r0 = tcb->mayday.r0; +#ifdef __ARM_EABI__ + regs->ARM_r7 = tcb->mayday.r7; +#endif +#ifdef CONFIG_ARM_THUMB + regs->ARM_cpsr = tcb->mayday.psr; +#endif +} diff --git a/kernel/cobalt/arch/arm64/switch.S b/kernel/cobalt/arch/arm64/switch.S new file mode 100644 index 0000000..505fd5a --- /dev/null +++ b/kernel/cobalt/arch/arm64/switch.S @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2005 Stelian Pop. + * + * 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, Inc., 675 Mass Ave, Cambridge MA 02139, + * USA; either version 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/linkage.h> +#include <linux/version.h> +#include <asm/assembler.h> +#include <asm/asm-offsets.h> +#include <asm/tls.h> +#ifdef CONFIG_VFP +#include <asm/vfpmacros.h> +#endif + + .macro fpu_switch tmp +#ifdef CONFIG_VFP +#if __LINUX_ARM_ARCH__ <= 6 +#ifdef CONFIG_JUMP_LABEL +9998: nop + .pushsection __jump_table, "aw" + .word 9998b, 9999f, __xeno_vfp_key + .popsection +#else + ldr \tmp, =elf_hwcap + ldr \tmp, [\tmp] + tst \tmp, #HWCAP_VFP + beq 9999f +#endif +#endif + @ Always disable VFP so we can lazily save/restore the old + @ state. This occurs in the context of the previous thread. + VFPFMRX \tmp, FPEXC + bic \tmp, \tmp, #FPEXC_EN + VFPFMXR FPEXC, \tmp +#if __LINUX_ARM_ARCH__ <= 6 +9999: +#endif +#endif + .endm + + .text + +#if defined(CONFIG_VFP) && defined(CONFIG_XENO_ARCH_FPU) +/* Copied from vfp_save_state in arch/arm/vfp/vfphw.S + * r0 = pointer to union vfp_state, r1 = fpexc + */ +ENTRY(__asm_vfp_save) + VFPFSTMIA r0, r2 @ save the working registers + VFPFMRX r2, FPSCR @ current status + tst r1, #FPEXC_EX @ is there additional state to save? + beq 1f + VFPFMRX r3, FPINST @ FPINST (only if FPEXC.EX is set) + tst r1, #FPEXC_FP2V @ is there an FPINST2 to read? + beq 1f + VFPFMRX r12, FPINST2 @ FPINST2 if needed (and present) +1: + stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2 + mov pc, lr +ENDPROC(__asm_vfp_save) + +/* Copied from no_old_VFP_process in arch/arm/vfp/vfphw.S + * r0 = pointer to union vfp_state + * r1 = current cpu + */ +ENTRY(__asm_vfp_load) +#ifdef CONFIG_SMP + str r1, [r0, #VFP_CPU] +#endif + VFPFLDMIA r0, r2 @ reload the working registers while + @ FPEXC is in a safe state + ldmia r0, {r1, r2, r3, r12} @ load FPEXC, FPSCR, FPINST, FPINST2 + tst r1, #FPEXC_EX @ is there additional state to restore? + beq 1f + VFPFMXR FPINST, r3 @ restore FPINST (only if FPEXC.EX is set) + tst r1, #FPEXC_FP2V @ is there an FPINST2 to write? + beq 1f + VFPFMXR FPINST2, r12 @ FPINST2 if needed (and present) +1: + VFPFMXR FPSCR, r2 @ restore status + mov pc, lr +ENDPROC(__asm_vfp_load) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) + .macro load_tls base, tp, tpuser + ldr \tp, [\base, #TI_TP_VALUE] + .endm + + .macro switch_tls base, tp, tpuser, tmp1, tmp2 + set_tls \tp, \tmp1, \tmp2 + .endm +#else + .macro load_tls base, tp, tpuser + ldr \tp, [\base, #TI_TP_VALUE] + ldr \tpuser, [\base, #TI_TP_VALUE + 4] + .endm +#endif + +/* +/* + * Switch context routine. + * + * Registers according to the ARM procedure call standard: + * Reg Description + * r0-r3 argument/scratch registers + * r4-r9 variable register + * r10=sl stack limit/variable register + * r11=fp frame pointer/variable register + * r12=ip intra-procedure-call scratch register + * r13=sp stack pointer (auto preserved) + * r14=lr link register + * r15=pc program counter (auto preserved) + * + * Copied from __switch_to, arch/arm/kernel/entry-armv.S. + * Right now it is identical, but who knows what the + * future reserves us... + * + * XXX: All the following config options are NOT tested: + * CONFIG_IWMMXT + * + * Calling args: + * r0 = previous thread_info, r1 = next thread_info + */ +ENTRY(__asm_thread_switch) + add ip, r0, #TI_CPU_SAVE + ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack + THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack + THUMB( str sp, [ip], #4 ) + THUMB( str lr, [ip], #4 ) + load_tls r1, r4, r5 +#ifdef CONFIG_CPU_USE_DOMAINS + ldr r6, [r1, #TI_CPU_DOMAIN] +#endif + switch_tls r0, r4, r5, r3, r7 +#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) + ldr r7, [r1, #TI_TASK] + ldr r8, =__stack_chk_guard + ldr r7, [r7, #TSK_STACK_CANARY] +#endif +#ifdef CONFIG_CPU_USE_DOMAINS + mcr p15, 0, r6, c3, c0, 0 @ Set domain register +#endif + fpu_switch r4 +#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) + str r7, [r8] +#endif + ARM( add r4, r1, #TI_CPU_SAVE ) + ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously + THUMB( add ip, r1, #TI_CPU_SAVE ) + THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously + THUMB( ldr sp, [ip], #4 ) + THUMB( ldr pc, [ip] ) +ENDPROC(__asm_thread_switch) diff --git a/kernel/cobalt/arch/arm64/syscall.c b/kernel/cobalt/arch/arm64/syscall.c new file mode 100644 index 0000000..ee78243 --- /dev/null +++ b/kernel/cobalt/arch/arm64/syscall.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005 Stelian Pop + * Copyright (C) 2010 Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> + * + * Xenomai 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 2 of the License, or + * (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <linux/ipipe.h> +#include <asm/xenomai/syscall.h> +#include <asm/xenomai/uapi/tsc.h> + +int xnarch_local_syscall(unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, + unsigned long a5) +{ + struct ipipe_sysinfo ipipe_info; + struct __ipipe_tscinfo *p = &ipipe_info.arch.tsc; + struct __xn_tscinfo info; + int ret; + + if (a1 != XENOMAI_SYSARCH_TSCINFO) + return -EINVAL; + + ret = ipipe_get_sysinfo(&ipipe_info); + if (ret) + return ret; + + switch (p->type) { + case IPIPE_TSC_TYPE_DECREMENTER: + info.counter = p->u.dec.counter; + break; + case IPIPE_TSC_TYPE_NONE: + return -ENOSYS; + default: + info.counter = p->u.fr.counter; + break; + } + + return cobalt_copy_to_user((void *)a2, &info, sizeof(info)); +} diff --git a/kernel/cobalt/arch/arm64/thread.c b/kernel/cobalt/arch/arm64/thread.c new file mode 100644 index 0000000..825926c --- /dev/null +++ b/kernel/cobalt/arch/arm64/thread.c @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2001,2002,2003,2004 Philippe Gerum <r...@xenomai.org>. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * Xenomai 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 2 of the License, or + * (at your option) any later version. + * + * Xenomai 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 Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <linux/sched.h> +#include <linux/ipipe.h> +#include <linux/mm.h> +#include <linux/jump_label.h> +#include <asm/mmu_context.h> +#include <cobalt/kernel/thread.h> + +struct static_key __xeno_vfp_key = STATIC_KEY_INIT_TRUE; + +asmlinkage void __asm_thread_switch(struct thread_info *out, + struct thread_info *in); + +asmlinkage void __asm_thread_trampoline(void); + +#if defined(CONFIG_XENO_ARCH_FPU) && defined(CONFIG_VFP) + +static unsigned int vfp_checked; +static DEFINE_MUTEX(vfp_check_lock); + +asmlinkage void __asm_vfp_save(union vfp_state *vfp, unsigned int fpexc); + +asmlinkage void __asm_vfp_load(union vfp_state *vfp, unsigned int cpu); + +#define do_vfp_fmrx(_vfp_) \ + ({ \ + u32 __v; \ + asm volatile("mrc p10, 7, %0, " __stringify(_vfp_) \ + ", cr0, 0 @ fmrx %0, " #_vfp_: \ + "=r" (__v)); \ + __v; \ + }) + +#define do_vfp_fmxr(_vfp_,_var_) \ + asm volatile("mcr p10, 7, %0, " __stringify(_vfp_) \ + ", cr0, 0 @ fmxr " #_vfp_ ", %0": \ + /* */ : "r" (_var_)) + +extern union vfp_state *vfp_current_hw_state[NR_CPUS]; + +static inline union vfp_state *get_fpu_owner(void) +{ + union vfp_state *vfp_owner; + unsigned int cpu; +#ifdef CONFIG_SMP + unsigned int fpexc; +#endif + +#if __LINUX_ARM_ARCH__ <= 6 + if (!static_key_true(&__xeno_vfp_key)) + return NULL; +#endif + +#ifdef CONFIG_SMP + fpexc = do_vfp_fmrx(FPEXC); + if (!(fpexc & FPEXC_EN)) + return NULL; +#endif + + cpu = ipipe_processor_id(); + vfp_owner = vfp_current_hw_state[cpu]; + if (!vfp_owner) + return NULL; + +#ifdef CONFIG_SMP + if (vfp_owner->hard.cpu != cpu) + return NULL; +#endif /* SMP */ + + return vfp_owner; +} + +#define do_disable_vfp(fpexc) \ + do_vfp_fmxr(FPEXC, fpexc & ~FPEXC_EN) + +#define XNARCH_VFP_ANY_EXC \ + (FPEXC_EX|FPEXC_DEX|FPEXC_FP2V|FPEXC_VV|FPEXC_TRAP_MASK) + +#define do_enable_vfp() \ + ({ \ + unsigned _fpexc = do_vfp_fmrx(FPEXC) | FPEXC_EN; \ + do_vfp_fmxr(FPEXC, _fpexc & ~XNARCH_VFP_ANY_EXC); \ + _fpexc; \ + }) + +int xnarch_fault_fpu_p(struct ipipe_trap_data *d) +{ + /* This function does the same thing to decode the faulting instruct as + "call_fpe" in arch/arm/entry-armv.S */ + static unsigned copro_to_exc[16] = { + IPIPE_TRAP_UNDEFINSTR, + /* FPE */ + IPIPE_TRAP_FPU, IPIPE_TRAP_FPU, + IPIPE_TRAP_UNDEFINSTR, +#ifdef CONFIG_CRUNCH + IPIPE_TRAP_FPU, IPIPE_TRAP_FPU, IPIPE_TRAP_FPU, +#else /* !CONFIG_CRUNCH */ + IPIPE_TRAP_UNDEFINSTR, IPIPE_TRAP_UNDEFINSTR, IPIPE_TRAP_UNDEFINSTR, +#endif /* !CONFIG_CRUNCH */ + IPIPE_TRAP_UNDEFINSTR, IPIPE_TRAP_UNDEFINSTR, IPIPE_TRAP_UNDEFINSTR, +#ifdef CONFIG_VFP + IPIPE_TRAP_VFP, IPIPE_TRAP_VFP, +#else /* !CONFIG_VFP */ + IPIPE_TRAP_UNDEFINSTR, IPIPE_TRAP_UNDEFINSTR, +#endif /* !CONFIG_VFP */ + IPIPE_TRAP_UNDEFINSTR, IPIPE_TRAP_UNDEFINSTR, + IPIPE_TRAP_UNDEFINSTR, IPIPE_TRAP_UNDEFINSTR, + }; + unsigned instr, exc, cp; + char *pc; + + if (d->exception == IPIPE_TRAP_FPU) + return 1; + + if (d->exception == IPIPE_TRAP_VFP) + goto trap_vfp; + + if (d->exception != IPIPE_TRAP_UNDEFINSTR) + return 0; + + pc = (char *) xnarch_fault_pc(d); + if (unlikely(thumb_mode(d->regs))) { + unsigned short thumbh, thumbl; + +#if defined(CONFIG_ARM_THUMB) && __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_V7) +#if __LINUX_ARM_ARCH__ < 7 + if (cpu_architecture() < CPU_ARCH_ARMv7) +#else + if (0) +#endif /* arch < 7 */ +#endif /* thumb && arch >= 6 && cpu_v7 */ + return 0; + + thumbh = *(unsigned short *) pc; + thumbl = *((unsigned short *) pc + 1); + + if ((thumbh & 0x0000f800) < 0x0000e800) + return 0; + instr = (thumbh << 16) | thumbl; + +#ifdef CONFIG_NEON + if ((instr & 0xef000000) == 0xef000000 + || (instr & 0xff100000) == 0xf9000000) + goto trap_vfp; +#endif + } else { + instr = *(unsigned *) pc; + +#ifdef CONFIG_NEON + if ((instr & 0xfe000000) == 0xf2000000 + || (instr & 0xff100000) == 0xf4000000) + goto trap_vfp; +#endif + } + + if ((instr & 0x0c000000) != 0x0c000000) + return 0; + + cp = (instr & 0x00000f00) >> 8; +#ifdef CONFIG_IWMMXT + /* We need something equivalent to _TIF_USING_IWMMXT for Xenomai kernel + threads */ + if (cp <= 1) { + d->exception = IPIPE_TRAP_FPU; + return 1; + } +#endif + + exc = copro_to_exc[cp]; + if (exc == IPIPE_TRAP_VFP) { + trap_vfp: + /* If an exception is pending, the VFP fault is not really an + "FPU unavailable" fault, so we return undefinstr in that + case, the nucleus will let linux handle the fault. */ + exc = do_vfp_fmrx(FPEXC); + if (exc & (FPEXC_EX|FPEXC_DEX) + || ((exc & FPEXC_EN) && do_vfp_fmrx(FPSCR) & FPSCR_IXE)) + exc = IPIPE_TRAP_UNDEFINSTR; + else + exc = IPIPE_TRAP_VFP; + } + + d->exception = exc; + return exc != IPIPE_TRAP_UNDEFINSTR; +} + +void xnarch_leave_root(struct xnthread *root) +{ + struct xnarchtcb *rootcb = xnthread_archtcb(root); + rootcb->fpup = get_fpu_owner(); +} + +void xnarch_save_fpu(struct xnthread *thread) +{ + struct xnarchtcb *tcb = &thread->tcb; + if (tcb->fpup) + __asm_vfp_save(tcb->fpup, do_enable_vfp()); +} + +void xnarch_switch_fpu(struct xnthread *from, struct xnthread *to) +{ + union vfp_state *const from_fpup = from ? from->tcb.fpup : NULL; + unsigned cpu = ipipe_processor_id(); + + if (xnthread_test_state(to, XNROOT) == 0) { + union vfp_state *const to_fpup = to->tcb.fpup; + unsigned fpexc = do_enable_vfp(); + + if (from_fpup == to_fpup) + return; + + if (from_fpup) + __asm_vfp_save(from_fpup, fpexc); + + __asm_vfp_load(to_fpup, cpu); + } else { + /* + * We are restoring the Linux current thread. The FPU + * can be disabled, so that a fault will occur if the + * newly switched thread uses the FPU, to allow the + * kernel handler to pick the correct FPU context, and + * save in the same move the last used RT context. + */ + vfp_current_hw_state[cpu] = from_fpup; +#ifdef CONFIG_SMP + /* + * On SMP, since returning to FPU disabled mode means + * that we have to save fpu, avoid doing it if + * current FPU context belongs to the task we are + * switching to. + */ + if (from_fpup) { + union vfp_state *const current_task_fpup = + &to->tcb.core.tip->vfpstate; + const unsigned fpdis = do_vfp_fmrx(FPEXC); + const unsigned fpen = fpdis | FPEXC_EN; + + do_vfp_fmxr(FPEXC, fpen & ~XNARCH_VFP_ANY_EXC); + if (from_fpup == current_task_fpup) + return; + + __asm_vfp_save(from_fpup, fpen); + do_vfp_fmxr(FPEXC, fpdis); + } +#endif + } +} + +int xnarch_handle_fpu_fault(struct xnthread *from, + struct xnthread *to, struct ipipe_trap_data *d) +{ + spl_t s; + + if (xnthread_test_state(to, XNFPU)) + /* FPU is already enabled, probably an exception */ + return 0; + +#if __LINUX_ARM_ARCH__ <= 6 + if (!static_key_true(&__xeno_vfp_key)) + /* VFP instruction emitted, on a cpu without VFP, this + is an error */ + return 0; +#endif + + xnlock_get_irqsave(&nklock, s); + xnthread_set_state(to, XNFPU); + xnlock_put_irqrestore(&nklock, s); + + xnarch_switch_fpu(from, to); + + /* Retry faulting instruction */ + d->regs->ARM_pc = xnarch_fault_pc(d); + return 1; +} + +void xnarch_init_shadow_tcb(struct xnthread *thread) +{ + struct xnarchtcb *tcb = xnthread_archtcb(thread); + + tcb->fpup = &task_thread_info(tcb->core.host_task)->vfpstate; + + if (vfp_checked == 0) { + mutex_lock(&vfp_check_lock); + if (vfp_checked == 0) { + if ((elf_hwcap & HWCAP_VFP) == 0) + static_key_slow_dec(&__xeno_vfp_key); + vfp_checked = 1; + } + mutex_unlock(&vfp_check_lock); + } + + /* XNFPU is set upon first FPU fault */ + xnthread_clear_state(thread, XNFPU); +} +#endif /* CONFIG_XENO_ARCH_FPU && CONFIG_VFP*/ + +void xnarch_switch_to(struct xnthread *out, struct xnthread *in) +{ + struct xnarchtcb *out_tcb = &out->tcb, *in_tcb = &in->tcb; + struct mm_struct *prev_mm, *next_mm; + struct task_struct *next; + + next = in_tcb->core.host_task; + prev_mm = out_tcb->core.active_mm; + + next_mm = in_tcb->core.mm; + if (next_mm == NULL) { + in_tcb->core.active_mm = prev_mm; + enter_lazy_tlb(prev_mm, next); + } else { + ipipe_switch_mm_head(prev_mm, next_mm, next); + /* + * We might be switching back to the root thread, + * which we preempted earlier, shortly after "current" + * dropped its mm context in the do_exit() path + * (next->mm == NULL). In that particular case, the + * kernel expects a lazy TLB state for leaving the mm. + */ + if (next->mm == NULL) + enter_lazy_tlb(prev_mm, next); + } + + __asm_thread_switch(out_tcb->core.tip, in_tcb->core.tip); +} + +int xnarch_escalate(void) +{ + if (ipipe_root_p) { + ipipe_raise_irq(cobalt_pipeline.escalate_virq); + return 1; + } + + return 0; +} diff --git a/lib/cobalt/arch/Makefile.am b/lib/cobalt/arch/Makefile.am index 3073a3f..608cda1 100644 --- a/lib/cobalt/arch/Makefile.am +++ b/lib/cobalt/arch/Makefile.am @@ -1,4 +1,4 @@ SUBDIRS = @XENO_TARGET_ARCH@ -DIST_SUBDIRS = arm blackfin powerpc x86 +DIST_SUBDIRS = arm arm64 blackfin powerpc x86 diff --git a/lib/cobalt/arch/arm64/Makefile.am b/lib/cobalt/arch/arm64/Makefile.am new file mode 100644 index 0000000..0aa02d6 --- /dev/null +++ b/lib/cobalt/arch/arm64/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libarch.la + +libarch_la_LDFLAGS = @XENO_LIB_LDFLAGS@ -version-info 0:0:0 + +libarch_la_SOURCES = features.c + +libarch_la_CPPFLAGS = \ + @XENO_COBALT_CFLAGS@ \ + -I$(srcdir)/../.. \ + -I$(top_srcdir)/include/cobalt \ + -I$(top_srcdir)/include + +SUBDIRS = include diff --git a/lib/cobalt/arch/arm64/features.c b/lib/cobalt/arch/arm64/features.c new file mode 100644 index 0000000..edabcf2 --- /dev/null +++ b/lib/cobalt/arch/arm64/features.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2011 Gilles Chanteperdrix <g...@xenomai.org>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include <cobalt/wrappers.h> +#include <asm/xenomai/syscall.h> +#include <asm/xenomai/tsc.h> +#include <asm/xenomai/features.h> +#include <asm/xenomai/uapi/fptest.h> +#include "internal.h" + +struct __xn_full_tscinfo __xn_tscinfo = { + .kinfo = { + .counter = NULL, + }, +}; + +void cobalt_check_features(struct cobalt_featinfo *finfo) +{ + unsigned long phys_addr; + unsigned page_size; + int err, fd; + void *addr; + + if (__xn_tscinfo.kinfo.counter != NULL) + return; + + err = XENOMAI_SYSCALL2(sc_cobalt_archcall, + XENOMAI_SYSARCH_TSCINFO, &__xn_tscinfo.kinfo); + if (err) + early_panic("missing TSC emulation: %s", + strerror(-err)); + + fd = __STD(open("/dev/mem", O_RDONLY | O_SYNC)); + if (fd == -1) + early_panic("failed open(/dev/mem): %s", strerror(errno)); + + page_size = sysconf(_SC_PAGESIZE); + + __xn_tscinfo.kuser_tsc_get = + (__xn_rdtsc_t *)(0xffff1004 - + ((*(unsigned *)(0xffff0ffc) + 3) << 5)); + + phys_addr = (unsigned long)__xn_tscinfo.kinfo.counter; + + addr = __STD(mmap(NULL, page_size, PROT_READ, MAP_SHARED, + fd, phys_addr & ~(page_size - 1))); + if (addr == MAP_FAILED) + early_panic("failed mmap(/dev/mem): %s", strerror(errno)); + + __xn_tscinfo.kinfo.counter = + ((volatile unsigned *) + ((char *) addr + (phys_addr & (page_size - 1)))); + + __STD(close(fd)); +} + +int cobalt_fp_detect(void) +{ + char buffer[1024]; + int features = 0; + FILE *fp; + + fp = fopen("/proc/cpuinfo", "r"); + if (fp == NULL) + return 0; + + while (fgets(buffer, sizeof(buffer), fp)) { + if(strncmp(buffer, "Features", sizeof("Features") - 1)) + continue; + if (strstr(buffer, "vfp")) { + features |= __COBALT_HAVE_VFP; + break; + } + } + + fclose(fp); + + return features; +} diff --git a/lib/cobalt/arch/arm64/include/Makefile.am b/lib/cobalt/arch/arm64/include/Makefile.am new file mode 100644 index 0000000..5cac5d2 --- /dev/null +++ b/lib/cobalt/arch/arm64/include/Makefile.am @@ -0,0 +1,2 @@ + +SUBDIRS = asm diff --git a/lib/cobalt/arch/arm64/include/asm/Makefile.am b/lib/cobalt/arch/arm64/include/asm/Makefile.am new file mode 100644 index 0000000..55ea661 --- /dev/null +++ b/lib/cobalt/arch/arm64/include/asm/Makefile.am @@ -0,0 +1,2 @@ + +SUBDIRS = xenomai diff --git a/lib/cobalt/arch/arm64/include/asm/xenomai/Makefile.am b/lib/cobalt/arch/arm64/include/asm/xenomai/Makefile.am new file mode 100644 index 0000000..d308b06 --- /dev/null +++ b/lib/cobalt/arch/arm64/include/asm/xenomai/Makefile.am @@ -0,0 +1,5 @@ + +noinst_HEADERS = \ + features.h \ + syscall.h \ + tsc.h diff --git a/lib/cobalt/arch/arm64/include/asm/xenomai/features.h b/lib/cobalt/arch/arm64/include/asm/xenomai/features.h new file mode 100644 index 0000000..10bd0c7 --- /dev/null +++ b/lib/cobalt/arch/arm64/include/asm/xenomai/features.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005 Philippe Gerum <r...@xenomai.org>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef _LIB_COBALT_ARM_FEATURES_H +#define _LIB_COBALT_ARM_FEATURES_H + +#include_next <features.h> +#include <xeno_config.h> + +#if defined(__ARM_ARCH_2__) +#define __LINUX_ARM_ARCH__ 2 +#endif /* armv2 */ + +#if defined(__ARM_ARCH_3__) +#define __LINUX_ARM_ARCH__ 3 +#endif /* armv3 */ + +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) +#define __LINUX_ARM_ARCH__ 4 +#endif /* armv4 */ + +#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) +#define __LINUX_ARM_ARCH__ 5 +#endif /* armv5 */ + +#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) +#define __LINUX_ARM_ARCH__ 6 +#endif /* armv6 */ + +#if defined(__ARM_ARCH_7A__) +#define __LINUX_ARM_ARCH__ 7 +#endif /* armv7 */ + +#ifndef __LINUX_ARM_ARCH__ +#error "Could not find current ARM architecture" +#endif + +#if __LINUX_ARM_ARCH__ < 6 && defined(CONFIG_SMP) +#error "SMP not supported below armv6, compile with -march=armv6 or above" +#endif + +#include <asm/xenomai/uapi/features.h> + +int cobalt_fp_detect(void); + +#endif /* !_LIB_COBALT_ARM_FEATURES_H */ diff --git a/lib/cobalt/arch/arm64/include/asm/xenomai/syscall.h b/lib/cobalt/arch/arm64/include/asm/xenomai/syscall.h new file mode 100644 index 0000000..8f48eb1 --- /dev/null +++ b/lib/cobalt/arch/arm64/include/asm/xenomai/syscall.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2001,2002,2003,2004 Philippe Gerum <r...@xenomai.org>. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef _LIB_COBALT_ARM_SYSCALL_H +#define _LIB_COBALT_ARM_SYSCALL_H + +#include <xeno_config.h> +#include <errno.h> +#include <cobalt/uapi/syscall.h> + +/* + * Some of the following macros have been adapted from Linux's + * implementation of the syscall mechanism in <asm-arm/unistd.h>: + */ +#if defined(HAVE_TLS) && __GNUC__ == 4 && __GNUC_MINOR__ >= 3 +#error TLS support (__thread) is broken with GCC >= 4.3, use --disable-tls when configuring +#endif + +#define LOADARGS_0(syscode, dummy...) \ + __a0 = (unsigned long) (syscode) +#define LOADARGS_1(syscode, arg1) \ + LOADARGS_0(syscode); \ + __a1 = (unsigned long) (arg1) +#define LOADARGS_2(syscode, arg1, arg2) \ + LOADARGS_1(syscode, arg1); \ + __a2 = (unsigned long) (arg2) +#define LOADARGS_3(syscode, arg1, arg2, arg3) \ + LOADARGS_2(syscode, arg1, arg2); \ + __a3 = (unsigned long) (arg3) +#define LOADARGS_4(syscode, arg1, arg2, arg3, arg4) \ + LOADARGS_3(syscode, arg1, arg2, arg3); \ + __a4 = (unsigned long) (arg4) +#define LOADARGS_5(syscode, arg1, arg2, arg3, arg4, arg5) \ + LOADARGS_4(syscode, arg1, arg2, arg3, arg4); \ + __a5 = (unsigned long) (arg5) + +#define CLOBBER_REGS_0 "r0" +#define CLOBBER_REGS_1 CLOBBER_REGS_0, "r1" +#define CLOBBER_REGS_2 CLOBBER_REGS_1, "r2" +#define CLOBBER_REGS_3 CLOBBER_REGS_2, "r3" +#define CLOBBER_REGS_4 CLOBBER_REGS_3, "r4" +#define CLOBBER_REGS_5 CLOBBER_REGS_4, "r5" + +#define LOADREGS_0 __r0 = __a0 +#define LOADREGS_1 LOADREGS_0; __r1 = __a1 +#define LOADREGS_2 LOADREGS_1; __r2 = __a2 +#define LOADREGS_3 LOADREGS_2; __r3 = __a3 +#define LOADREGS_4 LOADREGS_3; __r4 = __a4 +#define LOADREGS_5 LOADREGS_4; __r5 = __a5 + +#define ASM_INDECL_0 \ + unsigned long __a0; register unsigned long __r0 __asm__ ("r0"); +#define ASM_INDECL_1 ASM_INDECL_0; \ + unsigned long __a1; register unsigned long __r1 __asm__ ("r1") +#define ASM_INDECL_2 ASM_INDECL_1; \ + unsigned long __a2; register unsigned long __r2 __asm__ ("r2") +#define ASM_INDECL_3 ASM_INDECL_2; \ + unsigned long __a3; register unsigned long __r3 __asm__ ("r3") +#define ASM_INDECL_4 ASM_INDECL_3; \ + unsigned long __a4; register unsigned long __r4 __asm__ ("r4") +#define ASM_INDECL_5 ASM_INDECL_4; \ + unsigned long __a5; register unsigned long __r5 __asm__ ("r5") + +#define ASM_INPUT_0 "0" (__r0) +#define ASM_INPUT_1 ASM_INPUT_0, "r" (__r1) +#define ASM_INPUT_2 ASM_INPUT_1, "r" (__r2) +#define ASM_INPUT_3 ASM_INPUT_2, "r" (__r3) +#define ASM_INPUT_4 ASM_INPUT_3, "r" (__r4) +#define ASM_INPUT_5 ASM_INPUT_4, "r" (__r5) + +#define __sys2(x) #x +#define __sys1(x) __sys2(x) + +#ifdef __ARM_EABI__ +#define __SYS_REG , "r7" +#define __SYS_REG_DECL register unsigned long __r7 __asm__ ("r7") +#define __SYS_REG_SET __r7 = XENO_ARM_SYSCALL +#define __SYS_REG_INPUT ,"r" (__r7) +#define __SYS_CALLOP "swi\t0" +#else +#define __SYS_REG +#define __SYS_REG_DECL +#define __SYS_REG_SET +#define __SYS_REG_INPUT +#define __NR_OABI_SYSCALL_BASE 0x900000 +#define __SYS_CALLOP "swi\t" __sys1(__NR_OABI_SYSCALL_BASE + XENO_ARM_SYSCALL) "" +#endif + +#define XENOMAI_DO_SYSCALL(nr, op, args...) \ + ({ \ + ASM_INDECL_##nr; \ + __SYS_REG_DECL; \ + LOADARGS_##nr(__xn_syscode(op), args); \ + __asm__ __volatile__ ("" : /* */ : /* */ : \ + CLOBBER_REGS_##nr __SYS_REG); \ + LOADREGS_##nr; \ + __SYS_REG_SET; \ + __asm__ __volatile__ ( \ + __SYS_CALLOP \ + : "=r" (__r0) \ + : ASM_INPUT_##nr __SYS_REG_INPUT \ + : "memory"); \ + (int) __r0; \ + }) + +#define XENOMAI_SYSCALL0(op) \ + XENOMAI_DO_SYSCALL(0,op) +#define XENOMAI_SYSCALL1(op,a1) \ + XENOMAI_DO_SYSCALL(1,op,a1) +#define XENOMAI_SYSCALL2(op,a1,a2) \ + XENOMAI_DO_SYSCALL(2,op,a1,a2) +#define XENOMAI_SYSCALL3(op,a1,a2,a3) \ + XENOMAI_DO_SYSCALL(3,op,a1,a2,a3) +#define XENOMAI_SYSCALL4(op,a1,a2,a3,a4) \ + XENOMAI_DO_SYSCALL(4,op,a1,a2,a3,a4) +#define XENOMAI_SYSCALL5(op,a1,a2,a3,a4,a5) \ + XENOMAI_DO_SYSCALL(5,op,a1,a2,a3,a4,a5) +#define XENOMAI_SYSBIND(breq) \ + XENOMAI_DO_SYSCALL(1,sc_cobalt_bind,breq) + +#endif /* !_LIB_COBALT_ARM_SYSCALL_H */ diff --git a/lib/cobalt/arch/arm64/include/asm/xenomai/tsc.h b/lib/cobalt/arch/arm64/include/asm/xenomai/tsc.h new file mode 100644 index 0000000..594c4ad --- /dev/null +++ b/lib/cobalt/arch/arm64/include/asm/xenomai/tsc.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2001,2002,2003,2004 Philippe Gerum <r...@xenomai.org>. + * Copyright (C) 2013 Gilles Chanteperdrix <g...@xenomai.org>. + * + * ARM port + * Copyright (C) 2005 Stelian Pop + * + * Copyright (C) 2007 Sebastian Smolorz <se...@gmx.net> + * Support for TSC emulation in user space for decrementing counters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef _LIB_COBALT_ARM_TSC_H +#define _LIB_COBALT_ARM_TSC_H + +#include <asm/xenomai/uapi/tsc.h> +#include <asm/xenomai/features.h> + +/* + * Putting kuser_tsc_get and kinfo.counter in the same struct results + * in less operations in PIC code, thus optimizes. + */ +typedef unsigned long long __xn_rdtsc_t(volatile unsigned *vaddr); +struct __xn_full_tscinfo { + __xn_rdtsc_t *kuser_tsc_get; + struct __xn_tscinfo kinfo; +}; +extern struct __xn_full_tscinfo __xn_tscinfo; + +static inline __attribute__((always_inline)) +unsigned long long cobalt_read_tsc(void) +{ + return __xn_tscinfo.kuser_tsc_get(__xn_tscinfo.kinfo.counter); +} + +#endif /* !_LIB_COBALT_ARM_TSC_H */ _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git