1 //it takes the CONFIG_ENABLE_APIC_EXT_ID and CONFIG_APIC_ID_OFFSET and CONFIG_LIFT_BSP_APIC_ID
3 #if CONFIG_K8_REV_F_SUPPORT == 0
6 // for rev F, need to set FID to max
12 #ifndef SET_FIDVID_CORE0_ONLY
13 /* MSR FIDVID_CTL and FIDVID_STATUS are shared by cores, so may don't need to do twice*/
14 #define SET_FIDVID_CORE0_ONLY 1
17 static inline void print_initcpu8 (const char *strval, unsigned val)
19 printk(BIOS_DEBUG, "%s%02x\n", strval, val);
22 static inline void print_initcpu8_nocr (const char *strval, unsigned val)
24 printk(BIOS_DEBUG, "%s%02x", strval, val);
28 static inline void print_initcpu16 (const char *strval, unsigned val)
30 printk(BIOS_DEBUG, "%s%04x\n", strval, val);
33 static inline void print_initcpu(const char *strval, unsigned val)
35 printk(BIOS_DEBUG, "%s%08x\n", strval, val);
38 typedef void (*process_ap_t)(unsigned apicid, void *gp);
40 //core_range = 0 : all cores
41 //core range = 1 : core 0 only
42 //core range = 2 : cores other than core0
43 static void for_each_ap(unsigned bsp_apicid, unsigned core_range, process_ap_t process_ap, void *gp)
45 // here assume the OS don't change our apicid
49 unsigned siblings = 0;
50 unsigned disable_siblings;
51 unsigned e0_later_single_core;
55 /* get_nodes define in in_coherent_ht.c */
58 disable_siblings = !CONFIG_LOGICAL_CPUS;
59 #if CONFIG_LOGICAL_CPUS == 1 && CONFIG_HAVE_OPTION_TABLE == 1
60 if(read_option(CMOS_VSTART_multi_core, CMOS_VLEN_multi_core, 0) != 0) { // 0 mean multi core
65 /* here I assume that all node are same stepping, otherwise we can use use nb_cfg_54 from bsp for all nodes */
66 nb_cfg_54 = read_nb_cfg_54();
69 for(i=0; i<nodes;i++) {
70 e0_later_single_core = 0;
71 j = ((pci_read_config32(PCI_DEV(0, 0x18+i, 3), 0xe8) >> 12) & 3);
73 if(j == 0 ){ // if it is single core, we need to increase siblings for apic calculation
74 #if CONFIG_K8_REV_F_SUPPORT == 0
75 e0_later_single_core = is_e0_later_in_bsp(i); // single core
77 e0_later_single_core = is_cpu_f0_in_bsp(i); // We can read cpuid(1) from Func3
80 if(e0_later_single_core) {
86 unsigned jstart, jend;
95 if(e0_later_single_core || disable_siblings || (core_range==1)) {
102 for(j=jstart; j<=jend; j++) {
104 ap_apicid = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:8);
106 #if (CONFIG_ENABLE_APIC_EXT_ID == 1)
107 #if CONFIG_LIFT_BSP_APIC_ID == 0
108 if( (i!=0) || (j!=0)) /* except bsp */
110 ap_apicid += CONFIG_APIC_ID_OFFSET;
113 if(ap_apicid == bsp_apicid) continue;
115 process_ap(ap_apicid, gp);
122 static inline int lapic_remote_read(int apicid, int reg, unsigned *pvalue)
127 lapic_wait_icr_idle();
128 lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
129 lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
133 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
134 } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
138 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
139 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
142 if (status == LAPIC_ICR_RR_VALID) {
143 *pvalue = lapic_read(LAPIC_RRR);
149 #define LAPIC_MSG_REG 0x380
153 static void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid);
156 static inline __attribute__((always_inline)) void print_apicid_nodeid_coreid(unsigned apicid, struct node_core_id id, const char *str)
158 printk(BIOS_DEBUG, "%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str, apicid, id.nodeid, id.coreid);
162 static unsigned wait_cpu_state(unsigned apicid, unsigned state)
164 unsigned readback = 0;
165 unsigned timeout = 1;
168 if(lapic_remote_read(apicid, LAPIC_MSG_REG, &readback)!=0) continue;
169 if((readback & 0xff) == state) {
171 break; //target cpu is in stage started
182 static void wait_ap_started(unsigned ap_apicid, void *gp )
185 timeout = wait_cpu_state(ap_apicid, 0x33); // started
187 print_initcpu8_nocr("*", ap_apicid);
188 print_initcpu("*", timeout);
191 print_initcpu8_nocr(" ", ap_apicid);
195 static void wait_all_aps_started(unsigned bsp_apicid)
197 for_each_ap(bsp_apicid, 0 , wait_ap_started, (void *)0);
200 static void wait_all_other_cores_started(unsigned bsp_apicid) // all aps other than core0
202 print_debug("started ap apicid: ");
203 for_each_ap(bsp_apicid, 2 , wait_ap_started, (void *)0);
207 static void allow_all_aps_stop(unsigned bsp_apicid)
209 lapic_write(LAPIC_MSG_REG, (bsp_apicid<<24) | 0x44); // allow aps to stop
212 static void STOP_CAR_AND_CPU(void)
214 disable_cache_as_ram(); // inline
215 stop_this_cpu(); // inline, it will stop all cores except node0/core0 the bsp ....
218 #if CONFIG_MEM_TRAIN_SEQ == 1
219 static inline void train_ram_on_node(unsigned nodeid, unsigned coreid, struct sys_info *sysinfo, unsigned retcall);
222 #if RAMINIT_SYSINFO == 1
223 static unsigned init_cpus(unsigned cpu_init_detectedx ,struct sys_info *sysinfo)
225 static unsigned init_cpus(unsigned cpu_init_detectedx)
228 unsigned bsp_apicid = 0;
230 struct node_core_id id;
233 * already set early mtrr in cache_as_ram.inc
236 /* that is from initial apicid, we need nodeid and coreid later */
237 id = get_node_core_id_x();
240 /* NB_CFG MSR is shared between cores, so we need make sure core0 is done at first --- use wait_all_core0_started */
242 set_apicid_cpuid_lo(); /* only set it on core0 */
243 #if CONFIG_ENABLE_APIC_EXT_ID == 1
244 enable_apic_ext_id(id.nodeid);
249 // init_timer(); // We need TMICT to pass msg for FID/VID change
251 #if (CONFIG_ENABLE_APIC_EXT_ID == 1)
252 unsigned initial_apicid = get_initial_apicid();
253 #if CONFIG_LIFT_BSP_APIC_ID == 0
254 if( initial_apicid != 0 ) // other than bsp
257 /* use initial apic id to lift it */
258 uint32_t dword = lapic_read(LAPIC_ID);
259 dword &= ~(0xff<<24);
260 dword |= (((initial_apicid + CONFIG_APIC_ID_OFFSET) & 0xff)<<24);
262 lapic_write(LAPIC_ID, dword);
265 #if CONFIG_LIFT_BSP_APIC_ID == 1
266 bsp_apicid += CONFIG_APIC_ID_OFFSET;
271 /* get the apicid, it may be lifted already */
275 // show our apicid, nodeid, and coreid
277 if (id.nodeid!=0) //all core0 except bsp
278 print_apicid_nodeid_coreid(apicid, id, " core0: ");
282 print_apicid_nodeid_coreid(apicid, id, " core1: ");
288 if (cpu_init_detectedx) {
289 print_apicid_nodeid_coreid(apicid, id, "\n\n\nINIT detected from ");
290 print_debug("\nIssuing SOFT_RESET...\n");
295 distinguish_cpu_resets(id.nodeid);
296 // start_other_core(id.nodeid); // start second core in first cpu, only allowed for nb_cfg_54 is not set
299 //here don't need to wait
300 lapic_write(LAPIC_MSG_REG, (apicid<<24) | 0x33); // mark the cpu is started
302 if(apicid != bsp_apicid) {
306 #if (CONFIG_LOGICAL_CPUS == 1) && (SET_FIDVID_CORE0_ONLY == 1)
307 if(id.coreid == 0 ) // only need set fid for core0
309 init_fidvid_ap(bsp_apicid, apicid);
312 // We need to stop the CACHE as RAM for this CPU, really?
313 while(timeout && (loop-->0)) {
314 timeout = wait_cpu_state(bsp_apicid, 0x44);
317 print_initcpu8("while waiting for BSP signal to STOP, timeout in ap ", apicid);
319 lapic_write(LAPIC_MSG_REG, (apicid<<24) | 0x44); // bsp can not check it before stop_this_cpu
320 set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
321 #if CONFIG_MEM_TRAIN_SEQ == 1
322 train_ram_on_node(id.nodeid, id.coreid, sysinfo,
323 (unsigned) STOP_CAR_AND_CPU);
333 static unsigned is_core0_started(unsigned nodeid)
337 device = PCI_DEV(0, 0x18 + nodeid, 0);
338 htic = pci_read_config32(device, HT_INIT_CONTROL);
339 htic &= HTIC_INIT_Detect;
343 static void wait_all_core0_started(void)
345 //When core0 is started, it will distingush_cpu_resets. So wait for that
347 unsigned nodes = get_nodes();
349 print_debug("core0 started: ");
350 for(i=1;i<nodes;i++) { // skip bsp, because it is running on bsp
351 while(!is_core0_started(i)) {}
352 print_initcpu8_nocr(" ", i);