1 //it takes the ENABLE_APIC_EXT_ID and APIC_ID_OFFSET and LIFT_BSP_APIC_ID
3 #define K8_SET_FIDVID 0
6 #ifndef K8_SET_FIDVID_CORE0_ONLY
7 /* MSR FIDVID_CTL and FIDVID_STATUS are shared by cores, so may don't need to do twice*/
8 #define K8_SET_FIDVID_CORE0_ONLY 1
11 typedef void (*process_ap_t)(unsigned apicid, void *gp);
13 static void for_each_ap(unsigned bsp_apicid, unsigned core0_only, process_ap_t process_ap, void *gp)
15 // here assume the OS don't change our apicid
19 unsigned siblings = 0;
20 unsigned disable_siblings;
21 unsigned e0_later_single_core;
25 /* get_nodes define in in_coherent_ht.c */
28 disable_siblings = !CONFIG_LOGICAL_CPUS;
29 #if CONFIG_LOGICAL_CPUS == 1
30 if(read_option(CMOS_VSTART_dual_core, CMOS_VLEN_dual_core, 0) != 0) { // 0 mean dual core
35 /* here I assume that all node are same stepping, otherwise we can use use nb_cfg_54 from bsp for all nodes */
36 nb_cfg_54 = read_nb_cfg_54();
39 for(i=0; i<nodes;i++) {
40 e0_later_single_core = 0;
41 j = ((pci_read_config32(PCI_DEV(0, 0x18+i, 3), 0xe8) >> 12) & 3);
43 if(j == 0 ){ // if it is single core, we need to increase siblings for apic calculation
44 e0_later_single_core = is_e0_later_in_bsp(i); // single core
46 if(e0_later_single_core) {
54 if(e0_later_single_core || disable_siblings || core0_only) {
61 for(j=0; j<=jj; j++) {
63 ap_apicid = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:8);
65 #if (ENABLE_APIC_EXT_ID == 1)
66 #if LIFT_BSP_APIC_ID == 0
67 if( (i!=0) || (j!=0)) /* except bsp */
69 ap_apicid += APIC_ID_OFFSET;
72 if(ap_apicid == bsp_apicid) continue;
74 process_ap(ap_apicid, gp);
81 static inline int lapic_remote_read(int apicid, int reg, unsigned *pvalue)
86 lapic_wait_icr_idle();
87 lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
88 lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
92 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
93 } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
97 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
98 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
101 if (status == LAPIC_ICR_RR_VALID) {
102 *pvalue = lapic_read(LAPIC_RRR);
108 #define LAPIC_MSG_REG 0x380
111 #if K8_SET_FIDVID == 1
112 static void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid);
115 static inline __attribute__((always_inline)) void print_apicid_nodeid_coreid(unsigned apicid, struct node_core_id id, const char *str)
117 #if CONFIG_USE_INIT == 0
119 print_debug(" ---- {APICID = "); print_debug_hex8(apicid);
120 print_debug(" NODEID = "), print_debug_hex8(id.nodeid); print_debug(" COREID = "), print_debug_hex8(id.coreid);
121 print_debug("} --- \r\n");
123 printk_debug("%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\r\n", str, apicid, id.nodeid, id.coreid);
128 static void wait_cpu_state(unsigned apicid, unsigned state)
133 if(lapic_remote_read(apicid, LAPIC_MSG_REG, &readback)!=0) continue;
134 if((readback & 0xff) == state) break; //target cpu is in stage started
138 static void wait_ap_started(unsigned ap_apicid, void *gp )
140 wait_cpu_state(ap_apicid, 0x33); // started
143 static void wait_all_aps_started(unsigned bsp_apicid)
145 for_each_ap(bsp_apicid, 0 , wait_ap_started, (void *)0);
148 static void allow_all_aps_stop(unsigned bsp_apicid)
150 lapic_write(LAPIC_MSG_REG, (bsp_apicid<<24) | 0x44); // allow aps to stop
154 #if RAMINIT_SYSINFO == 1
155 static unsigned init_cpus(unsigned cpu_init_detectedx ,struct sys_info *sysinfo)
157 static unsigned init_cpus(unsigned cpu_init_detectedx)
160 unsigned bsp_apicid = 0;
162 struct node_core_id id;
165 * already set early mtrr in cache_as_ram.inc
168 /* that is from initial apicid, we need nodeid and coreid later */
169 id = get_node_core_id_x();
172 /* NB_CFG MSR is shared between cores, so we need make sure core0 is done at first --- use wait_all_core0_started */
174 set_apicid_cpuid_lo(); /* only set it on core0 */
175 #if ENABLE_APIC_EXT_ID == 1
176 enable_apic_ext_id(id.nodeid);
181 // init_timer(); // We need TMICT to pass msg for FID/VID change
183 #if (ENABLE_APIC_EXT_ID == 1)
184 unsigned initial_apicid = get_initial_apicid();
185 #if LIFT_BSP_APIC_ID == 0
186 if( initial_apicid != 0 ) // other than bsp
189 /* use initial apic id to lift it */
190 uint32_t dword = lapic_read(LAPIC_ID);
191 dword &= ~(0xff<<24);
192 dword |= (((initial_apicid + APIC_ID_OFFSET) & 0xff)<<24);
194 lapic_write(LAPIC_ID, dword);
197 #if LIFT_BSP_APIC_ID == 1
198 bsp_apicid += APIC_ID_OFFSET;
203 /* get the apicid, it may be lifted already */
207 // show our apicid, nodeid, and coreid
209 if (id.nodeid!=0) //all core0 except bsp
210 print_apicid_nodeid_coreid(apicid, id, " core0: ");
214 print_apicid_nodeid_coreid(apicid, id, " core1: ");
220 if (cpu_init_detectedx) {
221 print_apicid_nodeid_coreid(apicid, id, "\r\n\r\n\r\nINIT detected from ");
222 print_debug("\r\nIssuing SOFT_RESET...\r\n");
227 distinguish_cpu_resets(id.nodeid);
228 // start_other_core(id.nodeid); // start second core in first cpu, only allowed for nb_cfg_54 is not set
231 //here don't need to wait
232 lapic_write(LAPIC_MSG_REG, (apicid<<24) | 0x33); // mark the cpu is started
234 if(apicid != bsp_apicid) {
235 #if K8_SET_FIDVID == 1
236 #if (CONFIG_LOGICAL_CPUS == 1) && (K8_SET_FIDVID_CORE0_ONLY == 1)
237 if(id.coreid == 0 ) // only need set fid for core0
239 init_fidvid_ap(bsp_apicid, apicid);
242 // We need to stop the CACHE as RAM for this CPU, really?
243 wait_cpu_state(bsp_apicid, 0x44);
244 lapic_write(LAPIC_MSG_REG, (apicid<<24) | 0x44); // bsp can not check it before stop_this_cpu
246 set_init_ram_access(); //inline
247 disable_cache_as_ram(); // inline
248 stop_this_cpu(); // inline, it will stop all cores except node0/core0 the bsp ....
254 #if CONFIG_LOGICAL_CPUS == 1
256 static unsigned is_core0_started(unsigned nodeid)
260 device = PCI_DEV(0, 0x18 + nodeid, 0);
261 htic = pci_read_config32(device, HT_INIT_CONTROL);
262 htic &= HTIC_INIT_Detect;
266 static void wait_all_core0_started(void)
268 //When core0 is started, it will distingush_cpu_resets. So wait for that
270 unsigned nodes = get_nodes();
272 for(i=1;i<nodes;i++) { // skip bsp, because it is running on bsp
273 while(!is_core0_started(i)) {}