Commit 72c3c95e authored by Don Mahurin's avatar Don Mahurin Committed by Philippe Gerum
Browse files

arm64/ipipe: apply ipipe-3.10 arch/arm/{kernel,include,asm,Kconfig} changes to arch/arm64/kernel

parent 77c078a7
......@@ -86,6 +86,11 @@ config ARM64
help
ARM 64-bit (AArch64) Linux support.
if IPIPE
config IPIPE_WANT_ACTIVE_MM
def_bool y
endif
config 64BIT
def_bool y
......@@ -529,6 +534,8 @@ config HOTPLUG_CPU
Say Y here to experiment with turning CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu.
source kernel/ipipe/Kconfig
source kernel/Kconfig.preempt
config UP_LATE_INIT
......
......@@ -49,6 +49,18 @@
msr daifclr, #2
.endm
.macro disable_irq_cond
#ifdef CONFIG_IPIPE
msr daifset, #2
#endif
.endm
.macro enable_irq_cond
#ifdef CONFIG_IPIPE
msr daifclr, #2
#endif
.endm
/*
* Save/disable and restore interrupts.
*/
......
/* -*- linux-c -*-
* arch/arm/include/asm/ipipe.h
*
* Copyright (C) 2002-2005 Philippe Gerum.
* Copyright (C) 2005 Stelian Pop.
* Copyright (C) 2006-2008 Gilles Chanteperdrix.
* Copyright (C) 2010 Philippe Gerum (SMP port).
*
* 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.
*/
#ifndef __ARM_IPIPE_H
#define __ARM_IPIPE_H
#ifdef CONFIG_IPIPE
#define BROKEN_BUILTIN_RETURN_ADDRESS
#undef __BUILTIN_RETURN_ADDRESS0
#undef __BUILTIN_RETURN_ADDRESS1
#ifdef CONFIG_FRAME_POINTER
#define __BUILTIN_RETURN_ADDRESS0 arm_return_addr(0)
#define __BUILTIN_RETURN_ADDRESS1 arm_return_addr(1)
extern unsigned long arm_return_addr(int level);
#else
#define __BUILTIN_RETURN_ADDRESS0 ((unsigned long)__builtin_return_address(0))
#define __BUILTIN_RETURN_ADDRESS1 (0)
#endif
#include <linux/jump_label.h>
#include <linux/ipipe_trace.h>
#define IPIPE_CORE_RELEASE 7
struct ipipe_domain;
#define IPIPE_TSC_TYPE_NONE 0
#define IPIPE_TSC_TYPE_FREERUNNING 1
#define IPIPE_TSC_TYPE_DECREMENTER 2
#define IPIPE_TSC_TYPE_FREERUNNING_COUNTDOWN 3
#define IPIPE_TSC_TYPE_FREERUNNING_TWICE 4
#define IPIPE_TSC_TYPE_FREERUNNING_ARCH 5
/* tscinfo, exported to user-space */
struct __ipipe_tscinfo {
unsigned type;
unsigned freq;
unsigned long counter_vaddr;
union {
struct {
unsigned long counter_paddr;
unsigned long long mask;
};
struct {
unsigned *counter; /* Hw counter physical address */
unsigned long long mask; /* Significant bits in the hw counter. */
unsigned long long *tsc; /* 64 bits tsc value. */
} fr;
struct {
unsigned *counter; /* Hw counter physical address */
unsigned long long mask; /* Significant bits in the hw counter. */
unsigned *last_cnt; /* Counter value when updating
tsc value. */
unsigned long long *tsc; /* 64 bits tsc value. */
} dec;
} u;
};
struct ipipe_arch_sysinfo {
struct __ipipe_tscinfo tsc;
};
/* arch specific stuff */
extern char __ipipe_tsc_area[];
void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info);
#ifdef CONFIG_IPIPE_ARM_KUSER_TSC
unsigned long long __ipipe_tsc_get(void) __attribute__((long_call));
void __ipipe_tsc_register(struct __ipipe_tscinfo *info);
void __ipipe_tsc_update(void);
extern unsigned long __ipipe_kuser_tsc_freq;
#define __ipipe_hrclock_freq __ipipe_kuser_tsc_freq
#else /* ! generic tsc */
unsigned long long __ipipe_mach_get_tsc(void);
#define __ipipe_tsc_get() __ipipe_mach_get_tsc()
#ifndef __ipipe_hrclock_freq
extern unsigned long __ipipe_hrtimer_freq;
#define __ipipe_hrclock_freq __ipipe_hrtimer_freq
#endif /* !__ipipe_mach_hrclock_freq */
#endif /* ! generic tsc */
#ifdef CONFIG_IPIPE_DEBUG_INTERNAL
extern void (*__ipipe_mach_hrtimer_debug)(unsigned irq);
#endif /* CONFIG_IPIPE_DEBUG_INTERNAL */
#ifdef CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH
#define ipipe_mm_switch_protect(flags) \
do { \
(void)(flags); \
} while(0)
#define ipipe_mm_switch_unprotect(flags) \
do { \
(void)(flags); \
} while(0)
#else /* !CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH */
#define ipipe_mm_switch_protect(flags) \
flags = hard_cond_local_irq_save()
#define ipipe_mm_switch_unprotect(flags) \
hard_cond_local_irq_restore(flags)
#endif /* !CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH */
#define ipipe_get_active_mm() (__this_cpu_read(ipipe_percpu.active_mm))
#define ipipe_read_tsc(t) do { t = __ipipe_tsc_get(); } while(0)
#define __ipipe_read_timebase() __ipipe_tsc_get()
#define ipipe_tsc2ns(t) \
({ \
unsigned long long delta = (t)*1000; \
do_div(delta, __ipipe_hrclock_freq / 1000000 + 1); \
(unsigned long)delta; \
})
#define ipipe_tsc2us(t) \
({ \
unsigned long long delta = (t); \
do_div(delta, __ipipe_hrclock_freq / 1000000 + 1); \
(unsigned long)delta; \
})
static inline const char *ipipe_clock_name(void)
{
return "ipipe_tsc";
}
/* Private interface -- Internal use only */
#define __ipipe_enable_irq(irq) enable_irq(irq)
#define __ipipe_disable_irq(irq) disable_irq(irq)
/* PIC muting */
struct ipipe_mach_pic_muter {
void (*enable_irqdesc)(struct ipipe_domain *ipd, unsigned irq);
void (*disable_irqdesc)(struct ipipe_domain *ipd, unsigned irq);
void (*mute)(void);
void (*unmute)(void);
};
extern struct ipipe_mach_pic_muter ipipe_pic_muter;
void ipipe_pic_muter_register(struct ipipe_mach_pic_muter *muter);
void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq);
void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq);
static inline void ipipe_mute_pic(void)
{
if (ipipe_pic_muter.mute)
ipipe_pic_muter.mute();
}
static inline void ipipe_unmute_pic(void)
{
if (ipipe_pic_muter.unmute)
ipipe_pic_muter.unmute();
}
#define ipipe_notify_root_preemption() do { } while(0)
#ifdef CONFIG_SMP
void __ipipe_early_core_setup(void);
void __ipipe_hook_critical_ipi(struct ipipe_domain *ipd);
void __ipipe_root_localtimer(unsigned int irq, void *cookie);
void __ipipe_send_vnmi(void (*fn)(void *), cpumask_t cpumask, void *arg);
void __ipipe_do_vnmi(unsigned int irq, void *cookie);
void __ipipe_grab_ipi(unsigned svc, struct pt_regs *regs);
void __ipipe_ipis_alloc(void);
void __ipipe_ipis_request(void);
static inline void ipipe_handle_multi_ipi(int irq, struct pt_regs *regs)
{
__ipipe_grab_ipi(irq, regs);
}
#ifdef CONFIG_SMP_ON_UP
extern struct static_key __ipipe_smp_key;
#define ipipe_smp_p (static_key_true(&__ipipe_smp_key))
#endif /* SMP_ON_UP */
#else /* !CONFIG_SMP */
#define __ipipe_early_core_setup() do { } while(0)
#define __ipipe_hook_critical_ipi(ipd) do { } while(0)
#endif /* !CONFIG_SMP */
#ifndef __ipipe_mach_init_platform
#define __ipipe_mach_init_platform() do { } while(0)
#endif
void __ipipe_enable_pipeline(void);
void __ipipe_do_critical_sync(unsigned irq, void *cookie);
void __ipipe_grab_irq(int irq, struct pt_regs *regs);
void __ipipe_exit_irq(struct pt_regs *regs);
static inline void ipipe_handle_multi_irq(int irq, struct pt_regs *regs)
{
__ipipe_grab_irq(irq, regs);
}
static inline unsigned long __ipipe_ffnz(unsigned long ul)
{
return ffs(ul) - 1;
}
#define __ipipe_syscall_watched_p(p, sc) \
(ipipe_notifier_enabled_p(p) || (unsigned long)sc >= __NR_syscalls)
#define __ipipe_root_tick_p(regs) (!arch_irqs_disabled_flags(regs->ARM_cpsr))
#else /* !CONFIG_IPIPE */
#define __ipipe_tsc_update() do { } while(0)
#define hard_smp_processor_id() smp_processor_id()
#define ipipe_mm_switch_protect(flags) \
do { \
(void) (flags); \
} while(0)
#define ipipe_mm_switch_unprotect(flags) \
do { \
(void) (flags); \
} while(0)
static inline void ipipe_handle_multi_irq(int irq, struct pt_regs *regs)
{
handle_IRQ(irq, regs);
}
#ifdef CONFIG_SMP
static inline void ipipe_handle_multi_ipi(int irq, struct pt_regs *regs)
{
handle_IPI(irq, regs);
}
#endif /* CONFIG_SMP */
#endif /* CONFIG_IPIPE */
#if defined (CONFIG_IPIPE_DEBUG) && \
(defined(CONFIG_DEBUG_LL) || defined(CONFIG_SERIAL_8250_CONSOLE))
void __ipipe_serial_debug(const char *fmt, ...);
#else
#define __ipipe_serial_debug(fmt, args...) do { } while (0)
#endif
#endif /* !__ARM_IPIPE_H */
/* -*- linux-c -*-
* arch/arm/include/asm/ipipe_base.h
*
* Copyright (C) 2007 Gilles Chanteperdrix.
* Copyright (C) 2010 Philippe Gerum (SMP port).
*
* 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.
*/
#ifndef __ASM_ARM_IPIPE_BASE_H
#define __ASM_ARM_IPIPE_BASE_H
#include <asm/irq.h> /* For NR_IRQS */
#ifdef CONFIG_IPIPE
#define IPIPE_NR_ROOT_IRQS 1024
#define IPIPE_NR_XIRQS IPIPE_NR_ROOT_IRQS
#ifdef CONFIG_SMP
extern unsigned __ipipe_first_ipi;
#define IPIPE_CRITICAL_IPI __ipipe_first_ipi
#define IPIPE_HRTIMER_IPI (IPIPE_CRITICAL_IPI + 1)
#define IPIPE_RESCHEDULE_IPI (IPIPE_CRITICAL_IPI + 2)
#define IPIPE_SERVICE_VNMI (IPIPE_CRITICAL_IPI + 3)
#define IPIPE_LAST_IPI IPIPE_SERVICE_VNMI
#ifdef CONFIG_IPIPE_LEGACY
#define hard_smp_processor_id() \
({ \
unsigned int cpunum; \
__asm__ __volatile__ ("\n" \
"1: mrc p15, 0, %0, c0, c0, 5\n" \
" .pushsection \".alt.smp.init\", \"a\"\n" \
" .long 1b\n" \
" mov %0, #0\n" \
" .popsection" \
: "=r" (cpunum)); \
cpunum &= 0xFF; \
})
extern u32 __cpu_logical_map[];
#define ipipe_processor_id() (__cpu_logical_map[hard_smp_processor_id()])
#else /* !legacy */
#define hard_smp_processor_id() raw_smp_processor_id()
#ifdef CONFIG_SMP_ON_UP
unsigned __ipipe_processor_id(void);
#define ipipe_processor_id() \
({ \
register unsigned int cpunum __asm__ ("r0"); \
register unsigned int r1 __asm__ ("r1"); \
register unsigned int r2 __asm__ ("r2"); \
register unsigned int r3 __asm__ ("r3"); \
register unsigned int ip __asm__ ("ip"); \
register unsigned int lr __asm__ ("lr"); \
__asm__ __volatile__ ("\n" \
"1: bl __ipipe_processor_id\n" \
" .pushsection \".alt.smp.init\", \"a\"\n" \
" .long 1b\n" \
" mov %0, #0\n" \
" .popsection" \
: "=r"(cpunum), "=r"(r1), "=r"(r2), "=r"(r3), \
"=r"(ip), "=r"(lr) \
: /* */ : "cc"); \
cpunum; \
})
#else /* !SMP_ON_UP */
#define ipipe_processor_id() raw_smp_processor_id()
#endif /* !SMP_ON_UP */
#endif /* !legacy */
#define IPIPE_ARCH_HAVE_VIRQ_IPI
#else /* !CONFIG_SMP */
#define ipipe_processor_id() (0)
#endif /* !CONFIG_IPIPE */
/* ARM traps */
#define IPIPE_TRAP_ACCESS 0 /* Data or instruction access exception */
#define IPIPE_TRAP_SECTION 1 /* Section fault */
#define IPIPE_TRAP_DABT 2 /* Generic data abort */
#define IPIPE_TRAP_UNKNOWN 3 /* Unknown exception */
#define IPIPE_TRAP_BREAK 4 /* Instruction breakpoint */
#define IPIPE_TRAP_FPU 5 /* Floating point exception */
#define IPIPE_TRAP_VFP 6 /* VFP floating point exception */
#define IPIPE_TRAP_UNDEFINSTR 7 /* Undefined instruction */
#define IPIPE_TRAP_ALIGNMENT 8 /* Unaligned access exception */
#define IPIPE_TRAP_MAYDAY 9 /* Internal recovery trap */
#define IPIPE_NR_FAULTS 10
#ifndef __ASSEMBLY__
#ifdef CONFIG_SMP
void ipipe_stall_root(void);
unsigned long ipipe_test_and_stall_root(void);
unsigned long ipipe_test_root(void);
#else /* !CONFIG_SMP */
#include <asm/irqflags.h>
#if __GNUC__ >= 4
/* Alias to ipipe_root_cpudom_var(status) */
extern unsigned long __ipipe_root_status;
#else
extern unsigned long *const __ipipe_root_status_addr;
#define __ipipe_root_status (*__ipipe_root_status_addr)
#endif
static inline void ipipe_stall_root(void)
{
unsigned long flags;
flags = hard_local_irq_save();
__ipipe_root_status |= 1;
hard_local_irq_restore(flags);
}
static inline unsigned ipipe_test_root(void)
{
return __ipipe_root_status & 1;
}
static inline unsigned ipipe_test_and_stall_root(void)
{
unsigned long flags, res;
flags = hard_local_irq_save();
res = __ipipe_root_status;
__ipipe_root_status = res | 1;
hard_local_irq_restore(flags);
return res & 1;
}
#endif /* !CONFIG_SMP */
#endif /* !__ASSEMBLY__ */
#ifdef CONFIG_IPIPE_LEGACY
#define __IPIPE_FEATURE_PREEMPTIBLE_SWITCH 1
#define __IPIPE_FEATURE_SYSINFO_V2 1
#ifdef CONFIG_VFP
#define __IPIPE_FEATURE_VFP_SAFE 1
#endif
#ifdef CONFIG_IPIPE_ARM_KUSER_TSC
#define __IPIPE_FEATURE_KUSER_TSC 1
#endif
#endif /* CONFIG_IPIPE_LEGACY */
#endif /* CONFIG_IPIPE */
#endif /* __ASM_ARM_IPIPE_BASE_H */
/* -*- linux-c -*-
* arch/arm/include/asm/ipipe_hwirq.h
*
* Copyright (C) 2002-2005 Philippe Gerum.
* Copyright (C) 2005 Stelian Pop.
* Copyright (C) 2006-2008 Gilles Chanteperdrix.
* Copyright (C) 2010 Philippe Gerum (SMP port).
*
* 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.
*/
#ifndef _ASM_ARM_IPIPE_HWIRQ_H
#define _ASM_ARM_IPIPE_HWIRQ_H
#define hard_local_irq_restore_notrace(x) \
__asm__ __volatile__( \
"msr cpsr_c, %0 @ hard_local_irq_restore\n" \
: \
: "r" (x) \
: "memory", "cc")
static inline void hard_local_irq_disable_notrace(void)
{
#if __LINUX_ARM_ARCH__ >= 6
__asm__("cpsid i @ __cli" : : : "memory", "cc");
#else /* linux arch <= 5 */
unsigned long temp;
__asm__ __volatile__(
"mrs %0, cpsr @ hard_local_irq_disable\n"
"orr %0, %0, #128\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory", "cc");
#endif /* linux arch <= 5 */
}
static inline void hard_local_irq_enable_notrace(void)
{
#if __LINUX_ARM_ARCH__ >= 6
__asm__("cpsie i @ __sti" : : : "memory", "cc");
#else /* linux arch <= 5 */
unsigned long temp;
__asm__ __volatile__(
"mrs %0, cpsr @ hard_local_irq_enable\n"
"bic %0, %0, #128\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory", "cc");
#endif /* linux arch <= 5 */
}
static inline void hard_local_fiq_disable_notrace(void)
{
#if __LINUX_ARM_ARCH__ >= 6
__asm__("cpsid f @ __clf" : : : "memory", "cc");
#else /* linux arch <= 5 */
unsigned long temp;
__asm__ __volatile__(
"mrs %0, cpsr @ clf\n"
"orr %0, %0, #64\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory", "cc");
#endif /* linux arch <= 5 */
}
static inline void hard_local_fiq_enable_notrace(void)
{
#if __LINUX_ARM_ARCH__ >= 6
__asm__("cpsie f @ __stf" : : : "memory", "cc");
#else /* linux arch <= 5 */
unsigned long temp;
__asm__ __volatile__(
"mrs %0, cpsr @ stf\n"
"bic %0, %0, #64\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory", "cc");
#endif /* linux arch <= 5 */
}
static inline unsigned long hard_local_irq_save_notrace(void)
{
unsigned long res;
#if __LINUX_ARM_ARCH__ >= 6
__asm__ __volatile__(
"mrs %0, cpsr @ hard_local_irq_save\n"
"cpsid i"
: "=r" (res) : : "memory", "cc");
#else /* linux arch <= 5 */
unsigned long temp;
__asm__ __volatile__(
"mrs %0, cpsr @ hard_local_irq_save\n"
"orr %1, %0, #128\n"
"msr cpsr_c, %1"
: "=r" (res), "=r" (temp)
:
: "memory", "cc");
#endif /* linux arch <= 5 */
return res;
}
#ifdef CONFIG_IPIPE
#include <linux/ipipe_trace.h>
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return (int)((flags) & PSR_I_BIT);
}
static inline unsigned long hard_local_save_flags(void)
{
unsigned long flags;
__asm__ __volatile__(
"mrs %0, cpsr @ hard_local_save_flags"
: "=r" (flags) : : "memory", "cc");
return flags;
}
#define hard_irqs_disabled_flags(flags) arch_irqs_disabled_flags(flags)
static inline int hard_irqs_disabled(void)