summaryrefslogtreecommitdiffstats
path: root/src/arch/riscv/include
diff options
context:
space:
mode:
authorMichael Brown2025-05-11 14:04:51 +0200
committerMichael Brown2025-05-11 14:46:21 +0200
commit95ede670bcfea5ea22965962fe764841243eb864 (patch)
treeb7a18723d1b1ad6cf034e2478632471d2a9bf258 /src/arch/riscv/include
parent[fdt] Generalise access to "reg" property (diff)
downloadipxe-95ede670bcfea5ea22965962fe764841243eb864.tar.gz
ipxe-95ede670bcfea5ea22965962fe764841243eb864.tar.xz
ipxe-95ede670bcfea5ea22965962fe764841243eb864.zip
[riscv] Hold virtual address offset in the thread pointer register
iPXE does not make use of any thread-local storage. Use the otherwise unused thread pointer register ("tp") to hold the current value of the virtual address offset, rather than using a global variable. This ensures that virt_offset can be made valid even during very early initialisation (when iPXE may be executing directly from read-only memory and so cannot update a global variable). Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch/riscv/include')
-rw-r--r--src/arch/riscv/include/bits/virt_offset.h33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/arch/riscv/include/bits/virt_offset.h b/src/arch/riscv/include/bits/virt_offset.h
new file mode 100644
index 000000000..83ac17551
--- /dev/null
+++ b/src/arch/riscv/include/bits/virt_offset.h
@@ -0,0 +1,33 @@
+#ifndef _BITS_VIRT_OFFSET_H
+#define _BITS_VIRT_OFFSET_H
+
+/** @file
+ *
+ * RISCV-specific virtual address offset
+ *
+ * We use the thread pointer register (tp) to hold the virtual address
+ * offset, so that virtual-to-physical address translations work as
+ * expected even while we are executing directly from read-only memory
+ * (and so cannot store a value in a global virt_offset variable).
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/**
+ * Read virtual address offset held in thread pointer register
+ *
+ * @ret virt_offset Virtual address offset
+ */
+static inline __attribute__ (( const, always_inline )) unsigned long
+tp_virt_offset ( void ) {
+ register unsigned long tp asm ( "tp" );
+
+ __asm__ ( "" : "=r" ( tp ) );
+ return tp;
+}
+
+/** Always read thread pointer register to get virtual address offset */
+#define virt_offset tp_virt_offset()
+
+#endif /* _BITS_VIRT_OFFSET_H */