[uaccess] Generalise librm's virt_offset mechanism for RISC-V

The virtual offset memory model used for i386-pcbios and x86_64-pcbios
can be generalised to also cover riscv32-sbi and riscv64-sbi.  In both
architectures, the 32-bit builds will use a circular map of the 32-bit
address space, and the 64-bit builds will use an identity map for the
relevant portion of the physical address space, with iPXE itself
placed in the negative (kernel) address space.

Generalise and document the virt_offset mechanism, and set it as the
default for both PCBIOS and SBI platforms.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-05-07 23:02:40 +01:00
parent e8a6c26571
commit 0279015d09
12 changed files with 189 additions and 72 deletions

View File

@@ -41,6 +41,13 @@ prefix_virt:
.dword _prefix
.size prefix_virt, . - prefix_virt
/* Current virtual address offset */
.section ".data.virt_offset", "aw", @progbits
.globl virt_offset
virt_offset:
.space ( __riscv_xlen / 8 )
.size virt_offset, . - virt_offset
/*****************************************************************************
*
* Print message to debug console

View File

@@ -26,11 +26,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <errno.h>
#include <elf.h>
#include <librm.h>
#include <ipxe/image.h>
#include <ipxe/elf.h>
#include <ipxe/features.h>
#include <ipxe/init.h>
#include <ipxe/uaccess.h>
/**
* @file

View File

@@ -1,14 +0,0 @@
#ifndef _BITS_UACCESS_H
#define _BITS_UACCESS_H
/** @file
*
* x86-specific user access API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <librm.h>
#endif /* _BITS_UACCESS_H */

View File

@@ -64,12 +64,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#else /* ASSEMBLY */
#ifdef UACCESS_LIBRM
#define UACCESS_PREFIX_librm
#else
#define UACCESS_PREFIX_librm __librm_
#endif
/**
* Call C function from real-mode code
*
@@ -79,53 +73,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
"pushl $( " _S2 ( VIRTUAL ( function ) ) " )\n\t" \
"call virt_call\n\t"
/* Variables in librm.S */
extern const unsigned long virt_offset;
/**
* Convert physical address to user pointer
*
* @v phys Physical address
* @ret virt Virtual address
*/
static inline __always_inline void *
UACCESS_INLINE ( librm, phys_to_virt ) ( unsigned long phys ) {
/* In a 64-bit build, any valid physical address is directly
* usable as a virtual address, since the low 4GB is
* identity-mapped.
*/
if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
return ( ( void * ) phys );
/* In a 32-bit build, subtract virt_offset */
return ( ( void * ) ( phys - virt_offset ) );
}
/**
* Convert virtual address to physical address
*
* @v virt Virtual address
* @ret phys Physical address
*/
static inline __always_inline physaddr_t
UACCESS_INLINE ( librm, virt_to_phys ) ( volatile const void *virt ) {
physaddr_t addr = ( ( physaddr_t ) virt );
/* In a 64-bit build, any virtual address in the low 4GB is
* directly usable as a physical address, since the low 4GB is
* identity-mapped.
*/
if ( ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) &&
( addr <= 0xffffffffUL ) )
return addr;
/* In a 32-bit build or in a 64-bit build with a virtual
* address above 4GB: add virt_offset
*/
return ( addr + virt_offset );
}
/******************************************************************************
*
* Access to variables in .data16 and .text16

View File

@@ -4,6 +4,7 @@
#include <stdint.h>
#include <string.h>
#include <registers.h>
#include <librm.h>
#include <ipxe/uaccess.h>
/*

View File

@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
#include <registers.h>
#include <librm.h>
#include <ipxe/uaccess.h>
#include <ipxe/timer.h>
#include <ipxe/msr.h>

View File

@@ -429,8 +429,6 @@ void setup_sipi ( unsigned int vector, uint32_t handler,
copy_to_real ( ( vector << 8 ), 0, sipi, ( ( size_t ) sipi_len ) );
}
PROVIDE_UACCESS_INLINE ( librm, phys_to_virt );
PROVIDE_UACCESS_INLINE ( librm, virt_to_phys );
PROVIDE_IOMAP_INLINE ( pages, io_to_bus );
PROVIDE_IOMAP ( pages, ioremap, ioremap_pages );
PROVIDE_IOMAP ( pages, iounmap, iounmap_pages );