Files
Sam Demeulemeester 7fc312d5b0 Add support for aarch64 (ARM64) architecture (#626)
* Initial commit for ARM64 (header.S & startup.S)

* Add Aarch64 interrupt handler

* Adapt lib/ to Aarch64

* Small ASM addition for AArch64

* Rewrite Aarch64 system/
- cpuid.c/cpuinfo.c for CPU detection (Qualcomm, Apple, Nvidia, etc)
- Add ARM Power State Coordination Interface (PSCI) functions
- vmem.c for Virtual Memory MAnagement on ARM64
- Various functions placeholders

* Add pseudo-TSC correction for Aarch64

* Add pseudo-tsc measurement for Aarch64

* Add Aarch64 if/elif on basic IO/MMIO/MEM RW functions

* Add support for Surface 13 / Snapdragon X KB USB
Fix an issue with the XHCI.c drivers with packets > 8 bytes

* Add MMIO Serial support for ARM64

* Add ARM64 ASM for block_move & mov_inv_fixed. Fix VM start pointer

* Add ARM Serial MMIO configuration

* Revert previous commit & reintroduce ARM64 cache functions

* Add ACPI MCFG Table description & SMP parsing. This requires careful review/testing to avoid BC issues!

* Revert previous commmit and reintroduce relocation and heap change for ARM64

* ARM64 does not support CPU PNS. Use DMI type4 parsing instead. Add SMBIOS v3 support (ARM64 does not support v2)

* Fix typo in pci.h

* Move Aarch64 load-limit computation from main.c to pmem.c

* Add .arm64 to version string. Use PMU for clock computation display. Fix D5 Temp NULL not handled

* Add Makefile and linker scripts for aarch64. Set cross-compiler from x86 by default

* Attempt to add aarch64 to workflow

* Remove a remaining internal debug flag

* Correct typos

* Fix ARM64 SMP freeze
assign heap when RAM is one contiguous region, keep it below 3GB for DMA (RPi5), add DSB before SEV to avoid missed barrier wakeups
Sync I-cache with D-cache after program relocation to prevent stale instruction fetch

* Validate MADT entry lengths to avoid reading past the table (or looping forever) on malformed ACPI tables

* aarch64: add NEON kernels for the vector PRSG tests
Tests 3 (bus stress) and 5 (moving inversions, random) now dispatch to 128-bit NEON fill/scan instead of scalar.

* Fix ARM64 data abort from the per-second DMI check & fix unbounded strstr()

* Fix ARM64 data abort when saving results to USB after a relocation

* Update README.md with AArch64 (ARM64) support

* aarch64: shrink static string tables, harden MCFG/paging
 Replace pointer-based name tables with inline char arrays (saves ~1.5KB + relocs)
alidate MCFG length/bus ranges, and bound pm_map/vm_map fills against overflows

* Add NVIDIA & latest Apple ARM SoC to cpuid.c

* Fix stale pointers read by the report writer after a program relocation
cpu_model gets a static init (creates its reloc record)SPD type becomes an inline char array
2026-07-12 13:27:45 +02:00

170 lines
5.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
#ifndef MEMRW_H
#define MEMRW_H
/**
* \file
*
* Provides some 8/16/32/64-bit memory access functions. These stop the compiler
* optimizing accesses which need to be ordered and atomic. Mostly used
* for accessing memory-mapped hardware registers.
*
*//*
* Copyright (C) 2021-2022 Martin Whitaker.
* Copyright (C) 2024 Lionel Debroux.
*/
#include <stdint.h>
#if defined(__i386__) || defined(__x86_64__)
#define __MEMRW_SUFFIX_8BIT "b"
#define __MEMRW_SUFFIX_16BIT "w"
#define __MEMRW_SUFFIX_32BIT "l"
#define __MEMRW_SUFFIX_64BIT "q"
#define __MEMRW_READ_INSTRUCTIONS(bitwidth) "mov" __MEMRW_SUFFIX_##bitwidth##BIT " %1, %0"
#define __MEMRW_WRITE_INSTRUCTIONS(bitwidth) "mov" __MEMRW_SUFFIX_##bitwidth##BIT " %1, %0"
#define __MEMRW_FLUSH_INSTRUCTIONS(bitwidth) "mov" __MEMRW_SUFFIX_##bitwidth##BIT " %1, %0; mov" __MEMRW_SUFFIX_##bitwidth##BIT " %0, %1"
#elif defined(__loongarch_lp64)
#define __MEMRW_SUFFIX_8BIT "b"
#define __MEMRW_SUFFIX_16BIT "h"
#define __MEMRW_SUFFIX_32BIT "w"
#define __MEMRW_SUFFIX_64BIT "d"
#define __MEMRW_READ_INSTRUCTIONS(bitwidth) "ld." __MEMRW_SUFFIX_##bitwidth##BIT " %0, %1"
#define __MEMRW_WRITE_INSTRUCTIONS(bitwidth) "st." __MEMRW_SUFFIX_##bitwidth##BIT " %1, %0"
#define __MEMRW_FLUSH_INSTRUCTIONS(bitwidth) "st." __MEMRW_SUFFIX_##bitwidth##BIT " %1, %0; dbar 0"
#elif defined(__aarch64__)
#define __MEMRW_SUFFIX_8BIT "b"
#define __MEMRW_SUFFIX_16BIT "h"
#define __MEMRW_SUFFIX_32BIT ""
#define __MEMRW_SUFFIX_64BIT ""
#define __MEMRW_REG_8BIT "w"
#define __MEMRW_REG_16BIT "w"
#define __MEMRW_REG_32BIT "w"
#define __MEMRW_REG_64BIT "x"
#define __MEMRW_READ_INSTRUCTIONS(bitwidth) \
"ldr" __MEMRW_SUFFIX_##bitwidth##BIT " %" __MEMRW_REG_##bitwidth##BIT "0, %1"
#define __MEMRW_WRITE_INSTRUCTIONS(bitwidth) \
"str" __MEMRW_SUFFIX_##bitwidth##BIT " %" __MEMRW_REG_##bitwidth##BIT "1, %0"
#define __MEMRW_FLUSH_INSTRUCTIONS(bitwidth) \
"str" __MEMRW_SUFFIX_##bitwidth##BIT " %" __MEMRW_REG_##bitwidth##BIT "1, %0; dsb sy"
#endif
#define __MEMRW_READ_FUNC(bitwidth) \
static inline uint##bitwidth##_t read##bitwidth(const volatile uint##bitwidth##_t *ptr) \
{ \
uint##bitwidth##_t val; \
__asm__ __volatile__( \
__MEMRW_READ_INSTRUCTIONS(bitwidth) \
: "=r" (val) \
: "m" (*ptr) \
: "memory" \
); \
return val; \
}
#define __MEMRW_WRITE_FUNC(bitwidth) \
static inline void write##bitwidth(const volatile uint##bitwidth##_t *ptr, uint##bitwidth##_t val) \
{ \
__asm__ __volatile__( \
__MEMRW_WRITE_INSTRUCTIONS(bitwidth) \
: \
: "m" (*ptr), \
"r" (val) \
: "memory" \
); \
}
#define __MEMRW_FLUSH_FUNC(bitwidth) \
static inline void flush##bitwidth(const volatile uint##bitwidth##_t *ptr, uint##bitwidth##_t val) \
{ \
__asm__ __volatile__( \
__MEMRW_FLUSH_INSTRUCTIONS(bitwidth) \
: \
: "m" (*ptr), \
"r" (val) \
: "memory" \
); \
}
/**
* Reads and returns the value stored in the 8-bit memory location pointed to by ptr.
*/
__MEMRW_READ_FUNC(8)
/**
* Reads and returns the value stored in the 16-bit memory location pointed to by ptr.
*/
__MEMRW_READ_FUNC(16)
/**
* Reads and returns the value stored in the 32-bit memory location pointed to by ptr.
*/
__MEMRW_READ_FUNC(32)
/**
* Reads and returns the value stored in the 64-bit memory location pointed to by ptr.
*/
__MEMRW_READ_FUNC(64)
/**
* Writes val to the 8-bit memory location pointed to by ptr.
*/
__MEMRW_WRITE_FUNC(8)
/**
* Writes val to the 16-bit memory location pointed to by ptr.
*/
__MEMRW_WRITE_FUNC(16)
/**
* Writes val to the 32-bit memory location pointed to by ptr.
*/
__MEMRW_WRITE_FUNC(32)
/**
* Writes val to the 64-bit memory location pointed to by ptr.
*/
__MEMRW_WRITE_FUNC(64)
/**
* Writes val to the 8-bit memory location pointed to by ptr. Only returns when the write is complete.
*/
__MEMRW_FLUSH_FUNC(8)
/**
* Writes val to the 16-bit memory location pointed to by ptr. Only returns when the write is complete.
*/
__MEMRW_FLUSH_FUNC(16)
/**
* Writes val to the 32-bit memory location pointed to by ptr. Only returns when the write is complete.
*/
__MEMRW_FLUSH_FUNC(32)
/**
* Writes val to the 64-bit memory location pointed to by ptr. Only returns when the write is complete.
*/
__MEMRW_FLUSH_FUNC(64)
#if defined(__i386__) || defined(__x86_64__)
// The BDA helpers below dereference small constant addresses, which GCC's
// -Warray-bounds heuristic flags as likely null derefs. Suppress locally;
// the accesses are intentional reads/writes of the x86 BIOS Data Area.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
/**
* Reads a 16-bit value from the x86 BIOS Data Area at the given linear address.
*/
static inline uint16_t bda_read16(uintptr_t address)
{
return read16((const volatile uint16_t *)address);
}
/**
* Writes a 16-bit value to the x86 BIOS Data Area at the given linear address.
*/
static inline void bda_write16(uintptr_t address, uint16_t value)
{
write16((const volatile uint16_t *)address, value);
}
#pragma GCC diagnostic pop
#endif
#endif // MEMRW_H