hc
2024-08-16 a24a44ff9ca902811b99aa9663d697cf452e08ef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/* SPDX-License-Identifier: GPL-2.0 */
/* timer.h: System timer definitions for sun5.
 *
 * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net)
 */
 
#ifndef _SPARC64_TIMER_H
#define _SPARC64_TIMER_H
 
#include <uapi/asm/asi.h>
#include <linux/types.h>
#include <linux/init.h>
 
/* The most frequently accessed fields should be first,
 * to fit into the same cacheline.
 */
struct sparc64_tick_ops {
   unsigned long ticks_per_nsec_quotient;
   unsigned long offset;
   unsigned long long (*get_tick)(void);
   int (*add_compare)(unsigned long);
   unsigned long softint_mask;
   void (*disable_irq)(void);
 
   void (*init_tick)(void);
   unsigned long (*add_tick)(unsigned long);
   unsigned long (*get_frequency)(void);
   unsigned long frequency;
 
   char *name;
};
 
extern struct sparc64_tick_ops *tick_ops;
 
unsigned long sparc64_get_clock_tick(unsigned int cpu);
void setup_sparc64_timer(void);
void __init time_init(void);
 
#define TICK_PRIV_BIT        BIT(63)
#define TICKCMP_IRQ_BIT        BIT(63)
 
#define HBIRD_STICKCMP_ADDR    0x1fe0000f060UL
#define HBIRD_STICK_ADDR    0x1fe0000f070UL
 
#define GET_TICK_NINSTR        13
struct get_tick_patch {
   unsigned int    addr;
   unsigned int    tick[GET_TICK_NINSTR];
   unsigned int    stick[GET_TICK_NINSTR];
};
 
extern struct get_tick_patch __get_tick_patch;
extern struct get_tick_patch __get_tick_patch_end;
 
static inline unsigned long get_tick(void)
{
   unsigned long tick, tmp1, tmp2;
 
   __asm__ __volatile__(
   /* read hbtick 13 instructions */
   "661:\n"
   "    mov    0x1fe, %1\n"
   "    sllx    %1, 0x20, %1\n"
   "    sethi    %%hi(0xf000), %2\n"
   "    or    %2, 0x70, %2\n"
   "    or    %1, %2, %1\n"    /* %1 = HBIRD_STICK_ADDR */
   "    add    %1, 8, %2\n"
   "    ldxa    [%2]%3, %0\n"
   "    ldxa    [%1]%3, %1\n"
   "    ldxa    [%2]%3, %2\n"
   "    sub    %2, %0, %0\n"    /* don't modify %xcc */
   "    brnz,pn    %0, 661b\n"    /* restart to save one register */
   "     sllx    %2, 32, %2\n"
   "    or    %2, %1, %0\n"
   /* Common/not patched code */
   "    sllx    %0, 1, %0\n"
   "    srlx    %0, 1, %0\n"    /* Clear TICK_PRIV_BIT */
   /* Beginning of patch section */
   "    .section .get_tick_patch, \"ax\"\n"
   "    .word    661b\n"
   /* read tick 2 instructions and 11 skipped */
   "    ba    1f\n"
   "     rd    %%tick, %0\n"
   "    .skip    4 * (%4 - 2)\n"
   "1:\n"
   /* read stick 2 instructions and 11 skipped */
   "    ba    1f\n"
   "     rd    %%asr24, %0\n"
   "    .skip    4 * (%4 - 2)\n"
   "1:\n"
   /* End of patch section */
   "    .previous\n"
   : "=&r" (tick), "=&r" (tmp1), "=&r" (tmp2)
   : "i" (ASI_PHYS_BYPASS_EC_E), "i" (GET_TICK_NINSTR));
 
   return tick;
}
 
#endif /* _SPARC64_TIMER_H */