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