From 9b4336cf418d22551bea09d93e1cee79281b110e Mon Sep 17 00:00:00 2001 From: Eric Biederman Date: Sat, 19 Jul 2003 04:28:22 +0000 Subject: - Major cleanup of the bootpath - Changes to allow more code to be compiled both ways - Working SMP support git-svn-id: svn://svn.coreboot.org/coreboot/trunk@987 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/arch/i386/include/arch/io.h | 196 +++++++++++++++++++++++----------- src/arch/i386/include/arch/romcc_io.h | 63 ----------- src/arch/i386/lib/cpu.c | 21 ++-- src/arch/i386/smp/secondary.S | 76 +++++++++++++ src/arch/i386/smp/start_stop.c | 1 + 5 files changed, 219 insertions(+), 138 deletions(-) create mode 100644 src/arch/i386/smp/secondary.S (limited to 'src/arch/i386') diff --git a/src/arch/i386/include/arch/io.h b/src/arch/i386/include/arch/io.h index bcba9a932c..c1207b3182 100644 --- a/src/arch/i386/include/arch/io.h +++ b/src/arch/i386/include/arch/io.h @@ -1,76 +1,142 @@ #ifndef _ASM_IO_H #define _ASM_IO_H +#include + /* * This file contains the definitions for the x86 IO instructions * inb/inw/inl/outb/outw/outl and the "string versions" of the same - * (insb/insw/insl/outsb/outsw/outsl). - * - * This file is not meant to be obfuscating: it's just complicated - * to (a) handle it all in a way that makes gcc able to optimize it - * as well as possible and (b) trying to avoid writing the same thing - * over and over again with slight variations and possibly making a - * mistake somewhere. - */ - - /* - * Bit simplified and optimized by Jan Hubicka - * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999. - */ - -/* - * Talk about misusing macros.. + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). */ -#define __OUT1(s,x) \ -extern inline void out##s(unsigned x value, unsigned short port) { - -#define __OUT2(s,s1,s2) \ -__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" - -#define __OUT(s,s1,x) \ -__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } - -#define __IN1(s) \ -extern inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v; - -#define __IN2(s,s1,s2) \ -__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" - -#define __IN(s,s1,i...) \ -__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } - -#define __INS(s) \ -extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \ -{ __asm__ __volatile__ ("cld ; rep ; ins" #s \ -: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } - -#define __OUTS(s) \ -extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ -{ __asm__ __volatile__ ("cld ; rep ; outs" #s \ -: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } - -#define RETURN_TYPE unsigned char -__IN(b,"") -#undef RETURN_TYPE -#define RETURN_TYPE unsigned short -__IN(w,"") -#undef RETURN_TYPE -#define RETURN_TYPE unsigned int -__IN(l,"") -#undef RETURN_TYPE - -__OUT(b,"b",char) -__OUT(w,"w",short) -__OUT(l,,int) - -__INS(b) -__INS(w) -__INS(l) - -__OUTS(b) -__OUTS(w) -__OUTS(l) +#ifdef __ROMCC__ +static void outb(unsigned char value, unsigned short port) +{ + __builtin_outb(value, port); +} + +static void outw(unsigned short value, unsigned short port) +{ + __builtin_outw(value, port); +} + +static void outl(unsigned int value, unsigned short port) +{ + __builtin_outl(value, port); +} + + +static unsigned char inb(unsigned short port) +{ + return __builtin_inb(port); +} + + +static unsigned char inw(unsigned short port) +{ + return __builtin_inw(port); +} + +static unsigned char inl(unsigned short port) +{ + return __builtin_inl(port); +} + +#else + +static inline void outb(uint8_t value, uint16_t port) +{ + __asm__ __volatile__ ("outb %b0, %w1" : : "a" (value), "Nd" (port)); +} + +static inline void outw(uint16_t value, uint16_t port) +{ + __asm__ __volatile__ ("outw %w0, %w1" : : "a" (value), "Nd" (port)); +} + +static inline void outl(uint32_t value, uint16_t port) +{ + __asm__ __volatile__ ("outl %0, %w1" : : "a" (value), "Nd" (port)); +} + +static inline uint8_t inb(uint16_t port) +{ + uint8_t value; + __asm__ __volatile__ ("inb %w1, %b0" : "=a"(value) : "Nd" (port)); + return value; +} + +static inline uint16_t inw(uint16_t port) +{ + uint16_t value; + __asm__ __volatile__ ("inw %w1, %w0" : "=a"(value) : "Nd" (port)); + return value; +} + +static inline uint32_t inl(uint16_t port) +{ + uint32_t value; + __asm__ __volatile__ ("inl %w1, %0" : "=a"(value) : "Nd" (port)); + return value; +} + +#endif /* __ROMCC__ */ + +static inline void outsb(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsb " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline void outsw(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsw " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline void outsl(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsl " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + + +static inline void insb(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insb " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline void insw(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insw " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline void insl(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insl " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} #endif diff --git a/src/arch/i386/include/arch/romcc_io.h b/src/arch/i386/include/arch/romcc_io.h index f8618b0e76..1a646359a7 100644 --- a/src/arch/i386/include/arch/romcc_io.h +++ b/src/arch/i386/include/arch/romcc_io.h @@ -1,37 +1,6 @@ #ifndef ARCH_ROMCC_IO_H #define ARCH_ROMCC_IO_H 1 -static void outb(unsigned char value, unsigned short port) -{ - __builtin_outb(value, port); -} - -static void outw(unsigned short value, unsigned short port) -{ - __builtin_outw(value, port); -} - -static void outl(unsigned int value, unsigned short port) -{ - __builtin_outl(value, port); -} - - -static unsigned char inb(unsigned short port) -{ - return __builtin_inb(port); -} - - -static unsigned char inw(unsigned short port) -{ - return __builtin_inw(port); -} - -static unsigned char inl(unsigned short port) -{ - return __builtin_inl(port); -} static void hlt(void) { @@ -76,38 +45,6 @@ int log2(int value) return __builtin_bsr(value); } - -typedef __builtin_msr_t msr_t; - -static msr_t rdmsr(unsigned long index) -{ - return __builtin_rdmsr(index); -} - -static void wrmsr(unsigned long index, msr_t msr) -{ - __builtin_wrmsr(index, msr.lo, msr.hi); -} - - -struct tsc_struct { - unsigned lo; - unsigned hi; -}; -typedef struct tsc_struct tsc_t; - -static tsc_t rdtsc(void) -{ - tsc_t res; - asm ("rdtsc" - : "=a" (res.lo), "=d"(res.hi) /* outputs */ - : /* inputs */ - : /* Clobbers */ - ); - return res; -} - - #define PCI_ADDR(BUS, DEV, FN, WHERE) ( \ (((BUS) & 0xFF) << 16) | \ (((DEV) & 0x1f) << 11) | \ diff --git a/src/arch/i386/lib/cpu.c b/src/arch/i386/lib/cpu.c index 19020fee55..95dba5f8e5 100644 --- a/src/arch/i386/lib/cpu.c +++ b/src/arch/i386/lib/cpu.c @@ -57,16 +57,16 @@ static void interrupts_on() #if defined(APIC) /* Only Pentium Pro and later have those MSR stuff */ - unsigned long low, high; + msr_t msr; printk_info("Setting up local apic..."); /* Enable the local apic */ - rdmsr(APIC_BASE_MSR, low, high); - low |= APIC_BASE_MSR_ENABLE; - low &= ~APIC_BASE_MSR_ADDR_MASK; - low |= APIC_DEFAULT_BASE; - wrmsr(APIC_BASE_MSR, low, high); + msr = rdmsr(APIC_BASE_MSR); + msr.lo |= APIC_BASE_MSR_ENABLE; + msr.lo &= ~APIC_BASE_MSR_ADDR_MASK; + msr.lo |= APIC_DEFAULT_BASE; + wrmsr(APIC_BASE_MSR, msr); /* * Set Task Priority to 'accept all'. @@ -103,13 +103,13 @@ static void interrupts_on() #else /* APIC */ #ifdef i686 /* Only Pentium Pro and later have those MSR stuff */ - unsigned long low, high; + msr_t msr; printk_info("Disabling local apic..."); - rdmsr(APIC_BASE_MSR, low, high); - low &= ~APIC_BASE_MSR_ENABLE; - wrmsr(APIC_BASE_MSR, low, high); + msr = rdmsr(APIC_BASE_MSR); + msr.lo &= ~APIC_BASE_MSR_ENABLE; + wrmsr(APIC_BASE_MSR, msr); #endif /* i686 */ #endif /* APIC */ printk_info("done.\n"); @@ -143,6 +143,7 @@ unsigned long cpu_initialize(struct mem_range *mem) configure_l2_cache(); #endif interrupts_on(); + processor_id = this_processors_id(); printk_info("CPU #%d Initialized\n", processor_id); return processor_id; } diff --git a/src/arch/i386/smp/secondary.S b/src/arch/i386/smp/secondary.S new file mode 100644 index 0000000000..78c55764b0 --- /dev/null +++ b/src/arch/i386/smp/secondary.S @@ -0,0 +1,76 @@ +#include +#include +#include +#include + .text + .globl _secondary_start + .balign 4096 +_secondary_start: + .code16 + cli + xorl %eax, %eax + movl %eax, %cr3 /* Invalidate TLB*/ + + /* On hyper threaded cpus invalidating the cache here is + * very very bad. Don't. + */ + + /* setup the data segment */ + movw %cs, %ax + movw %ax, %ds + + data32 lgdt gdtaddr - _secondary_start + + movl %cr0, %eax + andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ + orl $0x60000001, %eax /* CD, NW, PE = 1 */ + movl %eax, %cr0 + + ljmpl $0x10, $1f +1: + .code32 + movw $0x18, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + + /* Enable the local apic, and map it where we expext it */ + movl $APIC_BASE_MSR, %ecx + rdmsr + orl $APIC_BASE_MSR_ENABLE, %eax + andl $(~APIC_BASE_MSR_ADDR_MASK), %eax + orl $APIC_DEFAULT_BASE, %eax + wrmsr + + /* Get the apic_id */ + movl (APIC_ID + APIC_DEFAULT_BASE), %edi + shrl $24, %edi + + /* Get the cpu index (MAX_CPUS on error) */ + movl $-4, %ebx +1: addl $4, %ebx + cmpl $(MAX_CPUS << 2), %ebx + je 2 + cmpl %edi, initial_apicid(%ebx) + jne 1b +2: shrl $2, %ebx + + /* set the stack pointer */ + movl $_estack, %esp + movl %ebx, %eax + movl $STACK_SIZE, %ebx + mull %ebx + subl %eax, %esp + + call secondary_cpu_init +1: hlt + jmp 1b + +gdtaddr: + .word gdt_limit /* the table limit */ + .long gdt /* we know the offset */ + + +.code32 diff --git a/src/arch/i386/smp/start_stop.c b/src/arch/i386/smp/start_stop.c index 018ec30705..bb8868a8d9 100644 --- a/src/arch/i386/smp/start_stop.c +++ b/src/arch/i386/smp/start_stop.c @@ -3,6 +3,7 @@ #include #include #include +#include #ifndef START_CPU_SEG #define START_CPU_SEG 0x90000 -- cgit v1.2.3