iPXE
virt_offset.h File Reference

Virtual offset memory model. More...

#include <bits/virt_offset.h>

Go to the source code of this file.

Macros

#define UACCESS_PREFIX_offset   __offset_

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static __always_inline void * UACCESS_INLINE (offset, phys_to_virt)(unsigned long phys)
 Allow for architecture-specific overrides of virt_offset.
static __always_inline physaddr_t UACCESS_INLINE (offset, virt_to_phys)(volatile const void *virt)
 Convert virtual address to physical address.

Variables

const unsigned long virt_offset
 Virtual address offset.

Detailed Description

Virtual offset memory model.

No currently supported machine provides a full 64 bits of physical address space. When we have ownership of the page tables (or segmentation mechanism), we can therefore use the following model:

  • For 32-bit builds: set up a circular map so that all 32-bit virtual addresses are at a fixed offset from the 32-bit physical addresses.
  • For 64-bit builds: identity-map the required portion of the physical address space, place iPXE within the 32-bit physical address space, map iPXE using virtual addresses in the top part of the negative (kernel) address space, and optionally map the 32-bit physical address space with attributes suitable for coherent DMA accesses.

In both cases, we can define "virt_offset" as "the value to be added to an address within iPXE's own image in order to obtain its physical address". With this definition:

  • For 32-bit builds: conversion between physical and virtual addresses is a straightforward addition or subtraction of virt_offset, since the whole 32-bit address space is circular.
  • For 64-bit builds: conversion from any valid physical address is a no-op (since all physical addresses are identity-mapped), and conversion from a virtual address to a physical address requires an addition of virt_offset if and only if the virtual address lies in the high negative portion of the address space (i.e. has the MSB set, but has the MSB clear after adding virt_offset).

For x86_64-pcbios, we identity-map the low 4GB of address space since the only accesses required above 4GB are for MMIO (typically PCI devices with large memory BARs).

For riscv64-sbi, we identity-map as much of the physical address space as can be mapped by the paging model (Sv39, Sv48, or Sv57) and create a coherent DMA mapping of the low 4GB.

Definition in file virt_offset.h.

Macro Definition Documentation

◆ UACCESS_PREFIX_offset

#define UACCESS_PREFIX_offset   __offset_

Definition at line 55 of file virt_offset.h.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ UACCESS_INLINE() [1/2]

__always_inline void * UACCESS_INLINE ( offset ,
phys_to_virt  )
inlinestatic

Allow for architecture-specific overrides of virt_offset.

Convert physical address to virtual address

Parameters
physPhysical address
Return values
virtVirtual address

Definition at line 76 of file virt_offset.h.

76 {
77
78 /* In a 64-bit build, any valid physical address is directly
79 * usable as a virtual address, since physical addresses are
80 * identity-mapped.
81 */
82 if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
83 return ( ( void * ) phys );
84
85 /* In a 32-bit build: subtract virt_offset */
86 return ( ( void * ) ( phys - virt_offset ) );
87}
unsigned int uint32_t
Definition stdint.h:12
unsigned long physaddr_t
Definition stdint.h:20
static signed char phys[4]
Definition epic100.c:88
const unsigned long virt_offset
Virtual address offset.

References offset, phys, and virt_offset.

◆ UACCESS_INLINE() [2/2]

__always_inline physaddr_t UACCESS_INLINE ( offset ,
virt_to_phys  ) const volatile
inlinestatic

Convert virtual address to physical address.

Parameters
virtVirtual address
Return values
physPhysical address

Definition at line 96 of file virt_offset.h.

96 {
97 const physaddr_t msb = ( 1ULL << ( 8 * sizeof ( physaddr_t ) - 1 ) );
98 physaddr_t addr = ( ( physaddr_t ) virt );
99
100 /* In a 64-bit build, any valid virtual address with the MSB
101 * clear is directly usable as a physical address, since it
102 * must lie within the identity-mapped portion.
103 *
104 * This test will typically reduce to a single "branch if less
105 * than zero" instruction.
106 */
107 if ( ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) &&
108 ( ! ( addr & msb ) ) ) {
109 return addr;
110 }
111
112 /* In a 32-bit build or in a 64-bit build with a virtual
113 * address with the MSB set: add virt_offset
114 */
115 addr += virt_offset;
116
117 /* In a 64-bit build with an address that still has the MSB
118 * set after adding virt_offset: truncate the original virtual
119 * address to form a 32-bit physical address.
120 *
121 * This test will also typically reduce to a single "branch if
122 * less than zero" instruction.
123 */
124 if ( ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) &&
125 ( addr & msb ) ) {
126 return ( ( uint32_t ) ( physaddr_t ) virt );
127 }
128
129 return addr;
130}
uint32_t addr
Buffer address.
Definition dwmac.h:9

References addr, offset, and virt_offset.

Variable Documentation

◆ virt_offset

const unsigned long virt_offset
extern

Virtual address offset.

This is defined to be the value to be added to an address within iPXE's own image in order to obtain its physical address, as described above.

Referenced by UACCESS_INLINE(), and UACCESS_INLINE().