303 lines
5.9 KiB
ArmAsm
303 lines
5.9 KiB
ArmAsm
.section .text
|
|||
|
|
.option norvc
|
||
|
|
.global _start
|
||
|
|
|
||
|
|
# Helper macro to exit with code if condition fails
|
||
|
|
# Example: ASSERT_EQ a0, 0, 4 (if a0 != 0, exit with code 4)
|
||
|
|
.macro ASSERT_EQ reg, val, error_code
|
||
|
|
li t4, \val
|
||
|
|
beq \reg, t4, .L_ok_\@
|
||
|
|
li a0, \error_code
|
||
|
|
li a7, 93
|
||
|
|
ecall
|
||
|
|
.L_ok_\@:
|
||
|
|
.endm
|
||
|
|
|
||
|
|
# Helper macro to exit with code if registers are not equal
|
||
|
|
.macro ASSERT_REG_EQ reg1, reg2, error_code
|
||
|
|
beq \reg1, \reg2, .L_ok_reg_\@
|
||
|
|
li a0, \error_code
|
||
|
|
li a7, 93
|
||
|
|
ecall
|
||
|
|
.L_ok_reg_\@:
|
||
|
|
.endm
|
||
|
|
|
||
|
|
# Helper macro to exit with code if a register is negative
|
||
|
|
.macro ASSERT_GEZ reg, error_code
|
||
|
|
bgez \reg, .L_ok_gez_\@
|
||
|
|
li a0, \error_code
|
||
|
|
li a7, 93
|
||
|
|
ecall
|
||
|
|
.L_ok_gez_\@:
|
||
|
|
.endm
|
||
|
|
|
||
|
|
_start:
|
||
|
|
# 1. Write welcome message to stdout
|
||
|
|
li a7, 64 # sys_write
|
||
|
|
li a0, 1 # stdout
|
||
|
|
la a1, msg_welcome
|
||
|
|
li a2, 29 # welcome message length
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 29, 1
|
||
|
|
|
||
|
|
# 2. Test clock_gettime
|
||
|
|
li a7, 113 # sys_clock_gettime
|
||
|
|
li a0, 0 # CLOCK_REALTIME
|
||
|
|
la a1, timespec_buf
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 2
|
||
|
|
# verify we wrote something non-zero to seconds
|
||
|
|
lw t0, timespec_buf
|
||
|
|
ASSERT_GEZ t0, 3
|
||
|
|
|
||
|
|
# 3. Test gettimeofday
|
||
|
|
li a7, 169 # sys_gettimeofday
|
||
|
|
la a0, timeval_buf
|
||
|
|
li a1, 0 # NULL timezone
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 4
|
||
|
|
lw t0, timeval_buf
|
||
|
|
ASSERT_GEZ t0, 5
|
||
|
|
|
||
|
|
# 4. Test openat to create file
|
||
|
|
li a7, 56 # sys_openat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, file_name
|
||
|
|
li a2, 577 # O_CREAT | O_WRONLY | O_TRUNC (64 | 1 | 512 = 577)
|
||
|
|
li a3, 0644 # permissions
|
||
|
|
ecall
|
||
|
|
ASSERT_GEZ a0, 6
|
||
|
|
mv s2, a0 # save fd in s2
|
||
|
|
|
||
|
|
# 5. Write to the new file
|
||
|
|
li a7, 64 # sys_write
|
||
|
|
mv a0, s2 # fd
|
||
|
|
la a1, msg_to_file
|
||
|
|
li a2, 29 # length
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 29, 7
|
||
|
|
|
||
|
|
# 6. Close the file
|
||
|
|
li a7, 57 # sys_close
|
||
|
|
mv a0, s2 # fd
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 8
|
||
|
|
|
||
|
|
# 7. Open file O_RDONLY
|
||
|
|
li a7, 56 # sys_openat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, file_name
|
||
|
|
li a2, 0 # O_RDONLY
|
||
|
|
li a3, 0
|
||
|
|
ecall
|
||
|
|
ASSERT_GEZ a0, 9
|
||
|
|
mv s2, a0 # save fd in s2
|
||
|
|
|
||
|
|
# 7b. Test fstat
|
||
|
|
li a7, 80 # sys_fstat
|
||
|
|
mv a0, s2 # fd
|
||
|
|
la a1, stat_buf
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 20
|
||
|
|
lw t0, stat_buf + 48
|
||
|
|
ASSERT_EQ t0, 29, 21
|
||
|
|
|
||
|
|
# 7c. Test newfstatat
|
||
|
|
li a7, 79 # sys_newfstatat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, file_name
|
||
|
|
la a2, stat_buf
|
||
|
|
li a3, 0 # flags
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 22
|
||
|
|
lw t0, stat_buf + 48
|
||
|
|
ASSERT_EQ t0, 29, 23
|
||
|
|
|
||
|
|
|
||
|
|
# 8. Read from the file
|
||
|
|
li a7, 63 # sys_read
|
||
|
|
mv a0, s2 # fd
|
||
|
|
la a1, read_buf
|
||
|
|
li a2, 50 # buffer size
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 29, 10 # should read 29 bytes
|
||
|
|
|
||
|
|
# verify read content matches
|
||
|
|
la t0, msg_to_file
|
||
|
|
la t1, read_buf
|
||
|
|
li t2, 0 # index
|
||
|
|
.L_loop:
|
||
|
|
add t3, t0, t2
|
||
|
|
lb t3, 0(t3)
|
||
|
|
add t5, t1, t2
|
||
|
|
lb t5, 0(t5)
|
||
|
|
ASSERT_REG_EQ t3, t5, 11
|
||
|
|
addi t2, t2, 1
|
||
|
|
li t6, 29
|
||
|
|
blt t2, t6, .L_loop
|
||
|
|
|
||
|
|
# 9. Close the file
|
||
|
|
li a7, 57 # sys_close
|
||
|
|
mv a0, s2 # fd
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 12
|
||
|
|
|
||
|
|
# 9b. Test renameat (rename test_output.txt to test_output_new.txt)
|
||
|
|
li a7, 38 # sys_renameat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, file_name
|
||
|
|
li a2, -100 # AT_FDCWD
|
||
|
|
la a3, file_name_new
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 24
|
||
|
|
|
||
|
|
# 9c. Verify renamed file can be opened O_RDONLY
|
||
|
|
li a7, 56 # sys_openat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, file_name_new
|
||
|
|
li a2, 0 # O_RDONLY
|
||
|
|
li a3, 0
|
||
|
|
ecall
|
||
|
|
ASSERT_GEZ a0, 25
|
||
|
|
mv s3, a0
|
||
|
|
|
||
|
|
# 9d. Close renamed file
|
||
|
|
li a7, 57 # sys_close
|
||
|
|
mv a0, s3
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 26
|
||
|
|
|
||
|
|
|
||
|
|
# 10. Test mkdirat
|
||
|
|
li a7, 34 # sys_mkdirat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, dir_name
|
||
|
|
li a2, 0755
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 13
|
||
|
|
|
||
|
|
# 11. Open directory fd
|
||
|
|
li a7, 56 # sys_openat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, dir_name
|
||
|
|
li a2, 0 # O_RDONLY
|
||
|
|
li a3, 0
|
||
|
|
ecall
|
||
|
|
ASSERT_GEZ a0, 14
|
||
|
|
mv s2, a0 # save fd in s2
|
||
|
|
|
||
|
|
# 12. Test getdents64
|
||
|
|
li a7, 61 # sys_getdents64
|
||
|
|
mv a0, s2 # fd
|
||
|
|
la a1, dirents_buf
|
||
|
|
li a2, 512 # buffer size
|
||
|
|
ecall
|
||
|
|
ASSERT_GEZ a0, 15
|
||
|
|
|
||
|
|
# 13. Close directory fd
|
||
|
|
li a7, 57 # sys_close
|
||
|
|
mv a0, s2 # fd
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 16
|
||
|
|
|
||
|
|
# 13b. Test readlinkat
|
||
|
|
li a7, 78 # sys_readlinkat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, link_name
|
||
|
|
la a2, read_buf
|
||
|
|
li a3, 50 # buffer size
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 19, 27
|
||
|
|
|
||
|
|
# verify symlink target string
|
||
|
|
la t0, file_name_new
|
||
|
|
la t1, read_buf
|
||
|
|
li t2, 0
|
||
|
|
.L_loop_link:
|
||
|
|
add t3, t0, t2
|
||
|
|
lb t3, 0(t3)
|
||
|
|
add t5, t1, t2
|
||
|
|
lb t5, 0(t5)
|
||
|
|
ASSERT_REG_EQ t3, t5, 28
|
||
|
|
addi t2, t2, 1
|
||
|
|
li t6, 19
|
||
|
|
blt t2, t6, .L_loop_link
|
||
|
|
|
||
|
|
# 14. Test unlinkat for renamed file
|
||
|
|
li a7, 35 # sys_unlinkat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, file_name_new
|
||
|
|
li a2, 0
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 17
|
||
|
|
|
||
|
|
# 14b. Test unlinkat for symlink
|
||
|
|
li a7, 35 # sys_unlinkat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, link_name
|
||
|
|
li a2, 0
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 29
|
||
|
|
|
||
|
|
# 15. Test unlinkat with AT_REMOVEDIR for directory
|
||
|
|
li a7, 35 # sys_unlinkat
|
||
|
|
li a0, -100 # AT_FDCWD
|
||
|
|
la a1, dir_name
|
||
|
|
li a2, 512 # AT_REMOVEDIR
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 0, 18
|
||
|
|
|
||
|
|
|
||
|
|
# 15b. Test getrandom
|
||
|
|
li a7, 278 # sys_getrandom
|
||
|
|
la a0, random_buf
|
||
|
|
li a1, 16 # 16 bytes
|
||
|
|
li a2, 0 # no flags
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 16, 185
|
||
|
|
|
||
|
|
# 16. Write success message
|
||
|
|
li a7, 64 # sys_write
|
||
|
|
li a0, 1 # stdout
|
||
|
|
la a1, msg_success
|
||
|
|
li a2, 33 # success message length
|
||
|
|
ecall
|
||
|
|
ASSERT_EQ a0, 33, 19
|
||
|
|
|
||
|
|
# 17. Exit with 0
|
||
|
|
li a7, 93 # sys_exit
|
||
|
|
li a0, 0 # status 0
|
||
|
|
ecall
|
||
|
|
|
||
|
|
.section .rodata
|
||
|
|
msg_welcome:
|
||
|
|
.string "Running Syscall Verification\n"
|
||
|
|
msg_to_file:
|
||
|
|
.string "Hello from RISC-V A-Machine!\n"
|
||
|
|
msg_success:
|
||
|
|
.string "All Extended Syscall Tests PASS!\n"
|
||
|
|
file_name:
|
||
|
|
.string "test_output.txt"
|
||
|
|
file_name_new:
|
||
|
|
.string "test_output_new.txt"
|
||
|
|
link_name:
|
||
|
|
.string "test_link.txt"
|
||
|
|
dir_name:
|
||
|
|
.string "test_dir"
|
||
|
|
|
||
|
|
.section .bss
|
||
|
|
.align 4
|
||
|
|
timespec_buf:
|
||
|
|
.space 16
|
||
|
|
timeval_buf:
|
||
|
|
.space 8
|
||
|
|
read_buf:
|
||
|
|
.space 64
|
||
|
|
dirents_buf:
|
||
|
|
.space 512
|
||
|
|
random_buf:
|
||
|
|
.space 16
|
||
|
|
stat_buf:
|
||
|
|
.space 104
|
||
|
|
|