1 /*
2  * Copyright (C) 2021 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <types.h>
8 #include <softirq.h>
9 #include <irq.h>
10 #include <logmsg.h>
11 #include <asm/cpu.h>
12 #include <asm/msr.h>
13 #include <asm/irq.h>
14 #include <asm/apicreg.h>
15 #include <hw/hw_timer.h>
16 
17 /* run in interrupt context */
timer_expired_handler(__unused uint32_t irq,__unused void * data)18 static void timer_expired_handler(__unused uint32_t irq, __unused void *data)
19 {
20 	fire_softirq(SOFTIRQ_TIMER);
21 }
22 
set_hw_timeout(uint64_t timeout)23 void set_hw_timeout(uint64_t timeout)
24 {
25 	msr_write(MSR_IA32_TSC_DEADLINE, timeout);
26 }
27 
init_hw_timer(void)28 void init_hw_timer(void)
29 {
30 	int32_t retval = 0;
31 
32 	if (get_pcpu_id() == BSP_CPU_ID) {
33 		retval = request_irq(TIMER_IRQ, timer_expired_handler, NULL, IRQF_NONE);
34 		if (retval < 0) {
35 			pr_err("Timer setup failed");
36 		}
37 	}
38 
39 	if (retval >= 0) {
40 		uint32_t val = TIMER_VECTOR;
41 		val |= APIC_LVTT_TM_TSCDLT; /* TSC deadline and unmask */
42 		msr_write(MSR_IA32_EXT_APIC_LVT_TIMER, val);
43 		/* SDM 10.5.4.1: In x2APIC mode, the processor ensures the
44                    ordering of this write and any subsequent WRMSR to the
45                    deadline; no fencing is required. */
46 
47 		/* disarm timer */
48 		msr_write(MSR_IA32_TSC_DEADLINE, 0UL);
49 	}
50 }
51