add aarch64

master
equation314 6 years ago
parent 42f31a0c17
commit c524941890

2
.gitignore vendored

@ -0,0 +1,2 @@
build/
.DS_Store

@ -1,8 +1,7 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(ucore_user) project(ucore_user)
enable_language(ASM)
enable_language(C ASM)
# Path # Path
if (${ARCH} STREQUAL riscv32 OR ${ARCH} STREQUAL riscv64) if (${ARCH} STREQUAL riscv32 OR ${ARCH} STREQUAL riscv64)
@ -36,6 +35,8 @@ elseif (${ARCH} STREQUAL riscv64)
set(CMAKE_C_FLAGS "-march=rv64imac -mabi=lp64 -mcmodel=medany") set(CMAKE_C_FLAGS "-march=rv64imac -mabi=lp64 -mcmodel=medany")
elseif (${ARCH} STREQUAL aarch64) elseif (${ARCH} STREQUAL aarch64)
set(PREFIX aarch64-none-elf-) set(PREFIX aarch64-none-elf-)
set(CMAKE_C_FLAGS "-mgeneral-regs-only")
set(CMAKE_C_LINK_FLAGS "-Ttext 0xffff000000000000")
else() else()
message("Unsupported arch: ${ARCH}") message("Unsupported arch: ${ARCH}")
endif () endif ()
@ -44,7 +45,7 @@ set(CMAKE_C_COMPILER ${PREFIX}gcc)
set(CMAKE_RANLIB ${PREFIX}ranlib) set(CMAKE_RANLIB ${PREFIX}ranlib)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin -nostdinc -fno-stack-protector -ggdb -Wall") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin -nostdinc -fno-stack-protector -ggdb -Wall")
set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS})
set(CMAKE_C_LINK_FLAGS "-nostdlib") # get rid of '-Wl,-search_paths_first -Wl,-headerpad_max_install_names' set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") # get rid of '-Wl,-search_paths_first -Wl,-headerpad_max_install_names'
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) # get rid of '-rdynamic' on Linux set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) # get rid of '-rdynamic' on Linux
# Library # Library

@ -0,0 +1,14 @@
// See LICENSE for license details.
#ifndef __LIBS_AARCH64_H__
#define __LIBS_AARCH64_H__
#define do_div(n, base) \
({ \
int __res; \
__res = ((unsigned long)n) % (unsigned)base; \
n = ((unsigned long)n) / (unsigned)base; \
__res; \
})
#endif

@ -0,0 +1,75 @@
#ifndef __LIBS_ATOMIC_H__
#define __LIBS_ATOMIC_H__
// TODO: implement atomic operations for aarch64
/* Atomic operations that C can't guarantee us. Useful for resource counting etc.. */
static inline void set_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline void clear_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline void change_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_and_set_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_and_clear_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_bit(int nr, volatile void *addr) __attribute__((always_inline));
/* *
* set_bit - Atomically set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
* */
static inline void set_bit(int nr, volatile void *addr) {
/* unimplemented */
}
/* *
* clear_bit - Atomically clears a bit in memory
* @nr: the bit to clear
* @addr: the address to start counting from
* */
static inline void clear_bit(int nr, volatile void *addr) {
/* unimplemented */
}
/* *
* change_bit - Atomically toggle a bit in memory
* @nr: the bit to change
* @addr: the address to start counting from
* */
static inline void change_bit(int nr, volatile void *addr) {
/* unimplemented */
}
/* *
* test_bit - Determine whether a bit is set
* @nr: the bit to test
* @addr: the address to count from
* */
static inline bool test_bit(int nr, volatile void *addr) {
/* unimplemented */
return 0;
}
/* *
* test_and_set_bit - Atomically set a bit and return its old value
* @nr: the bit to set
* @addr: the address to count from
* */
static inline bool test_and_set_bit(int nr, volatile void *addr) {
/* unimplemented */
return 0;
}
/* *
* test_and_clear_bit - Atomically clear a bit and return its old value
* @nr: the bit to clear
* @addr: the address to count from
* */
static inline bool test_and_clear_bit(int nr, volatile void *addr) {
/* unimplemented */
return 0;
}
#endif /* !__LIBS_ATOMIC_H__ */

@ -0,0 +1,79 @@
#ifndef __LIBS_DEFS_H__
#define __LIBS_DEFS_H__
#ifndef NULL
#define NULL ((void *)0)
#endif
#define __always_inline inline __attribute__((always_inline))
#define __noinline __attribute__((noinline))
#define __noreturn __attribute__((noreturn))
#define CHAR_BIT 8
/* Represents true-or-false values */
typedef long long bool;
/* Explicitly-sized versions of integer types */
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
/* *
* Pointers and addresses are 32 bits long.
* We use pointer types to represent addresses,
* uintptr_t to represent the numerical values of addresses.
* */
typedef int64_t intptr_t;
typedef uint64_t uintptr_t;
/* size_t is used for memory object sizes */
typedef uintptr_t size_t;
/* off_t is used for file offsets and lengths */
typedef intptr_t off_t;
/* used for page numbers */
typedef size_t ppn_t;
/* *
* Rounding operations (efficient when n is a power of 2)
* Round down to the nearest multiple of n
* */
#define ROUNDDOWN(a, n) ({ \
size_t __a = (size_t)(a); \
(typeof(a))(__a - __a % (n)); \
})
/* Round up to the nearest multiple of n */
#define ROUNDUP(a, n) ({ \
size_t __n = (size_t)(n); \
(typeof(a))(ROUNDDOWN((size_t)(a) + __n - 1, __n)); \
})
/* Round up the result of dividing of n */
#define ROUNDUP_DIV(a, n) ({ \
uint64_t __n = (uint64_t)(n); \
(typeof(a))(((a) + __n - 1) / __n); \
})
/* Return the offset of 'member' relative to the beginning of a struct type */
#define offsetof(type, member) \
((size_t)(&((type *)0)->member))
/* *
* to_struct - get the struct from a ptr
* @ptr: a struct pointer of member
* @type: the type of the struct this is embedded in
* @member: the name of the member within the struct
* */
#define to_struct(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
#endif /* !__LIBS_DEFS_H__ */

