summary refs log tree commit diff
path: root/arch/sparc/kernel/time_64.c
diff options
context:
space:
mode:
authorPavel Tatashin <pasha.tatashin@oracle.com>2017-06-12 16:41:47 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-12 15:44:03 -0700
commit4929c83a6ce6584cb64381bf1407c487f67d588a (patch)
tree49e344e89629324a8af3418dca73db02109abc08 /arch/sparc/kernel/time_64.c
parent83e8eb99d908da78e6eff7dd141f26626fe01d12 (diff)
downloadlinux-4929c83a6ce6584cb64381bf1407c487f67d588a.tar.gz
sparc64: add hot-patched and inlined get_tick()
Add the new get_tick() function that is hot-patched during boot based on
processor we are booting on.

Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com>
Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/time_64.c')
-rw-r--r--arch/sparc/kernel/time_64.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index d149276ddd80..ca27415c393a 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -47,15 +47,13 @@
 #include <asm/cpudata.h>
 #include <linux/uaccess.h>
 #include <asm/irq_regs.h>
+#include <asm/cacheflush.h>
 
 #include "entry.h"
 #include "kernel.h"
 
 DEFINE_SPINLOCK(rtc_lock);
 
-#define TICK_PRIV_BIT	(1UL << 63)
-#define TICKCMP_IRQ_BIT	(1UL << 63)
-
 #ifdef CONFIG_SMP
 unsigned long profile_pc(struct pt_regs *regs)
 {
@@ -290,9 +288,6 @@ static struct sparc64_tick_ops stick_operations __read_mostly = {
  * 2) write high
  * 3) write low
  */
-#define HBIRD_STICKCMP_ADDR	0x1fe0000f060UL
-#define HBIRD_STICK_ADDR	0x1fe0000f070UL
-
 static unsigned long __hbird_read_stick(void)
 {
 	unsigned long ret, tmp1, tmp2, tmp3;
@@ -777,6 +772,26 @@ static u64 clocksource_tick_read(struct clocksource *cs)
 	return tick_operations.get_tick();
 }
 
+static void __init get_tick_patch(void)
+{
+	unsigned int *addr, *instr, i;
+	struct get_tick_patch *p;
+
+	if (tlb_type == spitfire && is_hummingbird())
+		return;
+
+	for (p = &__get_tick_patch; p < &__get_tick_patch_end; p++) {
+		instr = (tlb_type == spitfire) ? p->tick : p->stick;
+		addr = (unsigned int *)(unsigned long)p->addr;
+		for (i = 0; i < GET_TICK_NINSTR; i++) {
+			addr[i] = instr[i];
+			/* ensure that address is modified before flush */
+			wmb();
+			flushi(&addr[i]);
+		}
+	}
+}
+
 static void init_tick_ops(struct sparc64_tick_ops *ops)
 {
 	unsigned long freq, quotient, tick;
@@ -789,6 +804,7 @@ static void init_tick_ops(struct sparc64_tick_ops *ops)
 	ops->ticks_per_nsec_quotient = quotient;
 	ops->frequency = freq;
 	tick_operations = *ops;
+	get_tick_patch();
 }
 
 void __init time_init_early(void)