1 /* 2 * From coreboot file of same name 3 * 4 * Copyright (C) 2014 Google, Inc 5 * 6 * SPDX-License-Identifier: GPL-2.0 7 */ 8 9 #ifndef _ARCH_ASM_LAPIC_H 10 #define _ARCH_ASM_LAPIC_H 11 12 #include <asm/io.h> 13 #include <asm/msr.h> 14 #include <asm/msr-index.h> 15 #include <asm/processor.h> 16 17 #define LAPIC_DEFAULT_BASE 0xfee00000 18 19 #define LAPIC_ID 0x020 20 #define LAPIC_LVR 0x030 21 22 #define LAPIC_TASKPRI 0x080 23 #define LAPIC_TPRI_MASK 0xff 24 25 #define LAPIC_RRR 0x0c0 26 27 #define LAPIC_SPIV 0x0f0 28 #define LAPIC_SPIV_ENABLE 0x100 29 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 51 52 #define LAPIC_ICR2 0x310 53 #define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xff) 54 #define SET_LAPIC_DEST_FIELD(x) ((x) << 24) 55 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) 68 69 static inline __attribute__((always_inline)) 70 unsigned long lapic_read(unsigned long reg) 71 { 72 return readl(LAPIC_DEFAULT_BASE + reg); 73 } 74 75 static inline __attribute__((always_inline)) 76 void lapic_write(unsigned long reg, unsigned long val) 77 { 78 writel(val, LAPIC_DEFAULT_BASE + reg); 79 } 80 81 static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void) 82 { 83 do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY); 84 } 85 86 static inline void enable_lapic(void) 87 { 88 msr_t msr; 89 90 msr = msr_read(MSR_IA32_APICBASE); 91 msr.hi &= 0xffffff00; 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); 96 } 97 98 static inline void disable_lapic(void) 99 { 100 msr_t msr; 101 102 msr = msr_read(MSR_IA32_APICBASE); 103 msr.lo &= ~MSR_IA32_APICBASE_ENABLE; 104 msr_write(MSR_IA32_APICBASE, msr); 105 } 106 107 static inline __attribute__((always_inline)) unsigned long lapicid(void) 108 { 109 return lapic_read(LAPIC_ID) >> 24; 110 } 111 112 static inline __attribute__((always_inline)) void stop_this_cpu(void) 113 { 114 /* Called by an AP when it is ready to halt and wait for a new task */ 115 for (;;) 116 cpu_hlt(); 117 } 118 119 #define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \ 120 sizeof(*(ptr)))) 121 122 struct __xchg_dummy { unsigned long a[100]; }; 123 #define __xg(x) ((struct __xchg_dummy *)(x)) 124 125 /* 126 * Note: no "lock" prefix even on SMP. xchg always implies lock anyway. 127 * 128 * Note 2: xchg has side effect, so that attribute volatile is necessary, 129 * but generally the primitive is invalid, *ptr is output argument. 130 */ 131 static inline unsigned long __xchg(unsigned long x, volatile void *ptr, 132 int size) 133 { 134 switch (size) { 135 case 1: 136 __asm__ __volatile__("xchgb %b0,%1" 137 : "=q" (x) 138 : "m" (*__xg(ptr)), "0" (x) 139 : "memory"); 140 break; 141 case 2: 142 __asm__ __volatile__("xchgw %w0,%1" 143 : "=r" (x) 144 : "m" (*__xg(ptr)), "0" (x) 145 : "memory"); 146 break; 147 case 4: 148 __asm__ __volatile__("xchgl %0,%1" 149 : "=r" (x) 150 : "m" (*__xg(ptr)), "0" (x) 151 : "memory"); 152 break; 153 } 154 155 return x; 156 } 157 158 static inline void lapic_write_atomic(unsigned long reg, unsigned long v) 159 { 160 (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v); 161 } 162 163 #define lapic_read_around(x) lapic_read(x) 164 #define lapic_write_around(x, y) lapic_write_atomic((x), (y)) 165 166 static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue) 167 { 168 int timeout; 169 unsigned long status; 170 int result; 171 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)); 175 176 timeout = 0; 177 do { 178 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK; 179 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000); 180 181 result = -1; 182 if (status == LAPIC_ICR_RR_VALID) { 183 *pvalue = lapic_read(LAPIC_RRR); 184 result = 0; 185 } 186 187 return result; 188 } 189 190 void lapic_setup(void); 191 192 #endif 193