@ -0,0 +1,48 @@
#ifndef __LIBS_ELF_H__
#define __LIBS_ELF_H__
#include <defs.h>
#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian
/* file header */
struct elfhdr {
uint32_t e_magic; // must equal ELF_MAGIC
uint8_t e_elf[12];
uint16_t e_type; // 1=relocatable, 2=executable, 3=shared object, 4=core image
uint16_t e_machine; // 3=x86, 4=68K, etc.
uint32_t e_version; // file version, always 1
uint64_t e_entry; // entry point if executable
uint64_t e_phoff; // file position of program header or 0
uint64_t e_shoff; // file position of section header or 0
uint32_t e_flags; // architecture-specific flags, usually 0
uint16_t e_ehsize; // size of this elf header
uint16_t e_phentsize; // size of an entry in program header
uint16_t e_phnum; // number of entries in program header or 0
uint16_t e_shentsize; // size of an entry in section header
uint16_t e_shnum; // number of entries in section header or 0
uint16_t e_shstrndx; // section number that contains section name strings
};
/* program section header */
struct proghdr {
uint32_t p_type; // loadable code or data, dynamic linking info,etc.
uint32_t p_flags; // read/write/execute bits
uint64_t p_offset; // file offset of segment
uint64_t p_va; // virtual address to map segment
uint64_t p_pa; // physical address, not used
uint64_t p_filesz; // size of segment in file
uint64_t p_memsz; // size of segment in memory (bigger if contains bss
uint64_t p_align; // required alignment, invariably hardware page size
};
/* values for Proghdr::p_type */
#define ELF_PT_LOAD 1
/* flag bits for Proghdr::p_flags */
#define ELF_PF_X 1
#define ELF_PF_W 2
#define ELF_PF_R 4
#endif /* !__LIBS_ELF_H__ */

@ -0,0 +1,8 @@
.text
.globl _start
_start:
# call user-program function
ldr x0, [sp]
add x1, sp, #8
bl umain
1: b 1b

@ -5,7 +5,7 @@
#include <unistd.h> #include <unistd.h>
struct dirent { struct dirent {
off_t offset; int32_t offset;
char name[FS_MAX_FNAME_LEN + 1]; char name[FS_MAX_FNAME_LEN + 1];
}; };

@ -5,9 +5,9 @@
struct stat { struct stat {
uint32_t st_mode; // protection mode and file type uint32_t st_mode; // protection mode and file type
size_t st_nlinks; // number of hard links uint32_t st_nlinks; // number of hard links
size_t st_blocks; // number of blocks file is using uint32_t st_blocks; // number of blocks file is using
size_t st_size; // file size (bytes) uint32_t st_size; // file size (bytes)
}; };
#define S_IFMT 070000 // mask for type of file #define S_IFMT 070000 // mask for type of file

@ -78,7 +78,7 @@ readline(const char *prompt) {
i --; i --;
} }
else if (c == '\n' || c == '\r') { else if (c == '\n' || c == '\r') {
putc(c); putc('\n');
buffer[i] = '\0'; buffer[i] = '\0';
break; break;
} }

@ -12,10 +12,10 @@ static inline int
syscall(int num, ...) { syscall(int num, ...) {
va_list ap; va_list ap;
va_start(ap, num); va_start(ap, num);
uint32_t a[MAX_ARGS]; size_t a[MAX_ARGS];
int i, ret; int i, ret;
for (i = 0; i < MAX_ARGS; i ++) { for (i = 0; i < MAX_ARGS; i ++) {
a[i] = va_arg(ap, uint32_t); a[i] = va_arg(ap, size_t);
} }
va_end(ap); va_end(ap);
@ -50,6 +50,25 @@ syscall(int num, ...) {
"m" (a[4]) "m" (a[4])
: "memory" : "memory"
); );
#elif defined(__aarch64__)
asm volatile (
"ldr w8, %1\n"
"ldr x0, %2\n"
"ldr x1, %3\n"
"ldr x2, %4\n"
"ldr x3, %5\n"
"ldr x4, %6\n"
"svc 0\n"
"str w0, %0"
: "=m" (ret)
: "m" (num),
"m" (a[0]),
"m" (a[1]),
"m" (a[2]),
"m" (a[3]),
"m" (a[4])
: "cc", "memory"
);
#endif #endif
return ret; return ret;
} }

@ -7,10 +7,11 @@ int main(int argc, char *argv[]);
static int static int
initfd(int fd2, const char *path, uint32_t open_flags) { initfd(int fd2, const char *path, uint32_t open_flags) {
int fd1, ret; int fd1;
if ((fd1 = open(path, open_flags)) < 0) { if ((fd1 = open(path, open_flags)) < 0) {
return fd1; return fd1;
} }
int ret = fd1;
if (fd1 != fd2) { if (fd1 != fd2) {
close(fd2); close(fd2);
ret = dup2(fd1, fd2); ret = dup2(fd1, fd2);

Loading…
Cancel
Save