diff options
author | Pavel Tatashin <pasha.tatashin@oracle.com> | 2017-06-12 16:41:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-12 15:44:03 -0700 |
commit | 4929c83a6ce6584cb64381bf1407c487f67d588a (patch) | |
tree | 49e344e89629324a8af3418dca73db02109abc08 /arch/sparc/kernel | |
parent | 83e8eb99d908da78e6eff7dd141f26626fe01d12 (diff) | |
download | lwn-4929c83a6ce6584cb64381bf1407c487f67d588a.tar.gz lwn-4929c83a6ce6584cb64381bf1407c487f67d588a.zip |
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')
-rw-r--r-- | arch/sparc/kernel/time_64.c | 28 | ||||
-rw-r--r-- | arch/sparc/kernel/vmlinux.lds.S | 5 |
2 files changed, 27 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) diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 572db686f845..03b3d65d1266 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -149,6 +149,11 @@ SECTIONS *(.sun_m7_2insn_patch) __sun_m7_2insn_patch_end = .; } + .get_tick_patch : { + __get_tick_patch = .; + *(.get_tick_patch) + __get_tick_patch_end = .; + } PERCPU_SECTION(SMP_CACHE_BYTES) #ifdef CONFIG_JUMP_LABEL |