summaryrefslogtreecommitdiff
path: root/src/cpu/amd/dualcore/dualcore.c
blob: 3923891678b6bde425baf01a0c0af46f6e59afd8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/* 2004.12 yhlu add dual core support */

#include "cpu/amd/dualcore/dualcore_id.c"

static inline unsigned get_core_num_in_bsp(unsigned nodeid)
{
        return ((pci_read_config32(PCI_DEV(0, 0x18+nodeid, 3), 0xe8)>>12) & 3);
}

static inline uint8_t set_apicid_cpuid_lo(void) 
{
        if(is_cpu_pre_e0()) return 0; // pre_e0 can not be set


        if(read_option(CMOS_VSTART_dual_core, CMOS_VLEN_dual_core, 0) != 0)  { // disable dual_core
                return 0;
        }

                // set the NB_CFG[54]=1; why the OS will be happy with that ???
        msr_t msr;
        msr = rdmsr(NB_CFG_MSR);
        msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
        wrmsr(NB_CFG_MSR, msr);

        return 1;

}

#if USE_DCACHE_RAM == 0
static void do_k8_init_and_stop_secondaries(void)
{
	struct node_core_id id;
	device_t dev;
	unsigned apicid;
	unsigned max_siblings;
	msr_t msr;
	
	/* Skip this if there was a built in self test failure */

	if (is_cpu_pre_e0()) {
		id.nodeid = lapicid() & 0x7;
		id.coreid = 0;
	} else {
		/* Which cpu are we on? */
		id = get_node_core_id_x();

		/* Set NB_CFG_MSR
		 * Linux expect the core to be in the least signficant bits.
		 */
		msr = rdmsr(NB_CFG_MSR);
		msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
		wrmsr(NB_CFG_MSR, msr);
	}

	/* For now assume all cpus have the same number of siblings */
	max_siblings = (cpuid_ecx(0x80000008) & 0xff) + 1;

	/* Enable extended apic ids */
	device_t dev_f0 = PCI_DEV(0, 0x18+id.nodeid, 0);
	unsigned val = pci_read_config32(dev_f0, 0x68);
	val |= (1 << 18) | (1 << 17);
	pci_write_config32(dev_f0, 0x68, val);

	/* Set the lapicid */
	lapic_write(LAPIC_ID,(0x10 + id.coreid*0x10 + id.nodeid) << 24);

	/* Remember the cpuid */
	if (id.coreid == 0) {
		dev = PCI_DEV(0, 0x18 + id.nodeid, 2);
		pci_write_config32(dev, 0x9c, cpuid_eax(1));	
	}
	
	/* Maybe call distinguish_cpu_resets only on the last core? */
	distinguish_cpu_resets(id.nodeid);
	if (!boot_cpu()) {
		stop_this_cpu();
	}
}

static void k8_init_and_stop_secondaries(void)
{
	/* This doesn't work with Cache As Ram because it messes with 
	   the MTRR state, which breaks the init detection.
	   do_k8_init_and_stop_secondaries should be usable by CAR code.
	*/

	int init_detected;

	init_detected = early_mtrr_init_detected();
	amd_early_mtrr_init();

	enable_lapic();
	init_timer();
	if (init_detected) {
		asm volatile ("jmp __cpu_reset");
	}

	do_k8_init_and_stop_secondaries();
}

#endif