coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright (C) 2005 Advanced Micro Devices, Inc.
   5 * Copyright (C) 2007 Stefan Reinauer
   6 * Copyright (C) 2008 Ronald G. Minnich <rminnich@gmail.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  21 */
  22#include <mainboard.h>
  23#include <types.h>
  24#include <lib.h>
  25#include <console.h>
  26#include <cpu.h>
  27#include <globalvars.h>
  28#include <device/device.h>
  29#include <device/pci.h>
  30#include <string.h>
  31#include <msr.h>
  32#include <io.h>
  33#include <amd/k8/k8.h>
  34#include <mc146818rtc.h>
  35#include <spd.h>
  36#include <lapic.h>
  37
  38/* See page 330 of Publication # 26094       Revision: 3.30 Issue Date: February 2006
  39 * for APIC id discussion
  40 */
  41/**
  42 * for_each_ap
  43 * iterate over all APs and have them run a function.
  44 * The behaviour is modified by the core_range parameter
  45 * @param bsp_apicid The BSP APIC ID number
  46 * @param core_range modifier for the range of cores to run on:
  47 * core_range = 0 : all cores
  48 * core range = 1 : core 0 only
  49 * core range = 2 : cores other than core0
  50 * @param process_ap pointer to the function to run
  51 * @param gp general purpose argument to be passed as a parameter to the function
  52 */
  53void for_each_ap(unsigned bsp_apicid, unsigned core_range,
  54                        process_ap_t process_ap, void *gp)
  55{
  56        /* Assume the OS will not change our APIC ID. Why does this matter? Because some of the setup
  57         * we do for other cores may depend on it not being changed.
  58         */
  59        unsigned int ap_apicid;
  60
  61        unsigned int nodes;
  62        unsigned int siblings = 0;
  63        unsigned int disable_siblings = 1;
  64        unsigned int e0_later_single_core;
  65        unsigned int nb_cfg_54;
  66        int i, j;
  67
  68        /* The get_nodes function is defined in northbridge/amd/k8/coherent_ht.c */
  69        nodes = get_nodes();
  70
  71        /* if the get_option fails siblings remain disabled. */
  72        // This sound not be a config option.   disable_siblings = !CONFIG_LOGICAL_CPUS;
  73        //get_option(&disable_siblings, "dual_core");
  74
  75        /* There is an interesting problem in different steppings. See page 373. The interpretation of the
  76         * APIC ID bits is different. To determine which order is used, check bit 54 of the programmers' guide
  77         * here we assume that all nodes are the same stepping.
  78         * If not, "otherwise we can use use nb_cfg_54 from bsp for all nodes"
  79         */
  80        nb_cfg_54 = read_nb_cfg_54();
  81
  82        printk(BIOS_SPEW, "for_each_ap: nodes is %d\n", nodes);
  83        for (i = 0; i < nodes; i++) {
  84                e0_later_single_core = 0;
  85                /* Page 166. This field indicates the number of cores, with 0 meaning 1, 1 meaning 2, and all else reserved */
  86                j = ((pci_conf1_read_config32
  87                      (PCI_BDF(0, 0x18 + i, 3),
  88                       NORTHBRIDGE_CAP) >> NBCAP_CmpCap_SHIFT) &
  89                     NBCAP_CmpCap_MASK);
  90                if (nb_cfg_54) {
  91                        if (j == 0)     // if it is single core, we need to increase siblings for apic calculation
  92                                j = 1;
  93                }
  94                siblings = j;
  95
  96                printk(BIOS_SPEW, "Node %d: siblings is %d\n", i, siblings);
  97                unsigned jstart, jend;
  98
  99                if (core_range == 2) {
 100                        jstart = 1;
 101                } else {
 102                        jstart = 0;
 103                }
 104
 105                if (disable_siblings || (core_range == 1)) {
 106                        jend = 0;
 107                } else {
 108                        jend = siblings;
 109                }
 110
 111
 112                for (j = jstart; j <= jend; j++) {
 113                        printk(BIOS_SPEW, "Node %d: Start %d\n", i, j);
 114                        ap_apicid =
 115                            i * (nb_cfg_54 ? (siblings + 1) : 1) +
 116                            j * (nb_cfg_54 ? 1 : 8);
 117
 118#if (ENABLE_APIC_EXT_ID == 1)
 119#if LIFT_BSP_APIC_ID == 0
 120                        if ((i != 0) || (j != 0))       /* except bsp */
 121#endif
 122                                ap_apicid += APIC_ID_OFFSET;
 123#endif
 124
 125                        if (ap_apicid == bsp_apicid)
 126                                continue;
 127
 128                        process_ap(ap_apicid, gp);
 129
 130                }
 131        }
 132}
 133
 134/**
 135 * lapic remote read
 136 * lapics are more than just an interrupt steering system. They are a key part of inter-processor communication.
 137 * They can be used to start, control, and interrupt other CPUs from the BSP. It is not possible to bring up
 138 * an SMP system without somehow using the APIC.
 139 * CPUs and their attached IOAPICs all have an ID. For convenience, these IDs are unique.
 140 * The communications is packet-based, using (in coreboot) a polling-based strategy. As with most APIC ops,
 141 * the ID is the APIC ID. Even more fun, code can read registers in remote APICs, and this in turn can
 142 * provide us with remote CPU status.
 143 * This function does a remote read given an apic id. It returns the value or an error. It can time out.
 144 * @param apicid Remote APIC id
 145 * @param reg The register number to read
 146 * @param pvalue pointer to int for return value
 147 * @returns 0 on success, -1 on error
 148 */
 149int lapic_remote_read(int apicid, int reg, unsigned int *pvalue)
 150{
 151        int timeout;
 152        unsigned status;
 153        int result;
 154        /* Wait for the idle state. Could we enter this with the APIC busy? It's possible. */
 155        lapic_wait_icr_idle();
 156        /* The APIC Interrupt Control Registers define the operations and destinations.
 157         * In this case, we set ICR2 to the dest, set the op to REMOTE READ, and set the
 158         * reg (which is 16-bit aligned, it seems, hence the >> 4
 159         */
 160        lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
 161        lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
 162
 163        /* it's started. now we wait. */
 164        timeout = 0;
 165
 166        do {
 167                /* note here the ICR is command and status. */
 168                /* Why don't we use the lapic_wait_icr_idle() above? */
 169                /* That said, it's a bad idea to mess with this code too much.
 170                 * APICs (and their code) are quite fragile.
 171                 */
 172                status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
 173        } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
 174
 175        /* interesting but the timeout is not checked, hence no error on the send! */
 176
 177        timeout = 0;
 178        do {
 179                status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
 180        } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
 181
 182        result = -1;
 183        if (status == LAPIC_ICR_RR_VALID) {
 184                *pvalue = lapic_read(LAPIC_RRR);
 185                result = 0;
 186        }
 187        return result;
 188}
 189
 190#define LAPIC_MSG_REG 0x380
 191
 192void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid);
 193
 194void print_apicid_nodeid_coreid(unsigned apicid, struct node_core_id id,
 195                                const char *str)
 196{
 197        printk(BIOS_DEBUG, "%s --- {  APICID = %02x NODEID = %02x COREID = %02x} ---\n",
 198                str, apicid, id.nodeid, id.coreid);
 199}
 200
 201
 202/**
 203 * Using the APIC remote read code, wait for the CPU to enter a given state
 204 * This function can time out.
 205 * @param apicid The apicid of the remote CPU
 206 * @param state The state we are waiting for
 207 * @return 0 on success, readback value on error
 208 */
 209unsigned int wait_cpu_state(unsigned apicid, unsigned state)
 210{
 211        unsigned readback = 0;
 212        unsigned timeout = 1;
 213        int loop = 2000000;
 214        while (--loop > 0) {
 215                if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) !=
 216                    0)
 217                        continue;
 218                if ((readback & 0xff) == state) {
 219                        timeout = 0;
 220                        break;  //target cpu is in stage started
 221                }
 222        }
 223        if (timeout) {
 224                if (readback) {
 225                        timeout = readback;
 226                }
 227        }
 228
 229        return timeout;
 230}
 231
 232/**
 233 * Wait for an AP to start.
 234 * @param ap_apicid the apic id of the CPu
 235 * @param gp arbitrary parameter
 236 */
 237void wait_ap_started(unsigned ap_apicid, void *gp)
 238{
 239        unsigned timeout;
 240        timeout = wait_cpu_state(ap_apicid, 0x33);      // started
 241        if (timeout) {
 242                printk(BIOS_DEBUG, "%s%02x", "*",  ap_apicid);
 243                printk(BIOS_DEBUG, "%s%08x\n", "*",  timeout);
 244        } else {
 245                printk(BIOS_DEBUG, "%s%02x", " ",  ap_apicid);
 246        }
 247}
 248
 249
 250/**
 251 * wait for all apics to start. Make sure we don't wait on ourself.
 252 * @param bsp_apicid The BSP APIC ID
 253 */
 254void wait_all_aps_started(unsigned bsp_apicid)
 255{
 256        for_each_ap(bsp_apicid, 0, wait_ap_started, (void *) 0);
 257}
 258
 259/**
 260 * Wait on all other cores to start. This includes  cores on bsp, we think.
 261 * @param bsp_apicid The BSP APIC ID
 262 */
 263void wait_all_other_cores_started(unsigned bsp_apicid)  // all aps other than core0
 264{
 265        printk(BIOS_DEBUG, "started ap apicid: ");
 266        for_each_ap(bsp_apicid, 2, wait_ap_started, (void *) 0);
 267        printk(BIOS_DEBUG, "\n");
 268}
 269
 270void STOP_CAR_AND_CPU(void)
 271{
 272        disable_cache_as_ram(); // inline
 273        stop_this_cpu();        // inline
 274}
 275
 276#ifndef MEM_TRAIN_SEQ
 277#define MEM_TRAIN_SEQ 0
 278#endif
 279
 280
 281#if MEM_TRAIN_SEQ == 1
 282void train_ram_on_node(unsigned nodeid, unsigned coreid,
 283                        struct sys_info *sysinfo,
 284                        void * retcall);
 285#endif
 286
 287/**
 288 * Init all the CPUs. Part of the process involves setting APIC IDs for all cores on all sockets.
 289 * The code that is run
 290 * is for the most part the same on all cpus and cores of cpus.
 291 * Since we only support F2 and later Opteron CPUs our job is considerably simplified
 292 * as compared to v2. The basic process it to set up the cpu 0 core 0, then the other cpus, one by one.
 293 * Complications: BSP, a.k.a. cpu 0, comes up with APIC id 0, the others all come up with APIC id 7,
 294 * including other cpu 0 cores. Why? Because the BSP brings them up one by one and assigns their APIC ID.
 295 * There is also the question of the need to "lift" the BSP APIC id.
 296 * For some setups, we want the BSP APIC id to be 0; for others,
 297 * a non-zero value is preferred. This means that we have to change the BSP APIC ID on the fly.
 298 *
 299 * So here we have it, some of the slickest code you'll ever read. Which cores run this function?
 300 * All of them.
 301 * Do they communicate through APIC Interrupts or memory? Yes. Both. APICs before
 302 * memory is ready, memory afterword. What is the state of the cores at the end of this function?
 303 * They are all ready to go, just waiting to be started up. What is the state of memory on all sockets?
 304 * It's all working.
 305 * Except that it's not quite that simple. We'll try to comment this well enough to make sense.
 306 * But rest assured, it's complicated!
 307 * @param cpu_init_detectedx has this cpu been init'ed before?
 308 * @param sysinfo The sys_info pointer
 309 * @returns the BSP APIC ID
 310 */
 311unsigned int init_cpus(unsigned cpu_init_detectedx,
 312                        struct sys_info *sysinfo)
 313{
 314        unsigned bsp_apicid = 0;
 315        unsigned apicid;
 316        struct node_core_id id;
 317        /* this is a bit weird but soft_reset can be defined in many places,
 318         * so finding a common
 319         * include file to use is a little daunting.
 320         */
 321        void soft_reset(void);
 322
 323#warning ignore init_detectedx
 324cpu_init_detectedx = 0;
 325        /*
 326         * MTRR must be set by this point.
 327         */
 328
 329        /* that is from initial apicid, we need nodeid and coreid later */
 330        /* this comment still confuses me, but I *think* "that" means the "bsp_apicid". Not sure. */
 331        id = get_node_core_id();
 332        printk(BIOS_DEBUG, "init_cpus: node %d core %d\n", id.nodeid, id.coreid);
 333
 334        /* The NB_CFG MSR is shared between cores on a given node.
 335         * Here is an interesting parallel processing bug: if you were to start the
 336         * other cores and THEN make this setting, different cores might read
 337         * a different value! Since ALL cores run this code, it is very important to have
 338         * core0 initialize this setting before any others.
 339         * So do this setting very early in the function to make sure the bit has a
 340         * consistent value on all cores.
 341         */
 342        if (id.coreid == 0) {
 343                set_apicid_cpuid_lo();  /* only set it on core0 */
 344                /* Should we enable extended APIC IDs? This feature is used on a number of mainboards.
 345                 * It is required when the board requires more than 4 bits of ID.
 346                 * the question is, why not use it on all of them? Would it do harm to always enable it?
 347                 */
 348#if ENABLE_APIC_EXT_ID == 1
 349                enable_apic_ext_id(id.nodeid);
 350#endif
 351        }
 352
 353        /* enable the local APIC, which we need to do message passing between sockets. */
 354        enable_lapic();
 355//      init_timer(); // We need TMICT to pass msg for FID/VID change
 356
 357#if (ENABLE_APIC_EXT_ID == 1)
 358        /* we wish to enable extended APIC IDs. We have an APIC ID already which we can
 359         * use as a "base" for the extended ID.
 360         */
 361        unsigned initial_apicid = get_initial_apicid();
 362        /* We don't always need to lift the BSP APIC ID.
 363         * Again, is there harm if we do it anyway?
 364         */
 365#if LIFT_BSP_APIC_ID == 0
 366        if (initial_apicid != 0)        // This CPU is not the BSP so lift it.
 367#endif
 368        {
 369                /* Use the CPUs initial 4-bit APIC id as the basis for the extended ID */
 370                u32 dword = lapic_read(LAPIC_ID);
 371                dword &= ~(0xff << 24);
 372                dword |=
 373                    (((initial_apicid + APIC_ID_OFFSET) & 0xff) << 24);
 374
 375                lapic_write(LAPIC_ID, dword);
 376        }
 377        /* Again, the bsp_apicid is a special case and if we changed it
 378         * we need to remember that change.
 379         */
 380#if LIFT_BSP_APIC_ID == 1
 381        bsp_apicid += APIC_ID_OFFSET;
 382#endif
 383
 384#endif
 385
 386        apicid = lapicid();
 387
 388#if 1
 389        // show our apicid, nodeid, and coreid
 390        if (id.coreid == 0) {
 391                if (id.nodeid != 0)     //all core0 except bsp
 392                        print_apicid_nodeid_coreid(apicid, id, " core0: ");
 393        }
 394#if 1
 395        else {                  //all core non-zero
 396                print_apicid_nodeid_coreid(apicid, id, " core1: ");
 397        }
 398#endif
 399
 400#endif
 401
 402        if (cpu_init_detectedx) {
 403                print_apicid_nodeid_coreid(apicid, id,
 404                                           "\n\n\nINIT detected from ");
 405                printk(BIOS_DEBUG, "\nIssuing SOFT_RESET...\n");
 406                soft_reset();
 407        }
 408
 409        if (id.coreid == 0) {
 410                /* not known what this is yet. */
 411                distinguish_cpu_resets(id.nodeid);
 412//              start_other_core(id.nodeid); // start second core in first cpu, only allowed for nb_cfg_54 is not set
 413        }
 414        //Indicate to other CPUs that our CPU is running.
 415        /* and, again, recall that this is running on all sockets at some point, although it runs at
 416         * different times.
 417         */
 418        lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x33);
 419
 420        /* non-BSP CPUs are now set up and need to halt. There are a few possibilities here.
 421         * BSP may train memory
 422         * AP may train memory
 423         * In v2, both are possible.
 424         */
 425        if (apicid != bsp_apicid) {
 426                unsigned timeout = 1;
 427                unsigned loop = 100;
 428#if K8_SET_FIDVID == 1
 429#if (CONFIG_LOGICAL_CPUS == 1) && (K8_SET_FIDVID_CORE0_ONLY == 1)
 430                if (id.coreid == 0)     // only need set fid for core0
 431#endif
 432                        init_fidvid_ap(bsp_apicid, apicid);
 433#endif
 434
 435                // We need to stop the CACHE as RAM for this CPU, really?
 436                /* Yes we do. What happens here is really interesting. To this point
 437                 * we have used APICs to communicate. We're going to use the sysinfo
 438                 * struct. But to do that we have to use real memory. So we have to
 439                 * disable car, and do it in a way that lets us continue in this function.
 440                 * The way we do it for non-node 0 is to never return from this function,
 441                 * but to do the work in this function to train RAM.
 442                 * Note that serengeti, the SimNow target, does not do this; it lets BSP train AP memory.
 443                 */
 444                /* Wait for the bsp to enter state 44. */
 445                while (timeout && (loop-- > 0)) {
 446                        timeout = wait_cpu_state(bsp_apicid, 0x44);
 447                }
 448                if (timeout) {
 449                        printk(BIOS_DEBUG, "while waiting for BSP signal to STOP, timeout in ap 0x%08x\n",
 450                                apicid);
 451                }
 452
 453                /* indicate that we are in state 44 as well. We are catching up to the BSP. */
 454                lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x44);
 455
 456                /* Now set up so we can use RAM.
 457                 * This will be low memory, i.e. BSP memory, already working.
 458                 */
 459                /* Keep the ap's tom consistent with bsp's */
 460                set_top_mem_ap(sysinfo->tom_k, sysinfo->tom2_k);
 461                set_mtrr_ram_access();
 462
 463                /* This is not done on Serengeti. */
 464#if MEM_TRAIN_SEQ == 1
 465                train_ram_on_node(id.nodeid, id.coreid, sysinfo,
 466                                  (void *)STOP_CAR_AND_CPU);
 467#endif
 468                /* this is inline and there is no return. */
 469                STOP_CAR_AND_CPU();
 470        }
 471
 472        return bsp_apicid;
 473}
 474
 475
 476/**
 477 * Given a node, find out if core0 is started.
 478 * @param nodeid the node ID
 479 * @returns non-zero if node is started
 480 */
 481static unsigned int is_core0_started(unsigned nodeid)
 482{
 483        u32 htic;
 484        u32 device;
 485        device = PCI_BDF(0, 0x18 + nodeid, 0);
 486        htic = pci_conf1_read_config32(device, HT_INIT_CONTROL);
 487        htic &= HTIC_INIT_Detect;
 488        return htic;
 489}
 490
 491/**
 492 * Wait for all core 0s on all CPUs to start up.
 493 */
 494void wait_all_core0_started(void)
 495{
 496        //When core0 is started, it will distingush_cpu_resets. So wait for that
 497        // whatever that comment means?
 498        unsigned i;
 499        unsigned nodes = get_nodes();
 500
 501        printk(BIOS_DEBUG, "core0 started: ");
 502        /* The BSP is node 0 by definition. If we're here, we are running.
 503         * Start the loop at 1
 504         */
 505        for (i = 1; i < nodes; i++) {
 506                while (!is_core0_started(i)) {
 507                }
 508                printk(BIOS_DEBUG, "%s%02x", " ",  i);
 509        }
 510        printk(BIOS_DEBUG, "\n");
 511
 512}
 513
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.