summaryrefslogtreecommitdiff
path: root/src/include/cpu/x86/lapic.h
diff options
context:
space:
mode:
authorEric Biederman <ebiederm@xmission.com>2004-10-14 20:13:01 +0000
committerEric Biederman <ebiederm@xmission.com>2004-10-14 20:13:01 +0000
commitc84c1906b78b767902bf9d8f18ae8a21d2f1f114 (patch)
tree136d8ed19f4cc487e5b7d01416aaab3810ee6659 /src/include/cpu/x86/lapic.h
parentb84166e8e53476f1ef4d49aca17f99d303b4aa67 (diff)
downloadcoreboot-c84c1906b78b767902bf9d8f18ae8a21d2f1f114.tar.xz
- Renamed cpu header files
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1659 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/include/cpu/x86/lapic.h')
-rw-r--r--src/include/cpu/x86/lapic.h168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/include/cpu/x86/lapic.h b/src/include/cpu/x86/lapic.h
new file mode 100644
index 0000000000..12ca518f66
--- /dev/null
+++ b/src/include/cpu/x86/lapic.h
@@ -0,0 +1,168 @@
+#ifndef CPU_X86_LAPIC_H
+#define CPU_X86_LAPIC_H
+
+#include <cpu/x86/lapic_def.h>
+#include <cpu/x86/msr.h>
+#include <arch/hlt.h>
+
+/* See if I need to initialize the local apic */
+#if CONFIG_SMP || CONFIG_IOAPIC
+# define NEED_LAPIC 1
+#endif
+
+static inline unsigned long lapic_read(unsigned long reg)
+{
+ return *((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg));
+}
+
+static inline void lapic_write(unsigned long reg, unsigned long v)
+{
+ *((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg)) = v;
+}
+
+static inline void lapic_wait_icr_idle(void)
+{
+ do { } while ( lapic_read( LAPIC_ICR ) & LAPIC_ICR_BUSY );
+}
+
+
+
+static inline void enable_lapic(void)
+{
+
+ msr_t msr;
+ msr = rdmsr(LAPIC_BASE_MSR);
+ msr.hi &= 0xffffff00;
+ msr.lo &= 0x000007ff;
+ msr.lo |= LAPIC_DEFAULT_BASE | (1 << 11);
+ wrmsr(LAPIC_BASE_MSR, msr);
+}
+
+static inline void disable_lapic(void)
+{
+ msr_t msr;
+ msr = rdmsr(LAPIC_BASE_MSR);
+ msr.lo &= ~(1 << 11);
+ wrmsr(LAPIC_BASE_MSR, msr);
+}
+
+static inline unsigned long lapicid(void)
+{
+ return lapic_read(LAPIC_ID) >> 24;
+}
+
+static inline void stop_this_cpu(void)
+{
+ unsigned apicid;
+ apicid = lapicid();
+
+ /* Send an APIC INIT to myself */
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
+ lapic_write(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT);
+ /* Wait for the ipi send to finish */
+ lapic_wait_icr_idle();
+
+ /* Deassert the APIC INIT */
+ lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
+ lapic_write(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT);
+ /* Wait for the ipi send to finish */
+ lapic_wait_icr_idle();
+
+ /* If I haven't halted spin forever */
+ for(;;) {
+ hlt();
+ }
+}
+
+#if ! defined (__ROMCC__)
+
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+/*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ * but generally the primitive is invalid, *ptr is output argument. --ANK
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("xchgb %b0,%1"
+ :"=q" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 2:
+ __asm__ __volatile__("xchgw %w0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 4:
+ __asm__ __volatile__("xchgl %0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ }
+ return x;
+}
+
+
+extern inline void lapic_write_atomic(unsigned long reg, unsigned long v)
+{
+ xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg), v);
+}
+
+
+#ifdef CONFIG_X86_GOOD_APIC
+# define FORCE_READ_AROUND_WRITE 0
+# define lapic_read_around(x) lapic_read(x)
+# define lapic_write_around(x,y) lapic_write((x),(y))
+#else
+# define FORCE_READ_AROUND_WRITE 1
+# define lapic_read_around(x) lapic_read(x)
+# define lapic_write_around(x,y) lapic_write_atomic((x),(y))
+#endif
+
+static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
+{
+ int timeout;
+ unsigned long status;
+ int result;
+ lapic_wait_icr_idle();
+ lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
+ lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
+ timeout = 0;
+ do {
+#if 0
+ udelay(100);
+#endif
+ status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
+ } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
+
+ result = -1;
+ if (status == LAPIC_ICR_RR_VALID) {
+ *pvalue = lapic_read(LAPIC_RRR);
+ result = 0;
+ }
+ return result;
+}
+
+
+void setup_lapic(void);
+
+
+#if CONFIG_SMP == 1
+struct device;
+int start_cpu(struct device *cpu);
+
+#endif /* CONFIG_SMP */
+
+
+#endif /* !__ROMCC__ */
+
+#endif /* CPU_X86_LAPIC_H */