- 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
This commit is contained in:
@@ -1,76 +1,142 @@
|
||||
#ifndef _ASM_IO_H
|
||||
#define _ASM_IO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
|
||||
* versions of the single-IO instructions (inb_p/inw_p/..).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bit simplified and optimized by Jan Hubicka
|
||||
* Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
|
||||
*/
|
||||
#ifdef __ROMCC__
|
||||
static void outb(unsigned char value, unsigned short port)
|
||||
{
|
||||
__builtin_outb(value, port);
|
||||
}
|
||||
|
||||
/*
|
||||
* Talk about misusing macros..
|
||||
*/
|
||||
#define __OUT1(s,x) \
|
||||
extern inline void out##s(unsigned x value, unsigned short port) {
|
||||
static void outw(unsigned short value, unsigned short port)
|
||||
{
|
||||
__builtin_outw(value, port);
|
||||
}
|
||||
|
||||
#define __OUT2(s,s1,s2) \
|
||||
__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
|
||||
static void outl(unsigned int value, unsigned short port)
|
||||
{
|
||||
__builtin_outl(value, port);
|
||||
}
|
||||
|
||||
#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;
|
||||
static unsigned char inb(unsigned short port)
|
||||
{
|
||||
return __builtin_inb(port);
|
||||
}
|
||||
|
||||
#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; }
|
||||
static unsigned char inw(unsigned short port)
|
||||
{
|
||||
return __builtin_inw(port);
|
||||
}
|
||||
|
||||
#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)); }
|
||||
static unsigned char inl(unsigned short port)
|
||||
{
|
||||
return __builtin_inl(port);
|
||||
}
|
||||
|
||||
#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)); }
|
||||
#else
|
||||
|
||||
#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
|
||||
static inline void outb(uint8_t value, uint16_t port)
|
||||
{
|
||||
__asm__ __volatile__ ("outb %b0, %w1" : : "a" (value), "Nd" (port));
|
||||
}
|
||||
|
||||
__OUT(b,"b",char)
|
||||
__OUT(w,"w",short)
|
||||
__OUT(l,,int)
|
||||
static inline void outw(uint16_t value, uint16_t port)
|
||||
{
|
||||
__asm__ __volatile__ ("outw %w0, %w1" : : "a" (value), "Nd" (port));
|
||||
}
|
||||
|
||||
__INS(b)
|
||||
__INS(w)
|
||||
__INS(l)
|
||||
static inline void outl(uint32_t value, uint16_t port)
|
||||
{
|
||||
__asm__ __volatile__ ("outl %0, %w1" : : "a" (value), "Nd" (port));
|
||||
}
|
||||
|
||||
__OUTS(b)
|
||||
__OUTS(w)
|
||||
__OUTS(l)
|
||||
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
|
||||
|
||||
|
@@ -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) | \
|
||||
|
@@ -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;
|
||||
}
|
||||
|
76
src/arch/i386/smp/secondary.S
Normal file
76
src/arch/i386/smp/secondary.S
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <arch/asm.h>
|
||||
#include <arch/intel.h>
|
||||
#include <cpu/p6/mtrr.h>
|
||||
#include <cpu/p6/apic.h>
|
||||
.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
|
@@ -3,6 +3,7 @@
|
||||
#include <cpu/p6/apic.h>
|
||||
#include <delay.h>
|
||||
#include <string.h>
|
||||
#include <console/console.h>
|
||||
|
||||
#ifndef START_CPU_SEG
|
||||
#define START_CPU_SEG 0x90000
|
||||
|
Reference in New Issue
Block a user