1+ #include <linux/clockchips.h>
12#include <linux/clocksource.h>
3+ #include <linux/cpuhotplug.h>
24#include <linux/delay.h>
35#include <linux/init.h>
6+ #include <linux/interrupt.h>
7+ #include <linux/irq.h>
8+ #include <linux/irqdomain.h>
9+ #include <asm/irq.h>
410#include <asm/wasm_imports.h>
511#include <asm/param.h>
612#include <asm/timex.h>
713#include <asm/processor.h>
814
915extern unsigned long loops_per_jiffy ;
16+ extern void wasm_set_timer_deadline (u64 deadline_ns );
17+ extern u64 wasm_get_timer_deadline (void );
18+
19+ static int timer_irq ;
1020void calibrate_delay (void )
1121{
1222 loops_per_jiffy = 1000000000 / HZ ;
@@ -32,9 +42,11 @@ void __const_udelay(unsigned long xloops)
3242 __delay (xloops / 0x10c7ul ); /* 2**32 / 1000000 (rounded up) */
3343}
3444
35- unsigned long long sched_clock (void ) {
45+ unsigned long long sched_clock (void )
46+ {
3647 static u64 origin = 0 ;
37- if (!origin ) origin = wasm_kernel_get_now_nsec ();
48+ if (!origin )
49+ origin = wasm_kernel_get_now_nsec ();
3850 return wasm_kernel_get_now_nsec () - origin ;
3951}
4052
@@ -51,8 +63,72 @@ static struct clocksource clocksource = {
5163 .mask = CLOCKSOURCE_MASK (64 ),
5264};
5365
66+ static DEFINE_PER_CPU (struct clock_event_device , clockevent ) ;
67+
68+ static irqreturn_t timer_interrupt (int irq , void * dev )
69+ {
70+ struct clock_event_device * evt = this_cpu_ptr (& clockevent );
71+
72+ if (evt -> event_handler )
73+ evt -> event_handler (evt );
74+
75+ return IRQ_HANDLED ;
76+ }
77+
78+ static int timer_set_next_event (unsigned long delta ,
79+ struct clock_event_device * evt )
80+ {
81+ u64 now = wasm_kernel_get_now_nsec ();
82+ u64 deadline = now + delta ;
83+ wasm_set_timer_deadline (deadline );
84+ return 0 ;
85+ }
86+
87+ static int timer_set_oneshot (struct clock_event_device * evt )
88+ {
89+ return 0 ;
90+ }
91+
92+ static int timer_shutdown (struct clock_event_device * evt )
93+ {
94+ wasm_set_timer_deadline (0 );
95+ return 0 ;
96+ }
97+
98+ static int timer_starting_cpu (unsigned int cpu )
99+ {
100+ struct clock_event_device * evt = this_cpu_ptr (& clockevent );
101+
102+ evt -> name = "wasm-timer" ;
103+ evt -> features = CLOCK_EVT_FEAT_ONESHOT ;
104+ evt -> rating = 300 ;
105+ evt -> set_next_event = timer_set_next_event ;
106+ evt -> set_state_oneshot = timer_set_oneshot ;
107+ evt -> set_state_shutdown = timer_shutdown ;
108+ evt -> cpumask = cpumask_of (cpu );
109+ evt -> irq = timer_irq ;
110+
111+ clockevents_config_and_register (evt , NSEC_PER_SEC , 1000 , LONG_MAX );
112+
113+ return 0 ;
114+ }
115+
54116void __init time_init (void )
55117{
118+ int ret ;
119+
56120 if (clocksource_register_khz (& clocksource , 1000 * 1000 ))
57121 panic ("unable to register clocksource\n" );
122+
123+ timer_irq = irq_create_mapping (NULL , TIMER_IRQ );
124+ if (!timer_irq )
125+ panic ("unable to create IRQ mapping for timer\n" );
126+
127+ if (request_irq (timer_irq , timer_interrupt , IRQF_TIMER , "timer" , NULL ))
128+ panic ("unable to request timer IRQ\n" );
129+
130+ ret = cpuhp_setup_state (CPUHP_AP_ONLINE_DYN , "wasm/timer:online" ,
131+ timer_starting_cpu , NULL );
132+ if (ret < 0 )
133+ panic ("unable to setup CPU hotplug state\n" );
58134}
0 commit comments