summaryrefslogtreecommitdiffstats
path: root/qemu/roms/seabios/docs/Memory_Model.md
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/seabios/docs/Memory_Model.md')
-rw-r--r--qemu/roms/seabios/docs/Memory_Model.md253
1 files changed, 253 insertions, 0 deletions
diff --git a/qemu/roms/seabios/docs/Memory_Model.md b/qemu/roms/seabios/docs/Memory_Model.md
new file mode 100644
index 000000000..0668bd8f9
--- /dev/null
+++ b/qemu/roms/seabios/docs/Memory_Model.md
@@ -0,0 +1,253 @@
+The SeaBIOS code is required to support multiple x86 CPU memory
+models. This requirement impacts the code layout and internal storage
+of SeaBIOS.
+
+x86 Memory Models
+=================
+
+The x86 line of CPUs has evolved over many years. The original 8086
+chip used 16bit pointers and could only address 1 megabyte of memory.
+The 80286 CPU still used 16bit pointers, but could address up to 16
+megabytes of memory. The 80386 chips could process 32bit instructions
+and could access up to 4 gigabyte of memory. The most recent x86 chips
+can process 64bit instructions and access 16 exabytes of ram.
+
+During the evolution of the x86 CPUs from the 8086 to the 80386 the
+BIOS was extended to handle calls in the various modes that the CPU
+implemented.
+
+This section outlines the five different x86 CPU execution and memory
+access models that SeaBIOS supports.
+
+16bit real mode
+---------------
+
+This mode is a
+[segmented](http://en.wikipedia.org/wiki/Memory_segmentation) memory
+mode invoked by callers. The CPU defaults to executing 16bit
+instructions. Callers typically invoke the BIOS by issuing an "int x"
+instruction which causes a software
+[interrupt](http://en.wikipedia.org/wiki/Interrupt) that is handled by
+the BIOS. The SeaBIOS code also handles hardware interrupts in this
+mode. SeaBIOS can only access the first 1 megabyte of memory in this
+mode, but it can access any part of that first megabyte.
+
+16bit bigreal mode
+------------------
+
+This mode is a segmented memory mode that is used for [option
+roms](http://en.wikipedia.org/wiki/Option_ROM). The CPU defaults to
+executing 16bit instructions and segmented memory accesses are still
+used. However, the segment limits are increased so that the entire
+first 4 gigabytes of memory is fully accessible. Callers can invoke
+all the [16bit real mode](#16bit_real_mode) functions while in this
+mode and can also invoke the Post Memory Manager (PMM) functions that
+are available during option rom execution.
+
+16bit protected mode
+--------------------
+
+CPU execution in this mode is similar to [16bit real
+mode](#16bit_real_mode). The CPU defaults to executing 16bit
+instructions. However, each segment register indexes a "descriptor
+table", and it is difficult or impossible to know what the physical
+address of each segment is. Generally speaking, the BIOS can only
+access code and data in the f-segment. The PCIBIOS, APM BIOS, and PNP
+BIOS all have documented 16bit protected mode entry points.
+
+Some old code may attempt to invoke the standard [16bit real
+mode](#16bit_real_mode) entry points while in 16bit protected
+mode. The PCI BIOS specification explicitly requires that the legacy
+"int 1a" real mode entry point support 16bit protected mode calls if
+they are for the PCI BIOS. Callers of other legacy entry points in
+protected mode have not been observed and SeaBIOS does not support
+them.
+
+32bit segmented mode
+--------------------
+
+In this mode the processor runs in 32bit mode, but the segment
+registers may have a limit and may have a non-zero offset. In effect,
+this mode has all of the limitations of [16bit protected
+mode](#16bit_protected_mode) - the main difference between the modes
+is that the processor defaults to executing 32bit instructions. In
+addition to these limitations, callers may also run the SeaBIOS code
+at varying virtual addresses and so the code must support code
+relocation. The PCI BIOS specification and APM BIOS specification
+define 32bit segmented mode interfaces.
+
+32bit flat mode
+---------------
+
+In this mode the processor defaults to executing 32bit instructions,
+and all segment registers have an offset of zero and allow access to
+the entire first 4 gigabytes of memory. This is the only "sane" mode
+for 32bit code - modern compilers and modern operating systems will
+generally only support this mode (when running 32bit code).
+Ironically, it's the only mode that is not strictly required for a
+BIOS to support. SeaBIOS uses this mode internally to support the POST
+and BOOT [phases of execution](Execution and code flow).
+
+code16gcc
+=========
+
+In order to produce code that can run when the processor is in a 16bit
+mode, SeaBIOS uses the
+[binutils](http://en.wikipedia.org/wiki/GNU_Binutils) ".code16gcc"
+assembler flag. This instructs the assembler to emit extra prefix
+opcodes so that the 32bit code produced by
+[gcc](http://en.wikipedia.org/wiki/GNU_Compiler_Collection) will run
+even when the processor is in 16bit mode. Note that gcc always
+produces 32bit code - it does not know about the ".code16gcc" flag and
+does not know that the code will run in a 16bit mode.
+
+SeaBIOS uses the same code for all of the 16bit modes ([16bit real
+mode](#16bit_real_mode), [16bit bigreal mode](#16bit_bigreal_mode),
+and [16bit protected mode](#16bit_protected_mode)) and that code is
+assembled using ".code16gcc". SeaBIOS is careful to use segment
+registers properly so that the same code can run in the different
+16bit modes that it needs to support.
+
+C code mode flags
+=================
+
+Two compile time flags are available to determine the memory model the
+code is intended for: MODE16 and MODESEGMENT. When compiling for the
+16 bit modes, MODE16 is true and MODESEGMENT is true. In 32bit
+segmented mode, MODE16 is false and MODESEGMENT is true. In 32bit flat
+mode both MODE16 and MODESEGMENT are false.
+
+Common memory used at run-time
+==============================
+
+There are several memory areas that the SeaBIOS "runtime"
+[phase](Execution and code flow) makes use of:
+
+* 0x000000-0x000400: Interrupt descriptor table (IDT). This area
+ defines 256 interrupt vectors as defined by the Intel CPU
+ specification for 16bit irq handlers. This area is read/writable at
+ runtime and can be accessed from 16bit real mode and 16bit bigreal
+ mode calls. SeaBIOS only uses this area to maintain compatibility
+ with legacy systems.
+
+* 0x000400-0x000500: BIOS Data Area (BDA). This area contains various
+ legacy flags and attributes. The area is read/writable at runtime
+ and can be accessed from 16bit real mode and 16bit bigreal mode
+ calls. SeaBIOS only uses this area to maintain compatibility with
+ legacy systems.
+
+* 0x09FC00-0x0A0000 (typical): Extended BIOS Data Area (EBDA). This
+ area contains a few legacy flags and attributes. The area is
+ typically located at 0x9FC00, but it can be moved by option roms, by
+ legacy operating systems, and by SeaBIOS if
+ CONFIG_MALLOC_UPPERMEMORY is not set. Its actual location is
+ determined by a pointer in the BDA. The area is read/writable at
+ runtime and can be accessed from 16bit real mode and 16bit bigreal
+ mode calls. SeaBIOS only uses this area to maintain compatibility
+ with legacy systems.
+
+* 0x0E0000-0x0F0000 (typical): "low" memory. This area is used for
+ custom read/writable storage internal to SeaBIOS. The area is
+ read/writable at runtime and can be accessed from 16bit real mode
+ and 16bit bigreal mode calls. The area is typically located at the
+ end of the e-segment, but the build may position it anywhere in the
+ 0x0C0000-0x0F0000 region. However, if CONFIG_MALLOC_UPPERMEMORY is
+ not set, then this region is between 0x090000-0x0A0000. Space is
+ allocated in this region by either marking a global variable with
+ the "VARLOW" flag or by calling malloc_low() during
+ initialization. The area can be grown dynamically (via malloc_low),
+ but it will never exceed 64K.
+
+* 0x0F0000-0x100000: The BIOS segment. This area is used for both
+ runtime code and static variables. Space is allocated in this region
+ by either marking a global variable with VAR16, one of the VARFSEG
+ flags, or by calling malloc_fseg() during initialization. The area
+ is read-only at runtime and can be accessed from 16bit real mode,
+ 16bit bigreal mode, 16bit protected mode, and 32bit segmented mode
+ calls.
+
+All of the above areas are also read/writable during the SeaBIOS
+initialization phase and are accessible when in 32bit flat mode.
+
+Segmented mode memory access
+============================
+
+The assembler entry functions for segmented mode calls (all modes
+except [32bit flat mode](#32bit_flat_mode)) will arrange
+to set the data segment (%ds) to be the same as the stack segment
+(%ss) before calling any C code. This permits all C variables located
+on the stack and C pointers to data located on the stack to work as
+normal.
+
+However, all code running in segmented mode must wrap non-stack memory
+accesses in special macros. These macros ensure the correct segment
+register is used. Failure to use the correct macro will result in an
+incorrect memory access that will likely cause hard to find errors.
+
+There are three low-level memory access macros:
+
+* GET_VAR / SET_VAR : Accesses a variable using the specified segment
+ register. This isn't typically used directly by C code.
+
+* GET_FARVAR / SET_FARVAR : Assigns the extra segment (%es) to the
+ given segment id and then performs the given memory access via %es.
+
+* GET_FLATVAR / SET_FLATVAR : These macros take a 32bit pointer,
+ construct a segment/offset pair valid in real mode, and then perform
+ the given access. These macros must not be used in 16bit protected
+ mode or 32bit segmented mode.
+
+Since most memory accesses are to [common memory used at
+run-time](#Common_memory_used_at_run-time), several helper
+macros are also available.
+
+* GET_IDT / SET_IDT : Access the interrupt descriptor table (IDT).
+
+* GET_BDA / SET_BDA : Access the BIOS Data Area (BDA).
+
+* GET_EBDA / SET_EBDA : Access the Extended BIOS Data Area (EBDA).
+
+* GET_LOW / SET_LOW : Access internal variables marked with
+ VARLOW. (There are also related macros GET_LOWFLAT / SET_LOWFLAT for
+ accessing storage allocated with malloc_low).
+
+* GET_GLOBAL : Access internal variables marked with the VAR16 or
+ VARFSEG flags. (There is also the related macro GET_GLOBALFLAT for
+ accessing storage allocated with malloc_fseg).
+
+Memory available during initialization
+======================================
+
+During the POST [phase](Execution and code flow) the code
+can fully access the first 4 gigabytes of memory. However, memory
+accesses are generally limited to the [common memory used at
+run-time](#Common_memory_used_at_run-time) and areas
+allocated at runtime via one of the malloc calls:
+
+* malloc_high : Permanent high-memory zone. This area is used for
+ custom read/writable storage internal to SeaBIOS. The area is
+ located at the top of the first 4 gigabytes of ram. It is commonly
+ used for storing standard tables accessed by the operating system at
+ runtime (ACPI, SMBIOS, and MPTable) and for DMA buffers used by
+ hardware drivers. The area is read/writable at runtime and an entry
+ in the e820 memory map is used to reserve it. When running on an
+ emulator that has only 1 megabyte of ram this zone will be empty.
+
+* malloc_tmphigh : Temporary high-memory zone. This area is used for
+ custom read/writable storage during the SeaBIOS initialization
+ phase. The area generally starts after the first 1 megabyte of ram
+ (0x100000) and ends prior to the Permanent high-memory zone. When
+ running on an emulator that has only 1 megabyte of ram this zone
+ will be empty. The area is not reserved from the operating system,
+ so it must not be accessed after the SeaBIOS initialization phase.
+
+* malloc_tmplow : Temporary low-memory zone. This area is used for
+ custom read/writable storage during the SeaBIOS initialization
+ phase. The area resides between 0x07000-0x90000. The area is not
+ reserved from the operating system and by specification it is
+ required to be zero'd at the end of the initialization phase.
+
+The "tmplow" and "tmphigh" regions are only available during the
+initialization phase. Any access (either read or write) after
+completion of the initialization phase can result in difficult to find
+errors.