speed up ecc clear by enable MTRR/Cache first.
[coreboot.git] / src / arch / i386 / lib / cpu.c
1 #include <console/console.h>
2 #include <cpu/cpu.h>
3 #include <mem.h>
4 #include <arch/io.h>
5 #include <string.h>
6 #include <cpu/cpufixup.h>
7 #include <smp/start_stop.h>
8 #include <cpu/cpufixup.h>
9 #include <cpu/p6/mtrr.h>
10 #include <cpu/p6/msr.h>
11 #include <cpu/p6/apic.h>
12 #include <cpu/p5/cpuid.h>
13 #include <arch/smp/lapic.h>
14 #if 0
15 #include <cpu/l2_cache.h>
16 #endif
17
18 #if CONFIG_SMP || CONFIG_IOAPIC
19 #define APIC 1
20 #endif
21
22
23 static void cache_on(struct mem_range *mem)
24 {
25         post_code(0x60);
26         printk_info("Enabling cache...");
27
28
29         /* we need an #ifdef i586 here at some point ... */
30         __asm__ __volatile__("mov %cr0, %eax\n\t"
31                              "and $0x9fffffff,%eax\n\t"
32                              "mov %eax, %cr0\n\t");
33         /* turns out cache isn't really on until you set MTRR registers on 
34          * 686 and later. 
35          * NOTHING FANCY. Linux does a much better job anyway. 
36          * so absolute minimum needed to get it going. 
37          */
38         /* OK, linux it turns out does nothing. We have to do it ... */
39 #if i686==1
40         // totalram here is in linux sizing, i.e. units of KB. 
41         // set_mtrr is responsible for getting it into the right units!
42         setup_mtrrs(mem);
43 #endif
44
45         post_code(0x6A);
46         printk_info("done.\n");
47 }
48
49 static void interrupts_on()
50 {
51         /* this is so interrupts work. This is very limited scope -- 
52          * linux will do better later, we hope ...
53          */
54         /* this is the first way we learned to do it. It fails on real SMP 
55          * stuff. So we have to do things differently ... 
56          * see the Intel mp1.4 spec, page A-3
57          */
58
59 #if defined(APIC)
60         /* Only Pentium Pro and later have those MSR stuff */
61         msr_t msr;
62
63         printk_info("Setting up local apic...");
64
65         /* Enable the local apic */
66         msr = rdmsr(APIC_BASE_MSR);
67         msr.lo |= APIC_BASE_MSR_ENABLE;
68         msr.lo &= ~APIC_BASE_MSR_ADDR_MASK;
69         msr.lo |= APIC_DEFAULT_BASE;
70         wrmsr(APIC_BASE_MSR, msr);
71
72         /*
73          * Set Task Priority to 'accept all'.
74          */
75         apic_write_around(APIC_TASKPRI,
76                 apic_read_around(APIC_TASKPRI) & ~APIC_TPRI_MASK);
77
78         /* Put the local apic in virtual wire mode */
79         apic_write_around(APIC_SPIV, 
80                 (apic_read_around(APIC_SPIV) & ~(APIC_VECTOR_MASK))
81                 | APIC_SPIV_ENABLE);
82         apic_write_around(APIC_LVT0, 
83                 (apic_read_around(APIC_LVT0) & 
84                         ~(APIC_LVT_MASKED | APIC_LVT_LEVEL_TRIGGER | 
85                                 APIC_LVT_REMOTE_IRR | APIC_INPUT_POLARITY | 
86                                 APIC_SEND_PENDING |APIC_LVT_RESERVED_1 |
87                                 APIC_DELIVERY_MODE_MASK))
88                 | (APIC_LVT_REMOTE_IRR |APIC_SEND_PENDING | 
89                         APIC_DELIVERY_MODE_EXTINT)
90                 );
91         apic_write_around(APIC_LVT1, 
92                 (apic_read_around(APIC_LVT1) & 
93                         ~(APIC_LVT_MASKED | APIC_LVT_LEVEL_TRIGGER | 
94                                 APIC_LVT_REMOTE_IRR | APIC_INPUT_POLARITY | 
95                                 APIC_SEND_PENDING |APIC_LVT_RESERVED_1 |
96                                 APIC_DELIVERY_MODE_MASK))
97                 | (APIC_LVT_REMOTE_IRR |APIC_SEND_PENDING | 
98                         APIC_DELIVERY_MODE_NMI)
99                 );
100
101         printk_debug(" apic_id: %d ", lapicid());
102
103 #else /* APIC */
104 #if i686==1
105         /* Only Pentium Pro and later have those MSR stuff */
106         msr_t msr;
107
108         printk_info("Disabling local apic...");
109
110         msr = rdmsr(APIC_BASE_MSR);
111         msr.lo &= ~APIC_BASE_MSR_ENABLE;
112         wrmsr(APIC_BASE_MSR, msr);
113 #endif /* i686 */
114 #endif /* APIC */
115         printk_info("done.\n");
116         post_code(0x9b);
117 }
118
119 unsigned long cpu_initialize(struct mem_range *mem)
120 {
121         /* Because we busy wait at the printk spinlock.
122          * It is important to keep the number of printed messages
123          * from secondary cpus to a minimum, when debugging is
124          * disabled.
125          */
126         unsigned long processor_id = this_processors_id();
127         printk_notice("Initializing CPU #%d\n", processor_id);
128
129         /* Turn on caching if we haven't already */
130         cache_on(mem);
131
132         display_cpuid();
133         mtrr_check();
134
135         /* some cpus need a fixup done. This is the hook for doing that. */
136         cpufixup(mem);
137
138 #if 0
139         /* now that everything is really up, enable the l2 cache if desired. 
140          * The enable can wait until this point, because linuxbios and it's
141          * data areas are tiny, easily fitting into the L1 cache. 
142          */
143         configure_l2_cache();
144 #endif
145
146         interrupts_on();
147         processor_id = this_processors_id();
148         printk_info("CPU #%d Initialized\n", processor_id);
149         return processor_id;
150 }
151