- Initial checkin of the freebios2 tree
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@784 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
139
src/arch/i386/lib/cpu.c
Normal file
139
src/arch/i386/lib/cpu.c
Normal file
@ -0,0 +1,139 @@
|
||||
#include <console/console.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <mem.h>
|
||||
#include <arch/io.h>
|
||||
#include <string.h>
|
||||
#include <cpu/cpufixup.h>
|
||||
#include <smp/start_stop.h>
|
||||
#include <cpu/cpufixup.h>
|
||||
#include <cpu/p6/mtrr.h>
|
||||
#include <cpu/p6/msr.h>
|
||||
#include <cpu/p6/apic.h>
|
||||
#include <cpu/p5/cpuid.h>
|
||||
#if 0
|
||||
#include <cpu/l2_cache.h>
|
||||
#endif
|
||||
|
||||
#if CONFIG_SMP || CONFIG_IOAPIC
|
||||
#define APIC 1
|
||||
#endif
|
||||
|
||||
static void cache_on(struct mem_range *mem)
|
||||
{
|
||||
post_code(0x60);
|
||||
printk_info("Enabling cache...");
|
||||
|
||||
|
||||
/* we need an #ifdef i586 here at some point ... */
|
||||
__asm__ __volatile__("mov %cr0, %eax\n\t"
|
||||
"and $0x9fffffff,%eax\n\t"
|
||||
"mov %eax, %cr0\n\t");
|
||||
/* turns out cache isn't really on until you set MTRR registers on
|
||||
* 686 and later.
|
||||
* NOTHING FANCY. Linux does a much better job anyway.
|
||||
* so absolute minimum needed to get it going.
|
||||
*/
|
||||
/* OK, linux it turns out does nothing. We have to do it ... */
|
||||
#if defined(i686)
|
||||
// totalram here is in linux sizing, i.e. units of KB.
|
||||
// set_mtrr is responsible for getting it into the right units!
|
||||
setup_mtrrs(mem);
|
||||
#endif
|
||||
|
||||
post_code(0x6A);
|
||||
printk_info("done.\n");
|
||||
}
|
||||
|
||||
static void interrupts_on()
|
||||
{
|
||||
/* this is so interrupts work. This is very limited scope --
|
||||
* linux will do better later, we hope ...
|
||||
*/
|
||||
/* this is the first way we learned to do it. It fails on real SMP
|
||||
* stuff. So we have to do things differently ...
|
||||
* see the Intel mp1.4 spec, page A-3
|
||||
*/
|
||||
|
||||
#if defined(APIC)
|
||||
/* Only Pentium Pro and later have those MSR stuff */
|
||||
unsigned long low, high;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/* Put the local apic in virtual wire mode */
|
||||
apic_write_around(APIC_SPIV,
|
||||
(apic_read_around(APIC_SPIV) & ~(APIC_VECTOR_MASK))
|
||||
| APIC_SPIV_ENABLE);
|
||||
apic_write_around(APIC_LVT0,
|
||||
(apic_read_around(APIC_LVT0) &
|
||||
~(APIC_LVT_MASKED | APIC_LVT_LEVEL_TRIGGER |
|
||||
APIC_LVT_REMOTE_IRR | APIC_INPUT_POLARITY |
|
||||
APIC_SEND_PENDING |APIC_LVT_RESERVED_1 |
|
||||
APIC_DELIVERY_MODE_MASK))
|
||||
| (APIC_LVT_REMOTE_IRR |APIC_SEND_PENDING |
|
||||
APIC_DELIVERY_MODE_EXTINT)
|
||||
);
|
||||
apic_write_around(APIC_LVT1,
|
||||
(apic_read_around(APIC_LVT1) &
|
||||
~(APIC_LVT_MASKED | APIC_LVT_LEVEL_TRIGGER |
|
||||
APIC_LVT_REMOTE_IRR | APIC_INPUT_POLARITY |
|
||||
APIC_SEND_PENDING |APIC_LVT_RESERVED_1 |
|
||||
APIC_DELIVERY_MODE_MASK))
|
||||
| (APIC_LVT_REMOTE_IRR |APIC_SEND_PENDING |
|
||||
APIC_DELIVERY_MODE_NMI)
|
||||
);
|
||||
#else /* APIC */
|
||||
#ifdef i686
|
||||
/* Only Pentium Pro and later have those MSR stuff */
|
||||
unsigned long low, high;
|
||||
|
||||
printk_info("Disabling local apic...");
|
||||
|
||||
rdmsr(APIC_BASE_MSR, low, high);
|
||||
low &= ~APIC_BASE_MSR_ENABLE;
|
||||
wrmsr(APIC_BASE_MSR, low, high);
|
||||
#endif /* i686 */
|
||||
#endif /* APIC */
|
||||
printk_info("done.\n");
|
||||
post_code(0x9b);
|
||||
}
|
||||
|
||||
unsigned long cpu_initialize(struct mem_range *mem)
|
||||
{
|
||||
/* Because we busy wait at the printk spinlock.
|
||||
* It is important to keep the number of printed messages
|
||||
* from secondary cpus to a minimum, when debugging is
|
||||
* disabled.
|
||||
*/
|
||||
unsigned long processor_id = this_processors_id();
|
||||
printk_notice("Initializing CPU #%d\n", processor_id);
|
||||
|
||||
/* some cpus need a fixup done. This is the hook for doing that. */
|
||||
cpufixup(mem);
|
||||
|
||||
/* Turn on caching if we haven't already */
|
||||
cache_on(mem);
|
||||
|
||||
display_cpuid();
|
||||
mtrr_check();
|
||||
|
||||
#if 0
|
||||
/* now that everything is really up, enable the l2 cache if desired.
|
||||
* The enable can wait until this point, because linuxbios and it's
|
||||
* data areas are tiny, easily fitting into the L1 cache.
|
||||
*/
|
||||
configure_l2_cache();
|
||||
#endif
|
||||
interrupts_on();
|
||||
printk_info("CPU #%d Initialized\n", processor_id);
|
||||
return processor_id;
|
||||
}
|
||||
|
Reference in New Issue
Block a user