summaryrefslogtreecommitdiff
path: root/arch/arm64
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-22 03:40:16 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-22 03:40:16 +0400
commit8b5628ab83b671f96ac9f174c1bd51c92589fc82 (patch)
tree8446b0fce80923c3694fe075ffcde7e422bcf818 /arch/arm64
parenta8f3740feb12928be1aad19659bf3527ea8d6d96 (diff)
parentfe7dc7202d7d24fe211e0eecf531d8b79b655b3c (diff)
downloadlinux-8b5628ab83b671f96ac9f174c1bd51c92589fc82.tar.xz
Merge tag 'virt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM virtualization changes: "This contains parts of the ARM KVM support that have dependencies on other patches merged through the arm-soc tree. In combination with patches coming through Russell's tree, this will finally add full support for the kernel based virtual machine on ARM, which has been awaited for some time now. Further, we now have a separate platform for virtual machines and qemu booting that is used by both Xen and KVM, separating these from the Versatile Express reference implementation. Obviously, this new platform is multiplatform capable so it can be combined with existing machines in the same kernel." * tag 'virt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (38 commits) ARM: arch_timer: include linux/errno.h arm: arch_timer: add missing inline in stub function ARM: KVM: arch_timers: Wire the init code and config option ARM: KVM: arch_timers: Add timer world switch ARM: KVM: arch_timers: Add guest timer core support ARM: KVM: Add VGIC configuration option ARM: KVM: VGIC initialisation code ARM: KVM: VGIC control interface world switch ARM: KVM: VGIC interrupt injection ARM: KVM: vgic: retire queued, disabled interrupts ARM: KVM: VGIC virtual CPU interface management ARM: KVM: VGIC distributor handling ARM: KVM: VGIC accept vcpu and dist base addresses from user space ARM: KVM: Initial VGIC infrastructure code ARM: KVM: Keep track of currently running vcpus KVM: ARM: Introduce KVM_ARM_SET_DEVICE_ADDR ioctl ARM: gic: add __ASSEMBLY__ guard to C definitions ARM: gic: define GICH offsets for VGIC support ARM: gic: add missing distributor defintions ARM: mach-virt: fixup machine descriptor after removal of sys_timer ...
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/include/asm/arch_timer.h133
-rw-r--r--arch/arm64/include/asm/arm_generic.h100
-rw-r--r--arch/arm64/kernel/time.c29
4 files changed, 161 insertions, 102 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 7c43569e3141..ab4aa54b36ef 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -4,6 +4,7 @@ config ARM64
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
select ARCH_WANT_FRAME_POINTERS
select ARM_AMBA
+ select ARM_ARCH_TIMER
select CLONE_BACKWARDS
select COMMON_CLK
select GENERIC_CLOCKEVENTS
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
new file mode 100644
index 000000000000..91e2a6a6fcd4
--- /dev/null
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -0,0 +1,133 @@
+/*
+ * arch/arm64/include/asm/arch_timer.h
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 __ASM_ARCH_TIMER_H
+#define __ASM_ARCH_TIMER_H
+
+#include <asm/barrier.h>
+
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <clocksource/arm_arch_timer.h>
+
+static inline void arch_timer_reg_write(int access, int reg, u32 val)
+{
+ if (access == ARCH_TIMER_PHYS_ACCESS) {
+ switch (reg) {
+ case ARCH_TIMER_REG_CTRL:
+ asm volatile("msr cntp_ctl_el0, %0" : : "r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+ asm volatile("msr cntp_tval_el0, %0" : : "r" (val));
+ break;
+ default:
+ BUILD_BUG();
+ }
+ } else if (access == ARCH_TIMER_VIRT_ACCESS) {
+ switch (reg) {
+ case ARCH_TIMER_REG_CTRL:
+ asm volatile("msr cntv_ctl_el0, %0" : : "r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+ asm volatile("msr cntv_tval_el0, %0" : : "r" (val));
+ break;
+ default:
+ BUILD_BUG();
+ }
+ } else {
+ BUILD_BUG();
+ }
+
+ isb();
+}
+
+static inline u32 arch_timer_reg_read(int access, int reg)
+{
+ u32 val;
+
+ if (access == ARCH_TIMER_PHYS_ACCESS) {
+ switch (reg) {
+ case ARCH_TIMER_REG_CTRL:
+ asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+ asm volatile("mrs %0, cntp_tval_el0" : "=r" (val));
+ break;
+ default:
+ BUILD_BUG();
+ }
+ } else if (access == ARCH_TIMER_VIRT_ACCESS) {
+ switch (reg) {
+ case ARCH_TIMER_REG_CTRL:
+ asm volatile("mrs %0, cntv_ctl_el0" : "=r" (val));
+ break;
+ case ARCH_TIMER_REG_TVAL:
+ asm volatile("mrs %0, cntv_tval_el0" : "=r" (val));
+ break;
+ default:
+ BUILD_BUG();
+ }
+ } else {
+ BUILD_BUG();
+ }
+
+ return val;
+}
+
+static inline u32 arch_timer_get_cntfrq(void)
+{
+ u32 val;
+ asm volatile("mrs %0, cntfrq_el0" : "=r" (val));
+ return val;
+}
+
+static inline void __cpuinit arch_counter_set_user_access(void)
+{
+ u32 cntkctl;
+
+ /* Disable user access to the timers and the physical counter. */
+ asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl));
+ cntkctl &= ~((3 << 8) | (1 << 0));
+
+ /* Enable user access to the virtual counter and frequency. */
+ cntkctl |= (1 << 1);
+ asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl));
+}
+
+static inline u64 arch_counter_get_cntpct(void)
+{
+ u64 cval;
+
+ isb();
+ asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
+
+ return cval;
+}
+
+static inline u64 arch_counter_get_cntvct(void)
+{
+ u64 cval;
+
+ isb();
+ asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
+
+ return cval;
+}
+
+#endif
diff --git a/arch/arm64/include/asm/arm_generic.h b/arch/arm64/include/asm/arm_generic.h
deleted file mode 100644
index df2aeb82f74e..000000000000
--- a/arch/arm64/include/asm/arm_generic.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * arch/arm64/include/asm/arm_generic.h
- *
- * Copyright (C) 2012 ARM Ltd.
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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 __ASM_ARM_GENERIC_H
-#define __ASM_ARM_GENERIC_H
-
-#include <linux/clocksource.h>
-
-#define ARCH_TIMER_CTRL_ENABLE (1 << 0)
-#define ARCH_TIMER_CTRL_IMASK (1 << 1)
-#define ARCH_TIMER_CTRL_ISTATUS (1 << 2)
-
-#define ARCH_TIMER_REG_CTRL 0
-#define ARCH_TIMER_REG_FREQ 1
-#define ARCH_TIMER_REG_TVAL 2
-
-static inline void arch_timer_reg_write(int reg, u32 val)
-{
- switch (reg) {
- case ARCH_TIMER_REG_CTRL:
- asm volatile("msr cntp_ctl_el0, %0" : : "r" (val));
- break;
- case ARCH_TIMER_REG_TVAL:
- asm volatile("msr cntp_tval_el0, %0" : : "r" (val));
- break;
- default:
- BUILD_BUG();
- }
-
- isb();
-}
-
-static inline u32 arch_timer_reg_read(int reg)
-{
- u32 val;
-
- switch (reg) {
- case ARCH_TIMER_REG_CTRL:
- asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val));
- break;
- case ARCH_TIMER_REG_FREQ:
- asm volatile("mrs %0, cntfrq_el0" : "=r" (val));
- break;
- case ARCH_TIMER_REG_TVAL:
- asm volatile("mrs %0, cntp_tval_el0" : "=r" (val));
- break;
- default:
- BUILD_BUG();
- }
-
- return val;
-}
-
-static inline void __cpuinit arch_counter_enable_user_access(void)
-{
- u32 cntkctl;
-
- /* Disable user access to the timers and the physical counter. */
- asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl));
- cntkctl &= ~((3 << 8) | (1 << 0));
-
- /* Enable user access to the virtual counter and frequency. */
- cntkctl |= (1 << 1);
- asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl));
-}
-
-static inline cycle_t arch_counter_get_cntpct(void)
-{
- cycle_t cval;
-
- asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
-
- return cval;
-}
-
-static inline cycle_t arch_counter_get_cntvct(void)
-{
- cycle_t cval;
-
- asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
-
- return cval;
-}
-
-#endif
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 3b4b7258f492..b0ef18d14c3b 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -31,8 +31,9 @@
#include <linux/syscore_ops.h>
#include <linux/timer.h>
#include <linux/irq.h>
+#include <linux/delay.h>
-#include <clocksource/arm_generic.h>
+#include <clocksource/arm_arch_timer.h>
#include <asm/thread_info.h>
#include <asm/stacktrace.h>
@@ -59,7 +60,31 @@ unsigned long profile_pc(struct pt_regs *regs)
EXPORT_SYMBOL(profile_pc);
#endif
+static u64 sched_clock_mult __read_mostly;
+
+unsigned long long notrace sched_clock(void)
+{
+ return arch_timer_read_counter() * sched_clock_mult;
+}
+
+int read_current_timer(unsigned long *timer_value)
+{
+ *timer_value = arch_timer_read_counter();
+ return 0;
+}
+
void __init time_init(void)
{
- arm_generic_timer_init();
+ u32 arch_timer_rate;
+
+ if (arch_timer_init())
+ panic("Unable to initialise architected timer.\n");
+
+ arch_timer_rate = arch_timer_get_rate();
+
+ /* Cache the sched_clock multiplier to save a divide in the hot path. */
+ sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;
+
+ /* Calibrate the delay loop directly */
+ lpj_fine = arch_timer_rate / HZ;
}