1 /* 2004.12 yhlu add dual core support */
3 #include "cpu/amd/dualcore/dualcore_id.c"
5 static inline unsigned get_core_num_in_bsp(unsigned nodeid)
7 return ((pci_read_config32(PCI_DEV(0, 0x18+nodeid, 3), 0xe8)>>12) & 3);
10 static inline uint8_t set_apicid_cpuid_lo(void)
12 if(is_cpu_pre_e0()) return 0; // pre_e0 can not be set
15 if(read_option(CMOS_VSTART_dual_core, CMOS_VLEN_dual_core, 0) != 0) { // disable dual_core
19 // set the NB_CFG[54]=1; why the OS will be happy with that ???
21 msr = rdmsr(NB_CFG_MSR);
22 msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
23 wrmsr(NB_CFG_MSR, msr);
29 #if USE_DCACHE_RAM == 0
30 static void do_k8_init_and_stop_secondaries(void)
32 struct node_core_id id;
35 unsigned max_siblings;
38 /* Skip this if there was a built in self test failure */
40 if (is_cpu_pre_e0()) {
41 id.nodeid = lapicid() & 0x7;
44 /* Which cpu are we on? */
45 id = get_node_core_id_x();
48 * Linux expect the core to be in the least signficant bits.
50 msr = rdmsr(NB_CFG_MSR);
51 msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
52 wrmsr(NB_CFG_MSR, msr);
55 /* For now assume all cpus have the same number of siblings */
56 max_siblings = (cpuid_ecx(0x80000008) & 0xff) + 1;
58 /* Enable extended apic ids */
59 device_t dev_f0 = PCI_DEV(0, 0x18+id.nodeid, 0);
60 unsigned val = pci_read_config32(dev_f0, 0x68);
61 val |= (1 << 18) | (1 << 17);
62 pci_write_config32(dev_f0, 0x68, val);
65 lapic_write(LAPIC_ID,(0x10 + id.coreid*0x10 + id.nodeid) << 24);
67 /* Remember the cpuid */
69 dev = PCI_DEV(0, 0x18 + id.nodeid, 2);
70 pci_write_config32(dev, 0x9c, cpuid_eax(1));
73 /* Maybe call distinguish_cpu_resets only on the last core? */
74 distinguish_cpu_resets(id.nodeid);
80 static void k8_init_and_stop_secondaries(void)
82 /* This doesn't work with Cache As Ram because it messes with
83 the MTRR state, which breaks the init detection.
84 do_k8_init_and_stop_secondaries should be usable by CAR code.
89 init_detected = early_mtrr_init_detected();
90 amd_early_mtrr_init();
95 asm volatile ("jmp __cpu_reset");
98 do_k8_init_and_stop_secondaries();