diff options
author | Eric Biederman <ebiederm@xmission.com> | 2004-10-14 20:13:01 +0000 |
---|---|---|
committer | Eric Biederman <ebiederm@xmission.com> | 2004-10-14 20:13:01 +0000 |
commit | c84c1906b78b767902bf9d8f18ae8a21d2f1f114 (patch) | |
tree | 136d8ed19f4cc487e5b7d01416aaab3810ee6659 /src/include/cpu/x86/lapic.h | |
parent | b84166e8e53476f1ef4d49aca17f99d303b4aa67 (diff) |
- 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.h | 168 |
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 */ |