1.. _x86_developer_guide:
2
3x86 Developer Guide
4###################
5
6Overview
7********
8
9This page contains information on certain aspects when developing for
10x86-based platforms.
11
12Virtual Memory
13**************
14
15During very early boot, page tables are loaded so technically the kernel
16is executing in virtual address space. By default, physical and virtual
17memory are identity mapped and thus giving the appearance of execution
18taking place in physical address space. The physical address space is
19marked by kconfig :kconfig:option:`CONFIG_SRAM_BASE_ADDRESS` and
20:kconfig:option:`CONFIG_SRAM_SIZE` while the virtual address space is marked by
21:kconfig:option:`CONFIG_KERNEL_VM_BASE` and :kconfig:option:`CONFIG_KERNEL_VM_SIZE`.
22Note that :kconfig:option:`CONFIG_SRAM_OFFSET` controls where the Zephyr kernel
23is being placed in the memory, and its counterpart
24:kconfig:option:`CONFIG_KERNEL_VM_OFFSET`.
25
26Separate Virtual Address Space from Physical Address Space
27==========================================================
28
29On 32-bit x86, it is possible to have separate physical and virtual
30address space. Code and data are linked in virtual address space,
31but are still loaded in physical memory. However, during boot, code
32and data must be available and also addressable in physical address
33space before ``vm_enter`` inside :file:`arch/x86/core/ia32/crt0.S`.
34After ``vm_enter``, code execution is done via virtual addresses
35and data can be referred via their virtual addresses. This is
36possible as the page table generation script
37(:file:`arch/x86/gen_mmu.py`) identity maps the physical addresses
38at the page directory level, in addition to mapping virtual addresses
39to the physical memory. Later in the boot process,
40the entries for identity mapping at the page directory level are
41cleared in :c:func:`z_x86_mmu_init()`, effectively removing
42the identity mapping of physical memory. This unmapping must be done
43for userspace isolation or else they would be able to access
44restricted memory via physical addresses. Since the identity mapping
45is done at the page directory level, there is no need to allocate
46additional space for the page table. However, additional space may
47still be required for additional page directory table.
48
49There are restrictions on where virtual address space can be:
50
51- Physical and virtual address spaces must be disjoint. This is
52  required as the entries in page directory table will be cleared.
53  If they are not disjoint, it would clear the entries needed for
54  virtual addresses.
55
56  - If :kconfig:option:`CONFIG_X86_PAE` is enabled (``=y``), each address space
57    must reside in their own 1GB region, due to each entry of PDP
58    (Page Directory Pointer) covers 1GB of memory. For example:
59
60    - Assuming ``CONFIG_SRAM_OFFSET`` and ``CONFIG_KERNEL_VM_OFFSET``
61      are both ``0x0``.
62
63    - ``CONFIG_SRAM_BASE_ADDRESS == 0x00000000`` and
64      ``CONFIG_KERNEL_VM_BASE = 0x40000000`` is valid, while
65
66    - ``CONFIG_SRAM_BASE_ADDRESS == 0x00000000`` and
67      ``CONFIG_KERNEL_VM_BASE = 0x20000000`` is not.
68
69  - If :kconfig:option:`CONFIG_X86_PAE` is disabled (``=n``), each address space
70    must reside in their own 4MB region, due to each entry of PD
71    (Page Directory) covers 4MB of memory.
72
73  - Both ``CONFIG_SRAM_BASE_ADDRESS`` and ``CONFIG_KERNEL_VM_BASE``
74    must also align with the starting addresses of targeted regions.
75
76Specifying Additional Memory Mappings at Build Time
77***************************************************
78
79The page table generation script (:file:`arch/x86/gen_mmu.py`) generates
80the necessary multi-level page tables for code execution and data access
81using the kernel image produced by the first linker pass. Additional
82command line arguments can be passed to the script to generate additional
83memory mappings. This is useful for static mappings and/or device MMIO
84access during very early boot. To pass extra command line arguments to
85the script, populate a CMake list named ``X86_EXTRA_GEN_MMU_ARGUMENTS``
86in the board configuration file. Here is an example:
87
88.. code-block:: cmake
89
90   set(X86_EXTRA_GEN_MMU_ARGUMENTS
91       --map 0xA0000000,0x2000
92       --map 0x80000000,0x400000,LWUX,0xB0000000)
93
94The argument ``--map`` takes the following value:
95``<physical address>,<size>[,<flags:LUWX>[,<virtual address>]]``, where:
96
97- ``<physical address>`` is the physical address of the mapping. (Required)
98
99- ``<size>`` is the size of the region to be mapped. (Required)
100
101- ``<flags>`` is the flag associated with the mapping: (Optional)
102
103  - ``L``: Large page at the page directory level.
104
105  - ``U``: Allow userspace access.
106
107  - ``W``: Read/write.
108
109  - ``X``: Allow execution.
110
111  - ``D``: Cache disabled.
112
113    - Default is small page (4KB), supervisor only, read only, and
114      execution disabled.
115
116- ``<virtual address`` is the virtual address of the mapping. (Optional)
117
118Note that specifying additional memory mappings requires larger storage
119space for the pre-allocated page tables (both kernel and per-domain
120tables). :kconfig:option:`CONFIG_X86_EXTRA_PAGE_TABLE_PAGES` is needed to
121specify how many more memory pages to be reserved for the page tables.
122If the needed space is not exactly the same as required space,
123the ``gen_mmu.py`` script will print out a message indicating what
124needs to be the value for the kconfig.
125