mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-27 20:14:27 +01:00
baremetal: all examples working, all failures accounted for!
SIMD&FP is now enabled in arm from bootloader.
This commit is contained in:
97
README.adoc
97
README.adoc
@@ -9795,7 +9795,7 @@ but the approximation is reasonable.
|
|||||||
+
|
+
|
||||||
It is used mostly for microarchitecture research purposes: when you are making a new chip technology, you don't really need to specialize enormously to an existing microarchitecture, but rather develop something that will work with a wide range of future architectures.
|
It is used mostly for microarchitecture research purposes: when you are making a new chip technology, you don't really need to specialize enormously to an existing microarchitecture, but rather develop something that will work with a wide range of future architectures.
|
||||||
** runs are deterministic by default, unlike QEMU which has a special <<qemu-record-and-replay>> mode, that requires first playing the content once and then replaying
|
** runs are deterministic by default, unlike QEMU which has a special <<qemu-record-and-replay>> mode, that requires first playing the content once and then replaying
|
||||||
** gem5 ARM at least appears to implement more low level CPU functionality than QEMU, e.g. QEMU only added EL2 in 2018: https://stackoverflow.com/questions/42824706/qemu-system-aarch64-entering-el1-when-emulating-a53-power-up See also: <<arm-exception-level>>
|
** gem5 ARM at least appears to implement more low level CPU functionality than QEMU, e.g. QEMU only added EL2 in 2018: https://stackoverflow.com/questions/42824706/qemu-system-aarch64-entering-el1-when-emulating-a53-power-up See also: <<arm-exception-levels>>
|
||||||
* disadvantage of gem5: slower than QEMU, see: <<benchmark-linux-kernel-boot>>
|
* disadvantage of gem5: slower than QEMU, see: <<benchmark-linux-kernel-boot>>
|
||||||
+
|
+
|
||||||
This implies that the user base is much smaller, since no Android devs.
|
This implies that the user base is much smaller, since no Android devs.
|
||||||
@@ -13034,6 +13034,19 @@ Does not have as many assembly code examples as you'd hope however...
|
|||||||
|
|
||||||
Latest version at: https://developer.arm.com/docs/den0024/latest/preface
|
Latest version at: https://developer.arm.com/docs/den0024/latest/preface
|
||||||
|
|
||||||
|
===== ARM processor documentation
|
||||||
|
|
||||||
|
ARM also releases documentation specific to each given processor.
|
||||||
|
|
||||||
|
This adds extra details to the more portable <<armarm8>> ISA documentation.
|
||||||
|
|
||||||
|
[[arm-cortex15-trm]]
|
||||||
|
===== ARM Cortex-A15 MPCore Processor Technical Reference Manual r4p0
|
||||||
|
|
||||||
|
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0438i/DDI0438I_cortex_a15_r4p0_trm.pdf
|
||||||
|
|
||||||
|
2013.
|
||||||
|
|
||||||
== Baremetal
|
== Baremetal
|
||||||
|
|
||||||
Getting started at: <<baremetal-setup>>
|
Getting started at: <<baremetal-setup>>
|
||||||
@@ -13226,9 +13239,51 @@ collect2: error: ld returned 1 exit status
|
|||||||
with the prebuilt toolchain, and I'm lazy to debug.
|
with the prebuilt toolchain, and I'm lazy to debug.
|
||||||
* there seems to to be no analogous `aarch64` Ubuntu package to `gcc-arm-none-eabi`: https://askubuntu.com/questions/1049249/is-there-a-package-with-the-aarch64-version-of-gcc-arm-none-eabi-for-bare-metal
|
* there seems to to be no analogous `aarch64` Ubuntu package to `gcc-arm-none-eabi`: https://askubuntu.com/questions/1049249/is-there-a-package-with-the-aarch64-version-of-gcc-arm-none-eabi-for-bare-metal
|
||||||
|
|
||||||
=== C++ baremetal
|
[[baremetal-cpp]]
|
||||||
|
=== Baremetal C++
|
||||||
|
|
||||||
TODO I tried by there was an error. Not yet properly reported. Should not be hard in theory since `libstdc++` is just part of GCC, as shown at: https://stackoverflow.com/questions/21872229/how-to-edit-and-re-build-the-gcc-libstdc-c-standard-library-source/51946224#51946224
|
TODO not working as of 8825222579767f2ee7e46ffd8204b9e509440759 + 1. Not yet properly researched / reported upstream yet.
|
||||||
|
|
||||||
|
Should not be hard in theory since `libstdc++` is just part of GCC, as shown at: https://stackoverflow.com/questions/21872229/how-to-edit-and-re-build-the-gcc-libstdc-c-standard-library-source/51946224#51946224
|
||||||
|
|
||||||
|
To test it out, I first hack link:common.py[] to enable `C++`:
|
||||||
|
|
||||||
|
....
|
||||||
|
consts['baremetal_build_in_exts'] = consts['build_in_exts']
|
||||||
|
....
|
||||||
|
|
||||||
|
and then I hack link:userland/arch/aarch64/c/multiline.cpp[] to consist only of an empty main:
|
||||||
|
|
||||||
|
....
|
||||||
|
int main() {}
|
||||||
|
....
|
||||||
|
|
||||||
|
then for example:
|
||||||
|
|
||||||
|
....
|
||||||
|
./build-baremetal --arch aarch64
|
||||||
|
./run --arch aarch64 --baremetal userland/arch/aarch64/c/multiline.cpp
|
||||||
|
....
|
||||||
|
|
||||||
|
fails with:
|
||||||
|
|
||||||
|
....
|
||||||
|
rom: requested regions overlap (rom dtb. free=0x00000000000000a0, addr=0x0000000000000000)
|
||||||
|
qemu-system-aarch64: rom check and register reset failed
|
||||||
|
....
|
||||||
|
|
||||||
|
and the gem5 build fails completely:
|
||||||
|
|
||||||
|
....
|
||||||
|
./build-baremetal --arch aarch64 --emulator gem5 userland/arch/aarch64/c/multiline.cpp
|
||||||
|
....
|
||||||
|
|
||||||
|
fails with:
|
||||||
|
|
||||||
|
....
|
||||||
|
/tmp/ccFd2YIB.o:(.eh_frame+0x1c): relocation truncated to fit: R_AARCH64_PREL32 against `.text'
|
||||||
|
collect2: error: ld returned 1 exit status
|
||||||
|
....
|
||||||
|
|
||||||
=== GDB builtin CPU simulator
|
=== GDB builtin CPU simulator
|
||||||
|
|
||||||
@@ -13300,7 +13355,7 @@ In this section we will focus on learning ARM architecture concepts that can onl
|
|||||||
|
|
||||||
Userland information can be found at: https://github.com/cirosantilli/arm-assembly-cheat
|
Userland information can be found at: https://github.com/cirosantilli/arm-assembly-cheat
|
||||||
|
|
||||||
==== ARM exception level
|
==== ARM exception levels
|
||||||
|
|
||||||
ARM exception levels are analogous to x86 <<ring0,rings>>.
|
ARM exception levels are analogous to x86 <<ring0,rings>>.
|
||||||
|
|
||||||
@@ -13512,7 +13567,7 @@ The first part of the table contains:
|
|||||||
|
|
||||||
and the following other parts are analogous, but referring to `SPx` and lower ELs.
|
and the following other parts are analogous, but referring to `SPx` and lower ELs.
|
||||||
|
|
||||||
We are going to do everything in <<arm-exception-level,EL1>> for now.
|
We are going to do everything in <<arm-exception-levels,EL1>> for now.
|
||||||
|
|
||||||
On the terminal output, we observe the initial values of:
|
On the terminal output, we observe the initial values of:
|
||||||
|
|
||||||
@@ -13729,7 +13784,21 @@ class RealViewPBX(RealView):
|
|||||||
|
|
||||||
==== aarch64 baremetal NEON setup
|
==== aarch64 baremetal NEON setup
|
||||||
|
|
||||||
Inside link:baremetal/lib/aarch64.S[] there is a chunk of code called "NEON setup".
|
Inside link:baremetal/lib/aarch64.S[] there is a chunk of code that enables floating point operations:
|
||||||
|
|
||||||
|
....
|
||||||
|
mov x1, 0x3 << 20
|
||||||
|
msr cpacr_el1, x1
|
||||||
|
isb
|
||||||
|
....
|
||||||
|
|
||||||
|
`cpacr_el1` is documented at <<armarm8>> D10.2.29 "CPACR_EL1, Architectural Feature Access Control Register".
|
||||||
|
|
||||||
|
Here we touch the FPEN bits to 3, which enable floating point operations:
|
||||||
|
|
||||||
|
____
|
||||||
|
11 This control does not cause any instructions to be trapped.
|
||||||
|
____
|
||||||
|
|
||||||
Without that, the `printf`:
|
Without that, the `printf`:
|
||||||
|
|
||||||
@@ -13787,7 +13856,7 @@ ISB
|
|||||||
|
|
||||||
but it entered an exception loop at `MSR CPTR_EL3, XZR`.
|
but it entered an exception loop at `MSR CPTR_EL3, XZR`.
|
||||||
|
|
||||||
We then found out that QEMU starts in EL1, and so we kept just the EL1 part, and it worked. Related:
|
We then found out that QEMU <<arm-exception-levels,<starts in EL1>>, and so we kept just the EL1 part, and it worked. Related:
|
||||||
|
|
||||||
* https://stackoverflow.com/questions/42824706/qemu-system-aarch64-entering-el1-when-emulating-a53-power-up
|
* https://stackoverflow.com/questions/42824706/qemu-system-aarch64-entering-el1-when-emulating-a53-power-up
|
||||||
* https://stackoverflow.com/questions/37299524/neon-support-in-armv8-system-mode-qemu
|
* https://stackoverflow.com/questions/37299524/neon-support-in-armv8-system-mode-qemu
|
||||||
@@ -15248,13 +15317,13 @@ So setup this `on_exit` automatically from all our <<baremetal-bootloaders>>, so
|
|||||||
+
|
+
|
||||||
The following examples end up testing that our setup is working:
|
The following examples end up testing that our setup is working:
|
||||||
+
|
+
|
||||||
* link:baremetal/c/assert_fail.c[]
|
* link:userland/c/assert_fail.c[]
|
||||||
* link:baremetal/return1.c[]
|
* link:userland/c/return0.c[]
|
||||||
* link:baremetal/return2.c[]
|
* link:userland/c/return1.c[]
|
||||||
* link:baremetal/exit0.c[]
|
* link:userland/c/return2.c[]
|
||||||
* link:baremetal/exit1.c[]
|
* link:userland/c/exit0.c[]
|
||||||
* link:baremetal/arch/arm/return1.S[]
|
* link:userland/c/exit1.c[]
|
||||||
* link:baremetal/arch/aarch64/return1.S[]
|
* link:userland/c/exit2.c[]
|
||||||
|
|
||||||
Beware that on Linux kernel simulations, you cannot even echo that string from userland, since userland stdout shows up on the serial.
|
Beware that on Linux kernel simulations, you cannot even echo that string from userland, since userland stdout shows up on the serial.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-exception-level */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-exception-levels */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-multicore */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-multicore */
|
||||||
|
|
||||||
.global main
|
#include <lkmc.h>
|
||||||
main:
|
|
||||||
|
LKMC_PROLOGUE
|
||||||
/* Reset spinlock. */
|
/* Reset spinlock. */
|
||||||
mov x0, 0
|
mov x0, 0
|
||||||
ldr x1, =spinlock
|
ldr x1, =spinlock
|
||||||
@@ -65,9 +66,6 @@ spinlock_start:
|
|||||||
/* Hint CPU 0 to enter low power mode. */
|
/* Hint CPU 0 to enter low power mode. */
|
||||||
wfe
|
wfe
|
||||||
cbz x0, spinlock_start
|
cbz x0, spinlock_start
|
||||||
|
LKMC_EPILOGUE
|
||||||
mov x0, 0
|
|
||||||
ret
|
|
||||||
|
|
||||||
spinlock:
|
spinlock:
|
||||||
.skip 8
|
.skip 8
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-exception-level */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-exception-levels */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
/* assert 0x12345678 + 1 == 0x12345679 */
|
|
||||||
|
|
||||||
#include <lkmc/m5ops.h>
|
|
||||||
|
|
||||||
.global main
|
|
||||||
main:
|
|
||||||
adr r0, myvar
|
|
||||||
ldr r1, [r0]
|
|
||||||
add r1, r1, #1
|
|
||||||
str r1, [r0]
|
|
||||||
movw r2, #0x5679
|
|
||||||
movt r2, #0x1234
|
|
||||||
cmp r1, r2
|
|
||||||
beq ok
|
|
||||||
LKMC_M5OPS_FAIL_1_ASM
|
|
||||||
ok:
|
|
||||||
LKMC_M5OPS_EXIT_ASM
|
|
||||||
myvar:
|
|
||||||
.word 0x12345678
|
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-multicore */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-multicore */
|
||||||
|
|
||||||
.global main
|
#include <lkmc.h>
|
||||||
main:
|
|
||||||
mov r0, #0
|
LKMC_PROLOGUE
|
||||||
|
mov r0, 0
|
||||||
ldr r1, =spinlock
|
ldr r1, =spinlock
|
||||||
str r0, [r1]
|
str r0, [r1]
|
||||||
/* Get CPU ID. */
|
/* Get CPU ID. */
|
||||||
mrc p15, 0, r1, c0, c0, 5
|
mrc p15, 0, r1, c0, c0, 5
|
||||||
ands r1, r1, #3
|
ands r1, r1, 3
|
||||||
beq cpu0_only
|
beq cpu0_only
|
||||||
cpu1_only:
|
cpu1_only:
|
||||||
mov r0, #1
|
mov r0, 1
|
||||||
ldr r1, =spinlock
|
ldr r1, =spinlock
|
||||||
str r0, [r1]
|
str r0, [r1]
|
||||||
dmb sy
|
dmb sy
|
||||||
@@ -22,17 +23,16 @@ cpu0_only:
|
|||||||
#if !LKMC_GEM5
|
#if !LKMC_GEM5
|
||||||
/* PSCI CPU_ON. */
|
/* PSCI CPU_ON. */
|
||||||
ldr r0, =0x84000003
|
ldr r0, =0x84000003
|
||||||
mov r1, #1
|
mov r1, 1
|
||||||
ldr r2, =cpu1_only
|
ldr r2, =cpu1_only
|
||||||
mov r3, #0
|
mov r3, 0
|
||||||
hvc 0
|
hvc 0
|
||||||
#endif
|
#endif
|
||||||
spinlock_start:
|
spinlock_start:
|
||||||
ldr r0, spinlock
|
ldr r0, spinlock
|
||||||
wfe
|
wfe
|
||||||
cmp r0, #0
|
cmp r0, 0
|
||||||
beq spinlock_start
|
beq spinlock_start
|
||||||
mov r0, #0
|
LKMC_EPILOGUE
|
||||||
bx lr
|
|
||||||
spinlock:
|
spinlock:
|
||||||
.skip 4
|
.skip 4
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
/* See the aarch64 version. */
|
/* See the aarch64 version. */
|
||||||
.global main
|
|
||||||
main:
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
LKMC_PROLOGUE
|
||||||
mov r0, #1
|
mov r0, #1
|
||||||
/* test-gdb-r0 */
|
/* test-gdb-r0 */
|
||||||
mov r1, #2
|
mov r1, #2
|
||||||
/* test-gdb-r1 */
|
/* test-gdb-r1 */
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
bx lr
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#magic-failure-string */
|
|
||||||
.global main
|
|
||||||
main:
|
|
||||||
mov r0, #1
|
|
||||||
bx lr
|
|
||||||
@@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
.global lkmc_start
|
.global lkmc_start
|
||||||
lkmc_start:
|
lkmc_start:
|
||||||
/* = NEON setup */
|
|
||||||
mov x1, #(0x3 << 20)
|
|
||||||
msr cpacr_el1, x1
|
|
||||||
isb
|
|
||||||
|
|
||||||
/* Load the vector table. */
|
/* Load the vector table. */
|
||||||
ldr x0, =lkmc_vector_table
|
ldr x0, =lkmc_vector_table
|
||||||
msr vbar_el1, x0
|
msr vbar_el1, x0
|
||||||
|
|
||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#aarch64-baremetal-neon-setup */
|
||||||
|
mov x1, 0x3 << 20
|
||||||
|
msr cpacr_el1, x1
|
||||||
|
isb
|
||||||
|
|
||||||
/* Prepare the stack for main, mandatory for C code. */
|
/* Prepare the stack for main, mandatory for C code. */
|
||||||
ldr x0, =stack_top
|
ldr x0, =stack_top
|
||||||
mov sp, x0
|
mov sp, x0
|
||||||
@@ -30,8 +30,8 @@ LKMC_VECTOR_TABLE
|
|||||||
|
|
||||||
/* Default trap handler. */
|
/* Default trap handler. */
|
||||||
LKMC_WEAK(lkmc_vector_trap_handler)
|
LKMC_WEAK(lkmc_vector_trap_handler)
|
||||||
ldr x0, =lkmc_vector_trap_handler_error
|
ldr x0, =lkmc_vector_trap_handler_error_message
|
||||||
bl puts
|
bl puts
|
||||||
bl abort
|
bl abort
|
||||||
lkmc_vector_trap_handler_error:
|
lkmc_vector_trap_handler_error_message:
|
||||||
.asciz "error: unexpected interrupt"
|
.asciz "error: unexpected interrupt"
|
||||||
|
|||||||
@@ -5,6 +5,19 @@ lkmc_start:
|
|||||||
/* Prepare the stack for main, mandatory for C code. */
|
/* Prepare the stack for main, mandatory for C code. */
|
||||||
ldr sp, =stack_top
|
ldr sp, =stack_top
|
||||||
|
|
||||||
|
/* Enable floating point.
|
||||||
|
* Code copied from: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0409h/CHDEGGFF.html
|
||||||
|
* Without this, SIMD operations such as vmov raise an exception.
|
||||||
|
*/
|
||||||
|
mrc p15, 0, r0, c1, c0, 2 /* Read CPACR into r0 */
|
||||||
|
orr r0, r0, 3 << 20 /* OR in User and Privileged access for CP10 */
|
||||||
|
orr r0, r0, 3 << 22 /* OR in User and Privileged access for CP11 */
|
||||||
|
bic r0, r0, 3 << 30 /* Clear ASEDIS/D32DIS if set */
|
||||||
|
mcr p15, 0, r0, c1, c0, 2 /* Store new access permissions into CPACR */
|
||||||
|
isb /* Ensure side-effect of CPACR is visible */
|
||||||
|
mov r0, 1 << 30 /* Create value with FPEXC (bit 30) set in r0 */
|
||||||
|
vmsr fpexc, r0 /* Enable VFP and SIMD extensions */
|
||||||
|
|
||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#magic-failure-string */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#magic-failure-string */
|
||||||
ldr r0, =lkmc_baremetal_on_exit_callback
|
ldr r0, =lkmc_baremetal_on_exit_callback
|
||||||
bl on_exit
|
bl on_exit
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ Build the baremetal examples with crosstool-NG.
|
|||||||
for path, in_dirnames, in_filenames in self.sh.walk(target):
|
for path, in_dirnames, in_filenames in self.sh.walk(target):
|
||||||
for in_filename in in_filenames:
|
for in_filename in in_filenames:
|
||||||
in_ext = os.path.splitext(in_filename)[1]
|
in_ext = os.path.splitext(in_filename)[1]
|
||||||
if not in_ext in self.env['build_in_exts']:
|
if not in_ext in self.env['baremetal_build_in_exts']:
|
||||||
continue
|
continue
|
||||||
in_path = os.path.join(path, in_filename)
|
in_path = os.path.join(path, in_filename)
|
||||||
my_thread_pool.submit({
|
my_thread_pool.submit({
|
||||||
|
|||||||
@@ -107,10 +107,13 @@ consts['cxx_ext'] = '.cpp'
|
|||||||
consts['header_ext'] = '.h'
|
consts['header_ext'] = '.h'
|
||||||
consts['kernel_module_ext'] = '.ko'
|
consts['kernel_module_ext'] = '.ko'
|
||||||
consts['obj_ext'] = '.o'
|
consts['obj_ext'] = '.o'
|
||||||
consts['build_in_exts'] = [
|
# https://github.com/cirosantilli/linux-kernel-module-cheat#baremetal-cpp
|
||||||
|
consts['baremetal_build_in_exts'] = [
|
||||||
consts['asm_ext'],
|
consts['asm_ext'],
|
||||||
consts['c_ext'],
|
consts['c_ext'],
|
||||||
consts['cxx_ext'],
|
]
|
||||||
|
consts['build_in_exts'] = consts['baremetal_build_in_exts'] + [
|
||||||
|
consts['cxx_ext']
|
||||||
]
|
]
|
||||||
consts['userland_out_exts'] = [
|
consts['userland_out_exts'] = [
|
||||||
consts['userland_executable_ext'],
|
consts['userland_executable_ext'],
|
||||||
@@ -939,7 +942,7 @@ Incompatible archs are skipped.
|
|||||||
env['disk_image'] = env['gem5_fake_iso']
|
env['disk_image'] = env['gem5_fake_iso']
|
||||||
path = self.resolve_baremetal_executable(env['baremetal'])
|
path = self.resolve_baremetal_executable(env['baremetal'])
|
||||||
source_path_noext = os.path.splitext(join(
|
source_path_noext = os.path.splitext(join(
|
||||||
env['baremetal_source_dir'],
|
env['root_dir'],
|
||||||
os.path.relpath(path, env['baremetal_build_dir'])
|
os.path.relpath(path, env['baremetal_build_dir'])
|
||||||
))[0]
|
))[0]
|
||||||
for ext in [env['c_ext'], env['asm_ext']]:
|
for ext in [env['c_ext'], env['asm_ext']]:
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ class PathProperties:
|
|||||||
# All new properties must be listed here or else you get an error.
|
# All new properties must be listed here or else you get an error.
|
||||||
default_properties = {
|
default_properties = {
|
||||||
'allowed_archs': None,
|
'allowed_archs': None,
|
||||||
|
# The example uses aarch32 instructions which are not present in ARMv7.
|
||||||
|
# Therefore, it cannot be run in baremetal ARMv7 CPUs.
|
||||||
|
# User mode simulation however seems to enable aarch32 so these run fine.
|
||||||
|
'arm_aarch32': False,
|
||||||
# Examples that can be built in baremetal.
|
# Examples that can be built in baremetal.
|
||||||
'baremetal': False,
|
'baremetal': False,
|
||||||
'c_std': default_c_std,
|
'c_std': default_c_std,
|
||||||
@@ -52,7 +56,6 @@ class PathProperties:
|
|||||||
# it only generates intermediate object files. Therefore it
|
# it only generates intermediate object files. Therefore it
|
||||||
# should not be run while testing.
|
# should not be run while testing.
|
||||||
'no_executable': False,
|
'no_executable': False,
|
||||||
'receives_signal': None,
|
|
||||||
# The script requires a non-trivial argument to be passed to run properly.
|
# The script requires a non-trivial argument to be passed to run properly.
|
||||||
'requires_argument': False,
|
'requires_argument': False,
|
||||||
'requires_dynamic_library': False,
|
'requires_dynamic_library': False,
|
||||||
@@ -66,6 +69,13 @@ class PathProperties:
|
|||||||
# deeply to the system it runs on, which would preventing further interactive
|
# deeply to the system it runs on, which would preventing further interactive
|
||||||
# or test usage of the system, for example poweroff or messing up the GUI.
|
# or test usage of the system, for example poweroff or messing up the GUI.
|
||||||
'requires_sudo': False,
|
'requires_sudo': False,
|
||||||
|
# The signal received is generated by the OS implicitly rather than explicitly
|
||||||
|
# done sith signal(), e.g. Illegal instruction or sigsegv.
|
||||||
|
# Therefore, it won't behave in the same way in baremetal. aarch64 already
|
||||||
|
# has an exception handler which we could use but arm doesn't and the IP
|
||||||
|
# goes astray, so let's just skip this for now.
|
||||||
|
'signal_generated_by_os': False,
|
||||||
|
'signal_received': None,
|
||||||
# We were lazy to properly classify why we are skipping these tests.
|
# We were lazy to properly classify why we are skipping these tests.
|
||||||
# TODO get it done.
|
# TODO get it done.
|
||||||
'skip_run_unclassified': False,
|
'skip_run_unclassified': False,
|
||||||
@@ -133,6 +143,12 @@ class PathProperties:
|
|||||||
is_baremetal=is_baremetal,
|
is_baremetal=is_baremetal,
|
||||||
is_userland=is_userland
|
is_userland=is_userland
|
||||||
) and
|
) and
|
||||||
|
not (
|
||||||
|
is_baremetal and (
|
||||||
|
self['arm_aarch32'] or
|
||||||
|
self['signal_generated_by_os']
|
||||||
|
)
|
||||||
|
) and
|
||||||
not self['interactive'] and
|
not self['interactive'] and
|
||||||
not self['more_than_1s'] and
|
not self['more_than_1s'] and
|
||||||
not self['no_executable'] and
|
not self['no_executable'] and
|
||||||
@@ -246,7 +262,6 @@ path_properties_tuples = (
|
|||||||
'arm': (
|
'arm': (
|
||||||
{'allowed_archs': {'arm'}},
|
{'allowed_archs': {'arm'}},
|
||||||
{
|
{
|
||||||
'gem5_assert.S': {'requires_m5ops': True},
|
|
||||||
'multicore.S': {'test_run_args': {'cpus': 2}},
|
'multicore.S': {'test_run_args': {'cpus': 2}},
|
||||||
'no_bootloader': (
|
'no_bootloader': (
|
||||||
{'extra_objs_disable_baremetal_bootloader': True},
|
{'extra_objs_disable_baremetal_bootloader': True},
|
||||||
@@ -326,11 +341,13 @@ path_properties_tuples = (
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
'lkmc_assert_eq_fail.S': {'receives_signal': signal.Signals.SIGABRT},
|
'lkmc_assert_eq_fail.S': {'signal_received': signal.Signals.SIGABRT},
|
||||||
'lkmc_assert_memcmp_fail.S': {'receives_signal': signal.Signals.SIGABRT},
|
'lkmc_assert_memcmp_fail.S': {'signal_received': signal.Signals.SIGABRT},
|
||||||
'udf.S': {
|
'udf.S': {
|
||||||
'receives_signal': signal.Signals.SIGILL
|
'signal_generated_by_os': True,
|
||||||
|
'signal_received': signal.Signals.SIGILL,
|
||||||
},
|
},
|
||||||
|
'vcvta.S': {'arm_aarch32': True},
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
'aarch64': (
|
'aarch64': (
|
||||||
@@ -344,15 +361,16 @@ path_properties_tuples = (
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
'lkmc_assert_eq_fail.S': {'receives_signal': signal.Signals.SIGABRT},
|
'lkmc_assert_eq_fail.S': {'signal_received': signal.Signals.SIGABRT},
|
||||||
'lkmc_assert_memcmp_fail.S': {'receives_signal': signal.Signals.SIGABRT},
|
'lkmc_assert_memcmp_fail.S': {'signal_received': signal.Signals.SIGABRT},
|
||||||
'udf.S': {
|
'udf.S': {
|
||||||
'receives_signal': signal.Signals.SIGILL
|
'signal_generated_by_os': True,
|
||||||
|
'signal_received': signal.Signals.SIGILL,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
'lkmc_assert_fail.S': {
|
'lkmc_assert_fail.S': {
|
||||||
'receives_signal': signal.Signals.SIGABRT,
|
'signal_received': signal.Signals.SIGABRT,
|
||||||
},
|
},
|
||||||
'x86_64': (
|
'x86_64': (
|
||||||
{'allowed_archs': {'x86_64'}},
|
{'allowed_archs': {'x86_64'}},
|
||||||
@@ -363,13 +381,13 @@ path_properties_tuples = (
|
|||||||
{
|
{
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
'ring0.c': {
|
'ring0.c': {
|
||||||
'receives_signal': signal.Signals.SIGSEGV
|
'signal_received': signal.Signals.SIGSEGV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
'lkmc_assert_eq_fail.S': {'receives_signal': signal.Signals.SIGABRT},
|
'lkmc_assert_eq_fail.S': {'signal_received': signal.Signals.SIGABRT},
|
||||||
'lkmc_assert_memcmp_fail.S': {'receives_signal': signal.Signals.SIGABRT},
|
'lkmc_assert_memcmp_fail.S': {'signal_received': signal.Signals.SIGABRT},
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -380,10 +398,10 @@ path_properties_tuples = (
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'abort.c': {
|
'abort.c': {
|
||||||
'receives_signal': signal.Signals.SIGABRT,
|
'signal_received': signal.Signals.SIGABRT,
|
||||||
},
|
},
|
||||||
'assert_fail.c': {
|
'assert_fail.c': {
|
||||||
'receives_signal': signal.Signals.SIGABRT,
|
'signal_received': signal.Signals.SIGABRT,
|
||||||
},
|
},
|
||||||
'exit1.c': {'exit_status': 1},
|
'exit1.c': {'exit_status': 1},
|
||||||
'exit2.c': {'exit_status': 2},
|
'exit2.c': {'exit_status': 2},
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ If given, run only the given tests. Otherwise, run all tests.
|
|||||||
path_abs = os.path.abspath(path)
|
path_abs = os.path.abspath(path)
|
||||||
dirpath_relative_root = path_abs[rootdir_abs_len + 1:]
|
dirpath_relative_root = path_abs[rootdir_abs_len + 1:]
|
||||||
for in_filename in in_filenames:
|
for in_filename in in_filenames:
|
||||||
if os.path.splitext(in_filename)[1] in (self.env['c_ext'], self.env['asm_ext']):
|
if os.path.splitext(in_filename)[1] in self.env['baremetal_build_in_exts']:
|
||||||
path_relative_root = os.path.join(dirpath_relative_root, in_filename)
|
path_relative_root = os.path.join(dirpath_relative_root, in_filename)
|
||||||
my_path_properties = path_properties.get(path_relative_root)
|
my_path_properties = path_properties.get(path_relative_root)
|
||||||
if my_path_properties.should_be_tested(self.env, is_baremetal=True):
|
if my_path_properties.should_be_tested(self.env, is_baremetal=True):
|
||||||
@@ -55,12 +55,16 @@ If given, run only the given tests. Otherwise, run all tests.
|
|||||||
'baremetal': os.path.relpath(os.path.join(path_abs, in_filename), os.getcwd()),
|
'baremetal': os.path.relpath(os.path.join(path_abs, in_filename), os.getcwd()),
|
||||||
})
|
})
|
||||||
cur_run_args.update(my_path_properties['test_run_args'])
|
cur_run_args.update(my_path_properties['test_run_args'])
|
||||||
my_thread_pool.submit({
|
run_test_args = {
|
||||||
'expected_exit_status': my_path_properties['exit_status'],
|
'expected_exit_status': my_path_properties['exit_status'],
|
||||||
'run_args': cur_run_args,
|
'run_args': cur_run_args,
|
||||||
'run_obj': lkmc.import_path.import_path_main('run'),
|
'run_obj': lkmc.import_path.import_path_main('run'),
|
||||||
'test_id': path_relative_root,
|
'test_id': path_relative_root,
|
||||||
})
|
}
|
||||||
|
signal = my_path_properties['signal_received']
|
||||||
|
if signal is not None:
|
||||||
|
run_test_args['expected_exit_status'] = 128 + signal.value
|
||||||
|
my_thread_pool.submit(run_test_args)
|
||||||
return self._handle_thread_pool_errors(my_thread_pool)
|
return self._handle_thread_pool_errors(my_thread_pool)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -65,8 +65,9 @@ If given, run only the given tests. Otherwise, run all tests.
|
|||||||
'run_obj': lkmc.import_path.import_path_main('run'),
|
'run_obj': lkmc.import_path.import_path_main('run'),
|
||||||
'test_id': path_relative_root,
|
'test_id': path_relative_root,
|
||||||
}
|
}
|
||||||
signal = my_path_properties['receives_signal']
|
signal = my_path_properties['signal_received']
|
||||||
if signal is not None:
|
if signal is not None:
|
||||||
|
# Python subprocess reports signals differently from Bash's 128 + signal rule.
|
||||||
run_test_args['expected_exit_status'] = -signal.value
|
run_test_args['expected_exit_status'] = -signal.value
|
||||||
my_thread_pool.submit(run_test_args)
|
my_thread_pool.submit(run_test_args)
|
||||||
return self._handle_thread_pool_errors(my_thread_pool)
|
return self._handle_thread_pool_errors(my_thread_pool)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
int main(void) {
|
int main() {
|
||||||
uint64_t io = 0;
|
uint64_t io = 0;
|
||||||
__asm__ (
|
__asm__ (
|
||||||
R"(
|
R"(
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#define ELEM_SIZE 4
|
#define ELEM_SIZE 4
|
||||||
|
|
||||||
.data;
|
.data;
|
||||||
|
.align 4
|
||||||
my_array_0:
|
my_array_0:
|
||||||
.word 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
.word 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
||||||
my_array_1:
|
my_array_1:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ LKMC_PROLOGUE
|
|||||||
|
|
||||||
/* Now the same from memory with vldr and vstr. */
|
/* Now the same from memory with vldr and vstr. */
|
||||||
.data
|
.data
|
||||||
|
.align 4
|
||||||
my_float_0:
|
my_float_0:
|
||||||
.float 1.5
|
.float 1.5
|
||||||
my_float_1:
|
my_float_1:
|
||||||
|
|||||||
1
userland/c/empty.c
Normal file
1
userland/c/empty.c
Normal file
@@ -0,0 +1 @@
|
|||||||
|
int main(void) {}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int ret;
|
int ret;
|
||||||
if (argc == 1) {
|
if (argc <= 1) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
ret = strtoull(argv[1], NULL, 0);
|
ret = strtoull(argv[1], NULL, 0);
|
||||||
|
|||||||
4
userland/cpp/empty.cpp
Normal file
4
userland/cpp/empty.cpp
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Sanity checking low level stuff, initially inspired by baremetal.
|
||||||
|
// https://github.com/cirosantilli/linux-kernel-module-cheat#baremetal-cpp
|
||||||
|
|
||||||
|
int main() {}
|
||||||
Reference in New Issue
Block a user