arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 1 | /* 2004.12 yhlu add dual core support */ |
| 2 | |
| 3 | #include <console/console.h> |
| 4 | #include <cpu/cpu.h> |
| 5 | #include <cpu/x86/lapic.h> |
Stefan Reinauer | 9a16e3e | 2010-03-29 14:45:36 +0000 | [diff] [blame] | 6 | #include <cpu/amd/multicore.h> |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 7 | #include <device/device.h> |
| 8 | #include <device/pci.h> |
| 9 | #include <pc80/mc146818rtc.h> |
| 10 | #include <smp/spinlock.h> |
| 11 | #include <cpu/x86/mtrr.h> |
Stefan Reinauer | 991f184 | 2015-11-22 23:40:29 +0100 | [diff] [blame] | 12 | #include <cpu/amd/msr.h> |
Stefan Reinauer | f5183cf | 2005-12-01 11:01:01 +0000 | [diff] [blame] | 13 | #include <cpu/amd/model_fxx_rev.h> |
Yinghai Lu | d4b278c | 2006-10-04 20:46:15 +0000 | [diff] [blame] | 14 | #include <cpu/amd/amdk8_sysconf.h> |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 15 | |
Luc Verhaegen | a9c5ea0 | 2009-06-03 14:19:33 +0000 | [diff] [blame] | 16 | static int disable_siblings = !CONFIG_LOGICAL_CPUS; |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 17 | |
Stefan Reinauer | f5183cf | 2005-12-01 11:01:01 +0000 | [diff] [blame] | 18 | #include "dualcore_id.c" |
Jason Schildt | 8b26cab | 2005-10-25 21:24:23 +0000 | [diff] [blame] | 19 | |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 20 | static int get_max_siblings(int nodes) |
| 21 | { |
| 22 | device_t dev; |
| 23 | int nodeid; |
| 24 | int siblings=0; |
| 25 | |
| 26 | //get max siblings from all the nodes |
| 27 | for(nodeid=0; nodeid<nodes; nodeid++){ |
| 28 | int j; |
| 29 | dev = dev_find_slot(0, PCI_DEVFN(0x18+nodeid, 3)); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 30 | j = (pci_read_config32(dev, 0xe8) >> 12) & 3; |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 31 | if(siblings < j) { |
| 32 | siblings = j; |
| 33 | } |
| 34 | } |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 35 | |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 36 | return siblings; |
| 37 | } |
| 38 | |
| 39 | static void enable_apic_ext_id(int nodes) |
| 40 | { |
| 41 | device_t dev; |
| 42 | int nodeid; |
| 43 | |
| 44 | //enable APIC_EXIT_ID all the nodes |
| 45 | for(nodeid=0; nodeid<nodes; nodeid++){ |
| 46 | uint32_t val; |
| 47 | dev = dev_find_slot(0, PCI_DEVFN(0x18+nodeid, 0)); |
| 48 | val = pci_read_config32(dev, 0x68); |
| 49 | val |= (1<<17)|(1<<18); |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 50 | pci_write_config32(dev, 0x68, val); |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 51 | } |
| 52 | } |
| 53 | |
| 54 | |
| 55 | unsigned get_apicid_base(unsigned ioapic_num) |
| 56 | { |
| 57 | device_t dev; |
| 58 | int nodes; |
| 59 | unsigned apicid_base; |
| 60 | int siblings; |
| 61 | unsigned nb_cfg_54; |
| 62 | int bsp_apic_id = lapicid(); // bsp apicid |
| 63 | |
Myles Watson | 4839e2c | 2010-04-08 15:06:44 +0000 | [diff] [blame] | 64 | get_option(&disable_siblings, "multi_core"); |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 65 | |
| 66 | //get the nodes number |
| 67 | dev = dev_find_slot(0, PCI_DEVFN(0x18,0)); |
| 68 | nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; |
| 69 | |
| 70 | siblings = get_max_siblings(nodes); |
| 71 | |
| 72 | if(bsp_apic_id > 0) { // io apic could start from 0 |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 73 | return 0; |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 74 | } else if(pci_read_config32(dev, 0x68) & ( (1<<17) | (1<<18)) ) { // enabled ext id but bsp = 0 |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 75 | return 1; |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | nb_cfg_54 = read_nb_cfg_54(); |
| 79 | |
Stefan Reinauer | f5183cf | 2005-12-01 11:01:01 +0000 | [diff] [blame] | 80 | #if 0 |
Stefan Reinauer | 38f147e | 2010-02-08 12:20:50 +0000 | [diff] [blame] | 81 | //it is for all e0 single core and nc_cfg_54 low is set, but in the romstage.c stage we do not set that bit for it. |
Stefan Reinauer | f5183cf | 2005-12-01 11:01:01 +0000 | [diff] [blame] | 82 | if(nb_cfg_54 && (!disable_siblings) && (siblings == 0)) { |
| 83 | //we need to check if e0 single core is there |
| 84 | int i; |
| 85 | for(i=0; i<nodes; i++) { |
| 86 | if(is_e0_later_in_bsp(i)) { |
| 87 | siblings = 1; |
| 88 | break; |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | #endif |
| 93 | |
Martin Roth | 4c3ab73 | 2013-07-08 16:23:54 -0600 | [diff] [blame] | 94 | //Construct apicid_base |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 95 | |
| 96 | if((!disable_siblings) && (siblings>0) ) { |
Martin Roth | 4c3ab73 | 2013-07-08 16:23:54 -0600 | [diff] [blame] | 97 | /* for 8 way dual core, we will used up apicid 16:16, actually 16 is not allowed by current kernel |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 98 | and the kernel will try to get one that is small than 16 to make io apic work. |
| 99 | I don't know when the kernel can support 256 apic id. (APIC_EXT_ID is enabled) */ |
| 100 | |
| 101 | //4:10 for two way 8:12 for four way 16:16 for eight way |
| 102 | //Use CONFIG_MAX_PHYSICAL_CPUS instead of nodes for better consistency? |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 103 | apicid_base = nb_cfg_54 ? (siblings+1) * nodes : 8 * siblings + nodes; |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 104 | |
| 105 | } |
| 106 | else { |
| 107 | apicid_base = nodes; |
| 108 | } |
| 109 | |
| 110 | if((apicid_base+ioapic_num-1)>0xf) { |
| 111 | // We need to enable APIC EXT ID |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 112 | printk(BIOS_INFO, "if the IO APIC device doesn't support 256 apic id, \n you need to set CONFIG_ENABLE_APIC_EXT_ID in romstage.c so you can spare 16 id for ioapic\n"); |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 113 | enable_apic_ext_id(nodes); |
| 114 | } |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 115 | |
arch import user (historical) | ef03afa | 2005-07-06 17:15:30 +0000 | [diff] [blame] | 116 | return apicid_base; |
| 117 | } |