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 typedef void (*process_ap_t) (u32 apicid, void *gp);
19 //core_range = 0 : all cores
20 //core range = 1 : core 0 only
21 //core range = 2 : cores other than core0
23 static void for_each_ap(u32 bsp_apicid, u32 core_range, process_ap_t process_ap,
26 // here assume the OS don't change our apicid
32 u32 e0_later_single_core;
36 /* get_nodes define in in_coherent_ht.c */
39 disable_siblings = !CONFIG_LOGICAL_CPUS;
41 #if CONFIG_LOGICAL_CPUS == 1 && CONFIG_HAVE_OPTION_TABLE == 1
42 if (read_option(CMOS_VSTART_multi_core, CMOS_VLEN_multi_core, 0) != 0) { // 0 mean multi core
47 /* here I assume that all node are same stepping, otherwise we can use use nb_cfg_54 from bsp for all nodes */
48 nb_cfg_54 = read_nb_cfg_54();
50 for (i = 0; i < nodes; i++) {
51 e0_later_single_core = 0;
52 j = ((pci_read_config32(PCI_DEV(0, 0x18 + i, 3), 0xe8) >> 12) &
55 if (j == 0) { // if it is single core, we need to increase siblings for apic calculation
56 #if CONFIG_K8_REV_F_SUPPORT == 0
57 e0_later_single_core = is_e0_later_in_bsp(i); // single core
59 e0_later_single_core = is_cpu_f0_in_bsp(i); // We can read cpuid(1) from Func3
62 if (e0_later_single_core) {
70 if (core_range == 2) {
76 if (e0_later_single_core || disable_siblings
77 || (core_range == 1)) {
83 for (j = jstart; j <= jend; j++) {
85 i * (nb_cfg_54 ? (siblings + 1) : 1) +
86 j * (nb_cfg_54 ? 1 : 8);
88 #if (CONFIG_ENABLE_APIC_EXT_ID == 1)
89 #if CONFIG_LIFT_BSP_APIC_ID == 0
90 if ((i != 0) || (j != 0)) /* except bsp */
92 ap_apicid += CONFIG_APIC_ID_OFFSET;
95 if (ap_apicid == bsp_apicid)
98 process_ap(ap_apicid, gp);
104 static inline int lapic_remote_read(int apicid, int reg, u32 *pvalue)
109 lapic_wait_icr_idle();
110 lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
111 lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
113 /* Extra busy check compared to lapic.h */
116 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
117 } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
121 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
122 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
126 if (status == LAPIC_ICR_RR_VALID) {
127 *pvalue = lapic_read(LAPIC_RRR);
133 #define LAPIC_MSG_REG 0x380
136 static void init_fidvid_ap(u32 bsp_apicid, u32 apicid);
139 static inline __attribute__ ((always_inline))
140 void print_apicid_nodeid_coreid(u32 apicid, struct node_core_id id,
144 "%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str,
145 apicid, id.nodeid, id.coreid);
148 static u32 wait_cpu_state(u32 apicid, u32 state)
154 if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) != 0)
156 if ((readback & 0xff) == state) {
158 break; //target cpu is in stage started
170 static void wait_ap_started(u32 ap_apicid, void *gp)
173 timeout = wait_cpu_state(ap_apicid, 0x33); // started
174 printk(BIOS_DEBUG, "* AP %02x", ap_apicid);
176 printk(BIOS_DEBUG, " timed out:%08x\n", timeout);
178 printk(BIOS_DEBUG, "started\n");
182 static void wait_all_aps_started(u32 bsp_apicid)
184 for_each_ap(bsp_apicid, 0, wait_ap_started, (void *)0);
187 static void wait_all_other_cores_started(u32 bsp_apicid)
189 // all aps other than core0
190 printk(BIOS_DEBUG, "started ap apicid: ");
191 for_each_ap(bsp_apicid, 2, wait_ap_started, (void *)0);
192 printk(BIOS_DEBUG, "\n");
195 static void allow_all_aps_stop(u32 bsp_apicid)
199 lapic_write(LAPIC_MSG_REG, (bsp_apicid << 24) | 0x44);
202 static void STOP_CAR_AND_CPU(void)
204 disable_cache_as_ram(); // inline
205 /* stop all cores except node0/core0 the bsp .... */
209 #if RAMINIT_SYSINFO == 1
210 static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
212 static u32 init_cpus(u32 cpu_init_detectedx)
217 struct node_core_id id;
220 * already set early mtrr in cache_as_ram.inc
223 /* that is from initial apicid, we need nodeid and coreid
225 id = get_node_core_id_x();
227 /* NB_CFG MSR is shared between cores, so we need make sure
228 core0 is done at first --- use wait_all_core0_started */
229 if (id.coreid == 0) {
230 set_apicid_cpuid_lo(); /* only set it on core0 */
231 #if (CONFIG_ENABLE_APIC_EXT_ID == 1)
232 enable_apic_ext_id(id.nodeid);
237 // init_timer(); // We need TMICT to pass msg for FID/VID change
239 #if (CONFIG_ENABLE_APIC_EXT_ID == 1)
240 u32 initial_apicid = get_initial_apicid();
242 #if CONFIG_LIFT_BSP_APIC_ID == 0
243 if (initial_apicid != 0) // other than bsp
246 /* use initial apic id to lift it */
247 u32 dword = lapic_read(LAPIC_ID);
248 dword &= ~(0xff << 24);
250 (((initial_apicid + CONFIG_APIC_ID_OFFSET) & 0xff) << 24);
252 lapic_write(LAPIC_ID, dword);
254 #if CONFIG_LIFT_BSP_APIC_ID == 1
255 bsp_apicid += CONFIG_APIC_ID_OFFSET;
260 /* get the apicid, it may be lifted already */
264 // show our apicid, nodeid, and coreid
265 if (id.coreid == 0) {
266 if (id.nodeid != 0) //all core0 except bsp
267 print_apicid_nodeid_coreid(apicid, id, " core0: ");
268 } else { //all other cores
269 print_apicid_nodeid_coreid(apicid, id, " corex: ");
273 if (cpu_init_detectedx) {
274 print_apicid_nodeid_coreid(apicid, id,
275 "\n\n\nINIT detected from ");
276 printk(BIOS_DEBUG, "\nIssuing SOFT_RESET...\n");
280 if (id.coreid == 0) {
281 distinguish_cpu_resets(id.nodeid);
282 // start_other_core(id.nodeid); // start second core in first cpu, only allowed for nb_cfg_54 is not set
284 //here don't need to wait
285 lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x33); // mark the cpu is started
287 if (apicid != bsp_apicid) {
292 #if (CONFIG_LOGICAL_CPUS == 1) && (SET_FIDVID_CORE0_ONLY == 1)
293 if (id.coreid == 0) // only need set fid for core0
295 init_fidvid_ap(bsp_apicid, apicid);
298 // We need to stop the CACHE as RAM for this CPU, really?
299 while (timeout && (loop-- > 0)) {
300 timeout = wait_cpu_state(bsp_apicid, 0x44);
304 "while waiting for BSP signal to STOP, timeout in ap %02x\n",
307 lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x44); // bsp can not check it before stop_this_cpu
308 set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
309 #if CONFIG_MEM_TRAIN_SEQ == 1
310 train_ram_on_node(id.nodeid, id.coreid, sysinfo,
311 (unsigned)STOP_CAR_AND_CPU);
320 static u32 is_core0_started(u32 nodeid)
324 device = PCI_DEV(0, 0x18 + nodeid, 0);
325 htic = pci_read_config32(device, HT_INIT_CONTROL);
326 htic &= HTIC_INIT_Detect;
330 static void wait_all_core0_started(void)
332 /* When core0 is started, it will distingush_cpu_resets
333 * So wait for that to finish */
335 u32 nodes = get_nodes();
337 printk(BIOS_DEBUG, "core0 started: ");
338 for (i = 1; i < nodes; i++) { // skip bsp, because it is running on bsp
339 while (!is_core0_started(i)) {
341 printk(BIOS_DEBUG, " %02x", i);
343 printk(BIOS_DEBUG, "\n");