4 ms·
Out of curiosity: Can anyone point me where to find how a recent x86-cpu actually boots? Where's the code that gets executed in the first few CPU cycles? The b
by cnvogel 12y ago
Out of curiosity: Can anyone point me where to find how a recent x86-cpu actually boots? Where's the code that gets executed in the first few CPU cycles?
The bulk of the firmware, that's clear, nowadays will be fetched from a serially connected flash, which this initial code will copy to the (then initialized) DRAM, also probably in several stages. But where do the first few instructions hide? Mask-rom in the CPU, or the chipset?
I know how initial bootup works on my day-job-default-CPU (a m68k/coldfire that basically just starts executing from a parallel connected flash), on a few ARMs and some PPC, but I have no idea about a "typical" intel core/i5..7/... CPU.
- userbinator 12y agoThe first "code" would probably be microcode in the CPU itself, but if you mean x86 instructions, recent CPUs boot in the same way as the orginal 8086: the first instruction after a reset is fetched from FFFF:FFF0, or 16 bytes less than the end of memory, in realmode. The BIOS ROM is mapped into this area. There are some good articles here: https://sites.google.com/site/pinczakko/ https://sites.google.com/site/pinczakko/
- cnvogel 12y ago> the first instruction after a reset is fetched from FFFF:FFF0 I trust you that this logically will certainly be true, but: what memory will that access to ffff:fff0 be mapped to if the "bios" in my PC is stored in a SPI flash that certainly can't be connected directly to anything resembling a "address/data-bus" in a modern PC...
- makomk 12y agoIf I recall corretly, the access is mapped to the SPI flash chip which is memory-mapped into the CPU address space by the chipset. Access to this address range is of course relatively slow, but that's always been true of BIOS flash.
- userbinator 12y agoThere is circuitry that translates the requests from the CPU into read commands to the serial flash. Depending on the system, this can be in the LPC-connected SuperIO, the southbridge, or on laptops more likely part of the EC (embedded controller) which is also connected via LPC. This is also why executing from the BIOS is slow - SPI flash bandwidth is in the dozens of MB/s range, and if it's going over LPC the max bandwidth on that is <16MB/s. If you're really interested in this stuff the articles in the above link are a good read, as well as datasheets for the various chipsets involved. I'd recommend even looking at the original IBM PC/AT Technical Reference, with BIOS listings and full schematics.
- cnvogel 12y agoIndeed, fascinating! The CPU will have to wait thousands of waitstates for each bytes from the SPI-flash, but who cares in the first few ms of booting ;-). Thanks for pointing me in that direction! There's quite some information also in the "7-series chipset datasheets" (and 8-series) from Intel, it seems that they have a very elaborate SPI implementation, in the chipset, in hardware...
- tryp 12y agoThe best place to look is probably Coreboot. It's the boot firmware used by Google Chromebooks. (Github mirror links used here for politeness to the project's servers.) Taking Intel Haswell processors as an example (because I know this code path) we can sketch the general process. Start at 0xfffffff0, the boot vector for x86, executing in 16-bit "I can run DOS 1.0" mode. https://github.com/coreboot/coreboot/blob/master/src/cpu/x86/16bit/entry16.inc https://github.com/coreboot/coreboot/blob/master/src/cpu/x86... It just jumps to the entry to 32-bit mode https://github.com/coreboot/coreboot/blob/master/src/cpu/x86/32bit/entry32.inc https://github.com/coreboot/coreboot/blob/master/src/cpu/x86... Turn on FPU https://github.com/coreboot/coreboot/blob/master/src/cpu/x86/fpu_enable.inc https://github.com/coreboot/coreboot/blob/master/src/cpu/x86... Turn on SSE https://github.com/coreboot/coreboot/blob/master/src/cpu/x86/sse_enable.inc https://github.com/coreboot/coreboot/blob/master/src/cpu/x86... Configure the cache not to require a backing DRAM so that it can be used temporarily as RAM. https://github.com/coreboot/coreboot/blob/master/src/cpu/intel/haswell/cache_as_ram.inc https://github.com/coreboot/coreboot/blob/master/src/cpu/int... Now that "RAM" is available for use as a stack, the next steps can be written in plain-ole C https://github.com/coreboot/coreboot/blob/master/src/cpu/intel/haswell/romstage.c#L165 https://github.com/coreboot/coreboot/blob/master/src/cpu/int... From there, mainboard-specific code sets up things like which SuperIO chip to configure, the i2c addresses to interrogate for information on RAM geometry and timing, and how the chipset is wired to connectors on the board. Commong chipset (northbridge and southbridge) init code is run using that configuration data. https://github.com/coreboot/coreboot/blob/master/src/mainboard/google/peppy/romstage.c#L121 https://github.com/coreboot/coreboot/blob/master/src/mainboa... Then DRAM is initialized (the Haswell example is a bit lame in that currently a binary blob of compiled code from Intel does this job.) The Sandybridge DDR3 init was recently reverse-engineered and re-implemented and fully exemplifies the training processes required. https://github.com/coreboot/coreboot/blob/master/src/northbridge/intel/sandybridge/raminit_native.c https://github.com/coreboot/coreboot/blob/master/src/northbr... Now that Gigagbytes of RAM are available, another boot stage is fetched from flash. When generic framework gets back to cpu-specific stuff, power management is configured,Inter-Processor Interrupt handlers are installed, and other cores go through a quick init sequence. https://github.com/coreboot/coreboot/blob/master/src/cpu/intel/haswell/haswell_init.c#L738 https://github.com/coreboot/coreboot/blob/master/src/cpu/int... Then essentially the PCI tree is walked to setup all the chipset devices. https://github.com/coreboot/coreboot/tree/master/src/southbridge/intel/lynxpoint https://github.com/coreboot/coreboot/tree/master/src/southbr... Once hardware is running, Coreboot loads a "payload" that is in turn responsible for loading the OS.