blob: 28978f2793a7b0441c7779ab4e6a72bbc5c8c419 [file] [log] [blame]
Eric Biedermanc84c1902004-10-14 20:13:01 +00001#ifndef CPU_X86_LAPIC_H
2#define CPU_X86_LAPIC_H
3
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +01004#include <arch/mmio.h>
Eric Biedermanc84c1902004-10-14 20:13:01 +00005#include <cpu/x86/lapic_def.h>
6#include <cpu/x86/msr.h>
Patrick Georgibd79c5e2014-11-28 22:35:36 +01007#include <halt.h>
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +01008#include <stdint.h>
Eric Biedermanc84c1902004-10-14 20:13:01 +00009
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +010010static __always_inline uint32_t lapic_read(unsigned int reg)
Eric Biedermanc84c1902004-10-14 20:13:01 +000011{
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +010012 return read32((volatile void *)(LAPIC_DEFAULT_BASE + reg));
Eric Biedermanc84c1902004-10-14 20:13:01 +000013}
14
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +010015static __always_inline void lapic_write(unsigned int reg, uint32_t v)
Eric Biedermanc84c1902004-10-14 20:13:01 +000016{
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +010017 write32((volatile void *)(LAPIC_DEFAULT_BASE + reg), v);
Eric Biedermanc84c1902004-10-14 20:13:01 +000018}
19
Aaron Durbin75a62e72018-09-13 02:10:45 -060020static __always_inline void lapic_wait_icr_idle(void)
Eric Biedermanc84c1902004-10-14 20:13:01 +000021{
Lee Leahy91d1e762017-03-07 14:31:19 -080022 do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
Eric Biedermanc84c1902004-10-14 20:13:01 +000023}
24
Eric Biedermanc84c1902004-10-14 20:13:01 +000025static inline void enable_lapic(void)
26{
Eric Biedermanc84c1902004-10-14 20:13:01 +000027 msr_t msr;
28 msr = rdmsr(LAPIC_BASE_MSR);
29 msr.hi &= 0xffffff00;
Kyösti Mälkkiff284f62017-08-18 12:11:16 +030030 msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
31 msr.lo |= LAPIC_DEFAULT_BASE;
32 msr.lo |= LAPIC_BASE_MSR_ENABLE;
Eric Biedermanc84c1902004-10-14 20:13:01 +000033 wrmsr(LAPIC_BASE_MSR, msr);
34}
35
36static inline void disable_lapic(void)
37{
38 msr_t msr;
39 msr = rdmsr(LAPIC_BASE_MSR);
Kyösti Mälkkiff284f62017-08-18 12:11:16 +030040 msr.lo &= ~LAPIC_BASE_MSR_ENABLE;
Eric Biedermanc84c1902004-10-14 20:13:01 +000041 wrmsr(LAPIC_BASE_MSR, msr);
42}
43
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +010044static __always_inline unsigned int lapicid(void)
Eric Biedermanc84c1902004-10-14 20:13:01 +000045{
46 return lapic_read(LAPIC_ID) >> 24;
47}
48
Julius Wernercd49cce2019-03-05 16:53:33 -080049#if !CONFIG(AP_IN_SIPI_WAIT)
Sven Schnelle51676b12012-07-29 19:18:03 +020050/* If we need to go back to sipi wait, we use the long non-inlined version of
51 * this function in lapic_cpu_init.c
52 */
Aaron Durbin75a62e72018-09-13 02:10:45 -060053static __always_inline void stop_this_cpu(void)
Eric Biedermanc84c1902004-10-14 20:13:01 +000054{
Sven Schnelle51676b12012-07-29 19:18:03 +020055 /* Called by an AP when it is ready to halt and wait for a new task */
Patrick Georgibd79c5e2014-11-28 22:35:36 +010056 halt();
Eric Biedermanc84c1902004-10-14 20:13:01 +000057}
Sven Schnelle51676b12012-07-29 19:18:03 +020058#else
59void stop_this_cpu(void);
60#endif
Eric Biedermanc84c1902004-10-14 20:13:01 +000061
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +010062static inline void lapic_write_atomic(unsigned long reg, uint32_t v)
Eric Biedermanc84c1902004-10-14 20:13:01 +000063{
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +010064 volatile uint32_t *ptr;
65
66 ptr = (volatile uint32_t *)(LAPIC_DEFAULT_BASE + reg);
67
68 asm volatile ("xchgl %0, %1\n"
69 : "+r" (v), "+m" (*(ptr))
70 : : "memory", "cc");
Eric Biedermanc84c1902004-10-14 20:13:01 +000071}
72
Eric Biedermanc84c1902004-10-14 20:13:01 +000073# define lapic_read_around(x) lapic_read(x)
Lee Leahyae3fd342017-03-07 12:55:23 -080074# define lapic_write_around(x, y) lapic_write_atomic((x), (y))
Eric Biedermanc84c1902004-10-14 20:13:01 +000075
Kyösti Mälkkiff284f62017-08-18 12:11:16 +030076void do_lapic_init(void);
Eric Biedermanc84c1902004-10-14 20:13:01 +000077
Kyösti Mälkkiff284f62017-08-18 12:11:16 +030078/* See if I need to initialize the local APIC */
79static inline int need_lapic_init(void)
80{
Julius Wernercd49cce2019-03-05 16:53:33 -080081 return CONFIG(SMP) || CONFIG(IOAPIC);
Kyösti Mälkkiff284f62017-08-18 12:11:16 +030082}
Eric Biedermanc84c1902004-10-14 20:13:01 +000083
Kyösti Mälkkiff284f62017-08-18 12:11:16 +030084static inline void setup_lapic(void)
85{
86 if (need_lapic_init())
87 do_lapic_init();
88 else
89 disable_lapic();
90}
91
Eric Biedermanc84c1902004-10-14 20:13:01 +000092struct device;
93int start_cpu(struct device *cpu);
Eric Biedermanc84c1902004-10-14 20:13:01 +000094
Eric Biedermanc84c1902004-10-14 20:13:01 +000095#endif /* CPU_X86_LAPIC_H */