As is known, the use of virtual machines, whose work is based on the software interpretation of the code, allows you to create universal applications that run on various hardware platforms without recompilation.
The EFI Byte Code technology is a typical example of the successful application of this approach. But with all its advantages, there is an obvious drawback - a software-implemented processor is significantly slower than a hardware one. The proposed article discusses a method to level the performance drop of EBC programs by the example of operations of filling a block of memory with a constant and copying the contents of a block of memory. Moreover, the use of “inserts” of the native code of the central processor is not discussed, since it discredits the very idea of
cross-platform .
Formulation of the problem
So, let's imagine that our application needs to fill in a given constant, specified memory areas, and also copy blocks. Moreover, the arrays are large enough and the performance of this operation is critical for the performance of the application as a whole. Using EBC instructions for processing blocks will result in a loss of performance, and the insertion of native code means a loss of cross-platform. How to be?
Solution exists
The developers of the UEFI specification have provided an elegant solution for this type of problem. In the set of EFI Boot Services service functions, procedures are provided for filling the memory block with the
SetMem () constant and copying the
CopyMem () memory block. Recall UEFI API service procedures are divided into
EFI Boot Services and
EFI Runtime Services . The first ones are available only during the OS boot phase, the second ones - during the whole operating time of the OS.
')
Figure 1 .
A description of the parameters of the SetMem () function in the UEFI document Specification version 2.4 Errata A.Buffer - base address of the block;
Size - block size;
Value - data to fill the block.
The function fills the memory block whose value is equal to the value of Buffer, the size in bytes is equal to the Size value of the byte constant Value.
Figure 2 .
Description of the parameters of the CopyMem () function in the UEFI document Specification version 2.4 Errata ADestination - the base address of the receiving unit;
Source - the base address of the source block;
Length - the length of the transfer operation, in bytes.
The function copies the source block with the size of Length, located at the Source address, to the recipient block located at the Destination address.
Example of filling a block with a constant
Figure 3 shows the listing of an EBC program that fills a block with a constant 11h, 32 bytes in size. Consider its implementation. The base address of the block is written to the R7 register, R6 is the block length, R5 is the data to be written. After this, a stack frame is created that is used to transfer the parameters of the called subroutine. Then, from the
EFI System Table, the address of the child table of the
EFI Boot Services Table is read, in which, in turn, at number 42 is the pointer to call the
SetMem () function. For the gateway between the EBC program and the UEFI firmware called procedure, the instruction CALL32EXA is used. After the subroutine has completed, the stack frame is eliminated.
In this and the following examples,
_Primary_Memory_Base and
_EFI_Table are offsets used to address variables that store, respectively, the base address of the memory block used by the program and the base address of the root EFI System Table system table transmitted to the application at startup.
Let us recall one feature of the construction of the UEFI system tables, which is essential for ensuring cross-platform. 32-bit UEFI implementations use pointers of 4 bytes, 64 bit ones of 8 bytes. The table header field is always 24 bytes in size. Therefore, the instructions addressing the UEFI system tables operate on two items when calculating the address: pointer number (entry) and header size. This allows the EBC virtual machine to correctly calculate the address of the desired element, regardless of the processor’s native bitness, which determines the size of the elements.
Figure 3 .
An example of the procedure for filling a block with a constant using the SetMem () function. EBC assembly instructions are used.
Figure 4 .
The result of the procedure of filling the block with a constant using the SetMem () function. Used to view the Intel EBC Debugger. In this example, the base address of the rendered block is 6C40000h, length 80h = 128 bytes. Constant 11h is filled with a block of 32 bytesBlock copy example
Figure 5 shows the listing of an EBC program that copies a block of 32 bytes in size. Consider its implementation. The base address of the source block is written to the R7 register, R6 is the base address of the receiving block, R5 is the length of the blocks. After this, a stack frame is created that is used to transfer the parameters of the called subroutine. Then, from the EFI System Table, the address of the child table of the EFI Boot Services Table is read, in which, in turn, at number 41 is the pointer to call the CopyMem () function. For the gateway between the EBC program and the UEFI firmware called procedure, the instruction CALL32EXA is used. After the subroutine has completed, the stack frame is eliminated.
Figure 5 .
An example of a block copying procedure using the CopyMem () function. EBC assembly instructions are used.
Figure 6 .
The result of the block copying procedure using the CopyMem () function. Used to view the Intel EBC Debugger. In this example, the base address of the rendered block is 6C40000h, length 80h = 128 bytes. The source block located at addresses 6C40000h-6C4001Fh, copied to the recipient block at addresses 6C40030h-6C4004FhSummary
The implementation of the UEFI firmware, the functions associated with the primitive processing of large arrays, theoretically, allows you to optimize the performance of these operations for the particular platform. Significant performance improvements can be achieved using 128 or 256-bit SSE instructions of the x86 central processor, using various DMA co-processors, as well as hardware implementation using memory controller means. How effective platform developers will use this potential is our further research, but even when using UEFI firmware procedures of classic 32-bit x86 instructions, an EBC application, without losing cross-platform functionality and running on a
software processor, gets the performance of a
hardware processor at its disposal.