2 * From coreboot file of same name
4 * Copyright (C) 2014 Google, Inc
6 * SPDX-License-Identifier: GPL-2.0
9 #ifndef _ARCH_ASM_LAPIC_H
10 #define _ARCH_ASM_LAPIC_H
14 #include <asm/msr-index.h>
15 #include <asm/processor.h>
17 #define LAPIC_DEFAULT_BASE 0xfee00000
19 #define LAPIC_ID 0x020
20 #define LAPIC_LVR 0x030
22 #define LAPIC_TASKPRI 0x080
23 #define LAPIC_TPRI_MASK 0xff
25 #define LAPIC_RRR 0x0c0
27 #define LAPIC_SPIV 0x0f0
28 #define LAPIC_SPIV_ENABLE 0x100
30 #define LAPIC_ICR 0x300
31 #define LAPIC_DEST_SELF 0x40000
32 #define LAPIC_DEST_ALLINC 0x80000
33 #define LAPIC_DEST_ALLBUT 0xc0000
34 #define LAPIC_ICR_RR_MASK 0x30000
35 #define LAPIC_ICR_RR_INVALID 0x00000
36 #define LAPIC_ICR_RR_INPROG 0x10000
37 #define LAPIC_ICR_RR_VALID 0x20000
38 #define LAPIC_INT_LEVELTRIG 0x08000
39 #define LAPIC_INT_ASSERT 0x04000
40 #define LAPIC_ICR_BUSY 0x01000
41 #define LAPIC_DEST_LOGICAL 0x00800
42 #define LAPIC_DM_FIXED 0x00000
43 #define LAPIC_DM_LOWEST 0x00100
44 #define LAPIC_DM_SMI 0x00200
45 #define LAPIC_DM_REMRD 0x00300
46 #define LAPIC_DM_NMI 0x00400
47 #define LAPIC_DM_INIT 0x00500
48 #define LAPIC_DM_STARTUP 0x00600
49 #define LAPIC_DM_EXTINT 0x00700
50 #define LAPIC_VECTOR_MASK 0x000ff
52 #define LAPIC_ICR2 0x310
53 #define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xff)
54 #define SET_LAPIC_DEST_FIELD(x) ((x) << 24)
56 #define LAPIC_LVT0 0x350
57 #define LAPIC_LVT1 0x360
58 #define LAPIC_LVT_MASKED (1 << 16)
59 #define LAPIC_LVT_LEVEL_TRIGGER (1 << 15)
60 #define LAPIC_LVT_REMOTE_IRR (1 << 14)
61 #define LAPIC_INPUT_POLARITY (1 << 13)
62 #define LAPIC_SEND_PENDING (1 << 12)
63 #define LAPIC_LVT_RESERVED_1 (1 << 11)
64 #define LAPIC_DELIVERY_MODE_MASK (7 << 8)
65 #define LAPIC_DELIVERY_MODE_FIXED (0 << 8)
66 #define LAPIC_DELIVERY_MODE_NMI (4 << 8)
67 #define LAPIC_DELIVERY_MODE_EXTINT (7 << 8)
69 static inline __attribute__((always_inline))
70 unsigned long lapic_read(unsigned long reg)
72 return readl(LAPIC_DEFAULT_BASE + reg);
75 static inline __attribute__((always_inline))
76 void lapic_write(unsigned long reg, unsigned long val)
78 writel(val, LAPIC_DEFAULT_BASE + reg);
81 static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void)
83 do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
86 static inline void enable_lapic(void)
90 msr = msr_read(MSR_IA32_APICBASE);
92 msr.lo |= MSR_IA32_APICBASE_ENABLE;
93 msr.lo &= ~MSR_IA32_APICBASE_BASE;
94 msr.lo |= LAPIC_DEFAULT_BASE;
95 msr_write(MSR_IA32_APICBASE, msr);
98 static inline void disable_lapic(void)
102 msr = msr_read(MSR_IA32_APICBASE);
103 msr.lo &= ~MSR_IA32_APICBASE_ENABLE;
104 msr_write(MSR_IA32_APICBASE, msr);
107 static inline __attribute__((always_inline)) unsigned long lapicid(void)
109 return lapic_read(LAPIC_ID) >> 24;
112 static inline __attribute__((always_inline)) void stop_this_cpu(void)
114 /* Called by an AP when it is ready to halt and wait for a new task */
119 #define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
122 struct __xchg_dummy { unsigned long a[100]; };
123 #define __xg(x) ((struct __xchg_dummy *)(x))
126 * Note: no "lock" prefix even on SMP. xchg always implies lock anyway.
128 * Note 2: xchg has side effect, so that attribute volatile is necessary,
129 * but generally the primitive is invalid, *ptr is output argument.
131 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
136 __asm__ __volatile__("xchgb %b0,%1"
138 : "m" (*__xg(ptr)), "0" (x)
142 __asm__ __volatile__("xchgw %w0,%1"
144 : "m" (*__xg(ptr)), "0" (x)
148 __asm__ __volatile__("xchgl %0,%1"
150 : "m" (*__xg(ptr)), "0" (x)
158 static inline void lapic_write_atomic(unsigned long reg, unsigned long v)
160 (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
163 #define lapic_read_around(x) lapic_read(x)
164 #define lapic_write_around(x, y) lapic_write_atomic((x), (y))
166 static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
169 unsigned long status;
172 lapic_wait_icr_idle();
173 lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
174 lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
178 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
179 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
182 if (status == LAPIC_ICR_RR_VALID) {
183 *pvalue = lapic_read(LAPIC_RRR);
190 void lapic_setup(void);