todo
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#define ZINNIA_ARCHCTL_H
|
#define ZINNIA_ARCHCTL_H
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
|
#include <zinnia/syscall.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -19,7 +20,9 @@ typedef enum {
|
|||||||
} zn_archctl_t;
|
} zn_archctl_t;
|
||||||
|
|
||||||
// Performs an architecture-dependent operation identified by `op`.
|
// Performs an architecture-dependent operation identified by `op`.
|
||||||
zn_status_t zn_archctl(zn_archctl_t op, void* value);
|
static inline zn_status_t zn_archctl(zn_archctl_t op, void* value) {
|
||||||
|
return zn_syscall2(op, value, ZN_SYSCALL_ARCHCTL);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <zinnia/handle.h>
|
#include <zinnia/handle.h>
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
|
#include <zinnia/syscall.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -17,20 +18,28 @@ enum zn_channel_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Creates a new channel.
|
// Creates a new channel.
|
||||||
zn_status_t zn_channel_create(enum zn_channel_flags flags, zn_handle_t* endpoint0, zn_handle_t* endpoint1);
|
static inline zn_status_t zn_channel_create(
|
||||||
|
enum zn_channel_flags flags,
|
||||||
|
zn_handle_t* endpoint0,
|
||||||
|
zn_handle_t* endpoint1
|
||||||
|
) {
|
||||||
|
return zn_syscall3(flags, endpoint0, endpoint1, ZN_SYSCALL_CHANNEL_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
// Notifies the peer that there is new data available.
|
// Notifies the peer that there is new data available.
|
||||||
// The kernel only copies the first `num_handles` handles and `num_bytes` bytes.
|
// The kernel only copies the first `num_handles` handles and `num_bytes` bytes.
|
||||||
zn_status_t zn_channel_write(
|
static inline zn_status_t zn_channel_write(
|
||||||
zn_handle_t channel,
|
zn_handle_t channel,
|
||||||
const zn_handle_t* handles,
|
const zn_handle_t* handles,
|
||||||
const void* bytes,
|
const void* bytes,
|
||||||
size_t num_handles,
|
size_t num_handles,
|
||||||
size_t num_bytes
|
size_t num_bytes
|
||||||
);
|
) {
|
||||||
|
return zn_syscall5(channel, handles, bytes, num_handles, num_bytes, ZN_SYSCALL_CHANNEL_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
// Waits for a new message to appear in the channel.
|
// Waits for a new message to appear in the channel.
|
||||||
zn_status_t zn_channel_read(
|
static inline zn_status_t zn_channel_read(
|
||||||
zn_handle_t channel,
|
zn_handle_t channel,
|
||||||
zn_handle_t* handles,
|
zn_handle_t* handles,
|
||||||
void* bytes,
|
void* bytes,
|
||||||
@@ -38,7 +47,18 @@ zn_status_t zn_channel_read(
|
|||||||
size_t num_bytes,
|
size_t num_bytes,
|
||||||
size_t* read_handles,
|
size_t* read_handles,
|
||||||
size_t* read_bytes
|
size_t* read_bytes
|
||||||
|
) {
|
||||||
|
return zn_syscall7(
|
||||||
|
channel,
|
||||||
|
handles,
|
||||||
|
bytes,
|
||||||
|
num_handles,
|
||||||
|
num_bytes,
|
||||||
|
read_handles,
|
||||||
|
read_bytes,
|
||||||
|
ZN_SYSCALL_CHANNEL_READ
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#define ZINNIA_FUTEX_H
|
#define ZINNIA_FUTEX_H
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
|
#include <zinnia/syscall.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -12,10 +13,14 @@ extern "C" {
|
|||||||
|
|
||||||
// Blocks the calling thread if *addr == expected.
|
// Blocks the calling thread if *addr == expected.
|
||||||
// Returns immediately if the value at addr has changed.
|
// Returns immediately if the value at addr has changed.
|
||||||
zn_status_t zn_futex_wait(int32_t* addr, int32_t expected);
|
static inline zn_status_t zn_futex_wait(int32_t* addr, int32_t expected) {
|
||||||
|
return zn_syscall2(addr, expected, ZN_SYSCALL_FUTEX_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
// Wakes up to `count` threads waiting on the given futex address.
|
// Wakes up to `count` threads waiting on the given futex address.
|
||||||
zn_status_t zn_futex_wake(int32_t* addr, int32_t count);
|
static inline zn_status_t zn_futex_wake(int32_t* addr, int32_t count) {
|
||||||
|
return zn_syscall2(addr, count, ZN_SYSCALL_FUTEX_WAKE);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <zinnia/rights.h>
|
#include <zinnia/rights.h>
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
|
#include <zinnia/syscall.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -21,16 +22,22 @@ typedef int32_t zn_handle_t;
|
|||||||
#define ZN_HANDLE_ZERO_VMO ((zn_handle_t)(-4))
|
#define ZN_HANDLE_ZERO_VMO ((zn_handle_t)(-4))
|
||||||
|
|
||||||
// Checks an object handle for validity.
|
// Checks an object handle for validity.
|
||||||
zn_status_t zn_handle_validate(zn_handle_t handle);
|
zn_status_t zn_handle_validate(zn_handle_t handle) {
|
||||||
|
return zn_syscall1(handle, ZN_SYSCALL_HANDLE_VALIDATE);
|
||||||
|
}
|
||||||
|
|
||||||
// Drops an object handle. All further references using this handle are invalid.
|
// Drops an object handle. All further references using this handle are invalid.
|
||||||
// The numerical value may become valid again, but it is an error to keep using it.
|
// The numerical value may become valid again, but it is an error to keep using it.
|
||||||
// The underlying object gets freed only once no other handle references it.
|
// The underlying object gets freed only once no other handle references it.
|
||||||
zn_status_t zn_handle_drop(zn_handle_t handle);
|
zn_status_t zn_handle_drop(zn_handle_t handle) {
|
||||||
|
return zn_syscall1(handle, ZN_SYSCALL_HANDLE_DROP);
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a new handle pointing to the same object as pointed to
|
// Creates a new handle pointing to the same object as pointed to
|
||||||
// by the original handle. The new handle may obtain new rights.
|
// by the original handle. The new handle may obtain new rights.
|
||||||
zn_status_t zn_handle_clone(zn_handle_t handle, zn_rights_t cloned_rights, zn_handle_t* cloned);
|
zn_status_t zn_handle_clone(zn_handle_t handle, zn_rights_t cloned_rights, zn_handle_t* cloned) {
|
||||||
|
return zn_syscall3(handle, cloned_rights, cloned, ZN_SYSCALL_HANDLE_CLONE);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-5
@@ -32,23 +32,31 @@ enum zn_vm_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Creates a new virtual memory object.
|
// Creates a new virtual memory object.
|
||||||
zn_status_t zn_vmo_create(size_t length, zn_handle_t* out);
|
static inline zn_status_t zn_vmo_create(size_t length, zn_handle_t* out) {
|
||||||
|
return zn_syscall2(length, out, ZN_SYSCALL_VMO_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a new virtual memory object which points to a contiguous phyiscal memory region.
|
// Creates a new virtual memory object which points to a contiguous phyiscal memory region.
|
||||||
zn_status_t zn_vmo_create_phys(uintptr_t phys_addr, size_t length, zn_handle_t* out);
|
static inline zn_status_t zn_vmo_create_phys(uintptr_t phys_addr, size_t length, zn_handle_t* out) {
|
||||||
|
return zn_syscall3(phys_addr, length, out, ZN_SYSCALL_VMO_CREATE_PHYS);
|
||||||
|
}
|
||||||
|
|
||||||
// Maps `bytes` of `vmo` at `vmo_offset` to `addr` in `vas`.
|
// Maps `bytes` of `vmo` at `vmo_offset` to `addr` in `vas`.
|
||||||
zn_status_t zn_vmo_map(
|
static inline zn_status_t zn_vmo_map(
|
||||||
zn_handle_t vmo,
|
zn_handle_t vmo,
|
||||||
zn_handle_t vas,
|
zn_handle_t vas,
|
||||||
uintptr_t vmo_offset,
|
uintptr_t vmo_offset,
|
||||||
uintptr_t* addr,
|
uintptr_t* addr,
|
||||||
size_t bytes,
|
size_t bytes,
|
||||||
enum zn_vm_flags flags
|
enum zn_vm_flags flags
|
||||||
);
|
) {
|
||||||
|
return zn_syscall6(vmo, vas, vmo_offset, addr, bytes, flags, ZN_SYSCALL_VMO_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a new virtual address space.
|
// Creates a new virtual address space.
|
||||||
zn_status_t zn_vas_create(zn_handle_t* out);
|
static inline zn_status_t zn_vas_create(zn_handle_t* out) {
|
||||||
|
return zn_syscall1(out, ZN_SYSCALL_VAS_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,15 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Creates a new namespace.
|
// Creates a new namespace.
|
||||||
zn_status_t zn_ns_create(zn_handle_t* out);
|
static inline zn_status_t zn_ns_create(zn_handle_t* out) {
|
||||||
|
return ZN_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
// Moves a handle to another namespace.
|
// Moves a handle to another namespace.
|
||||||
// The handle must have the `ZN_RIGHT_MOVE` right.
|
// The handle must have the `ZN_RIGHT_MOVE` right.
|
||||||
zn_status_t zn_ns_move(zn_handle_t handle, zn_handle_t target_ns);
|
static inline zn_status_t zn_ns_move(zn_handle_t handle, zn_handle_t target_ns) {
|
||||||
|
return ZN_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum {
|
#define ZN_RANDOM_MAX_ENTROPY 0x1000
|
||||||
ZN_RANDOM_MAX_ENTROPY = 0x1000
|
|
||||||
};
|
|
||||||
|
|
||||||
// Stores random bytes in a buffer.
|
// Stores random bytes in a buffer.
|
||||||
zn_status_t zn_random_get(void* addr, size_t len);
|
zn_status_t zn_random_get(void* addr, size_t len);
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#ifndef ZINNIA_RESOURCE_H
|
||||||
|
#define ZINNIA_RESOURCE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -36,8 +36,6 @@ typedef enum {
|
|||||||
ZN_ERR_ALREADY_EXISTS = -11,
|
ZN_ERR_ALREADY_EXISTS = -11,
|
||||||
} zn_status_t;
|
} zn_status_t;
|
||||||
|
|
||||||
const char* zn_status_to_string(zn_status_t err);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,236 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#ifndef ZINNIA_SYSCALL_H
|
||||||
|
#define ZINNIA_SYSCALL_H
|
||||||
|
|
||||||
|
#include <zinnia/status.h>
|
||||||
|
#include <zinnia/syscall_numbers.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uintptr_t zn_arg_t;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
#define ASM_REG_NUM "rax"
|
||||||
|
#define ASM_REG_RET "rax"
|
||||||
|
#define ASM_REG_A0 "rdi"
|
||||||
|
#define ASM_REG_A1 "rsi"
|
||||||
|
#define ASM_REG_A2 "rdx"
|
||||||
|
#define ASM_REG_A3 "r9"
|
||||||
|
#define ASM_REG_A4 "r8"
|
||||||
|
#define ASM_REG_A5 "r10"
|
||||||
|
#define ASM_REG_A6 "r12"
|
||||||
|
#define ASM_REG_A7 "r13"
|
||||||
|
#define ASM_SYSCALL "syscall"
|
||||||
|
#define ASM_CLOBBER "rcx", "r11"
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#define ASM_REG_NUM "x8"
|
||||||
|
#define ASM_REG_RET "x0"
|
||||||
|
#define ASM_REG_A0 "x0"
|
||||||
|
#define ASM_REG_A1 "x1"
|
||||||
|
#define ASM_REG_A2 "x2"
|
||||||
|
#define ASM_REG_A3 "x3"
|
||||||
|
#define ASM_REG_A4 "x4"
|
||||||
|
#define ASM_REG_A5 "x5"
|
||||||
|
#define ASM_REG_A6 "x6"
|
||||||
|
#define ASM_REG_A7 "x7"
|
||||||
|
#define ASM_SYSCALL "svc 0"
|
||||||
|
#define ASM_CLOBBER
|
||||||
|
#elif defined(__riscv) && (__riscv_xlen == 64)
|
||||||
|
#define ASM_REG_NUM "t3"
|
||||||
|
#define ASM_REG_RET "a0"
|
||||||
|
#define ASM_REG_A0 "a0"
|
||||||
|
#define ASM_REG_A1 "a1"
|
||||||
|
#define ASM_REG_A2 "a2"
|
||||||
|
#define ASM_REG_A3 "a3"
|
||||||
|
#define ASM_REG_A4 "a4"
|
||||||
|
#define ASM_REG_A5 "a5"
|
||||||
|
#define ASM_REG_A5 "a6"
|
||||||
|
#define ASM_REG_A5 "a7"
|
||||||
|
#define ASM_SYSCALL "ecall"
|
||||||
|
#define ASM_CLOBBER
|
||||||
|
#elif defined(__loongarch64)
|
||||||
|
#define ASM_REG_NUM "a7"
|
||||||
|
#define ASM_REG_RET "a0"
|
||||||
|
#define ASM_REG_A0 "a0"
|
||||||
|
#define ASM_REG_A1 "a1"
|
||||||
|
#define ASM_REG_A2 "a2"
|
||||||
|
#define ASM_REG_A3 "a3"
|
||||||
|
#define ASM_REG_A4 "a4"
|
||||||
|
#define ASM_REG_A5 "a5"
|
||||||
|
// TODO: Define ABI
|
||||||
|
#define ASM_REG_A6 TODO
|
||||||
|
#define ASM_REG_A7 TODO
|
||||||
|
#define ASM_SYSCALL "syscall 0"
|
||||||
|
#define ASM_CLOBBER
|
||||||
|
#else
|
||||||
|
#error "Unsupported architecture!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall0(zn_syscall_t num) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
asm volatile(ASM_SYSCALL : "=r"(value) : "r"(rnum) : "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall1(zn_arg_t a0, zn_syscall_t num) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
register zn_arg_t r0 asm(ASM_REG_A0) = a0;
|
||||||
|
asm volatile(ASM_SYSCALL : "=r"(value) : "r"(rnum), "r"(r0) : "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define zn_syscall1(a0, num) zn_syscall1((zn_arg_t)a0, num)
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall2(zn_arg_t a0, zn_arg_t a1, zn_syscall_t num) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
register zn_arg_t r0 asm(ASM_REG_A0) = a0;
|
||||||
|
register zn_arg_t r1 asm(ASM_REG_A1) = a1;
|
||||||
|
asm volatile(ASM_SYSCALL : "=r"(value) : "r"(rnum), "r"(r0), "r"(r1) : "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define zn_syscall2(a0, a1, num) zn_syscall2((zn_arg_t)a0, (zn_arg_t)a1, num)
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall3(zn_arg_t a0, zn_arg_t a1, zn_arg_t a2, zn_syscall_t num) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
register zn_arg_t r0 asm(ASM_REG_A0) = a0;
|
||||||
|
register zn_arg_t r1 asm(ASM_REG_A1) = a1;
|
||||||
|
register zn_arg_t r2 asm(ASM_REG_A2) = a2;
|
||||||
|
asm volatile(ASM_SYSCALL : "=r"(value) : "r"(rnum), "r"(r0), "r"(r1), "r"(r2) : "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define zn_syscall3(a0, a1, a2, num) zn_syscall3((zn_arg_t)a0, (zn_arg_t)a1, (zn_arg_t)a2, num)
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall4(zn_arg_t a0, zn_arg_t a1, zn_arg_t a2, zn_arg_t a3, zn_syscall_t num) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
register zn_arg_t r0 asm(ASM_REG_A0) = a0;
|
||||||
|
register zn_arg_t r1 asm(ASM_REG_A1) = a1;
|
||||||
|
register zn_arg_t r2 asm(ASM_REG_A2) = a2;
|
||||||
|
register zn_arg_t r3 asm(ASM_REG_A3) = a3;
|
||||||
|
asm volatile(ASM_SYSCALL : "=r"(value) : "r"(rnum), "r"(r0), "r"(r1), "r"(r2), "r"(r3) : "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define zn_syscall4(a0, a1, a2, a3, num) zn_syscall4((zn_arg_t)a0, (zn_arg_t)a1, (zn_arg_t)a2, (zn_arg_t)a3, num)
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall5(
|
||||||
|
zn_arg_t a0,
|
||||||
|
zn_arg_t a1,
|
||||||
|
zn_arg_t a2,
|
||||||
|
zn_arg_t a3,
|
||||||
|
zn_arg_t a4,
|
||||||
|
zn_syscall_t num
|
||||||
|
) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
register zn_arg_t r0 asm(ASM_REG_A0) = a0;
|
||||||
|
register zn_arg_t r1 asm(ASM_REG_A1) = a1;
|
||||||
|
register zn_arg_t r2 asm(ASM_REG_A2) = a2;
|
||||||
|
register zn_arg_t r3 asm(ASM_REG_A3) = a3;
|
||||||
|
register zn_arg_t r4 asm(ASM_REG_A4) = a4;
|
||||||
|
asm volatile(ASM_SYSCALL
|
||||||
|
: "=r"(value)
|
||||||
|
: "r"(rnum), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
|
||||||
|
: "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define zn_syscall5(a0, a1, a2, a3, a4, num) \
|
||||||
|
zn_syscall5((zn_arg_t)a0, (zn_arg_t)a1, (zn_arg_t)a2, (zn_arg_t)a3, (zn_arg_t)a4, num)
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall6(
|
||||||
|
zn_arg_t a0,
|
||||||
|
zn_arg_t a1,
|
||||||
|
zn_arg_t a2,
|
||||||
|
zn_arg_t a3,
|
||||||
|
zn_arg_t a4,
|
||||||
|
zn_arg_t a5,
|
||||||
|
zn_syscall_t num
|
||||||
|
) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
register zn_arg_t r0 asm(ASM_REG_A0) = a0;
|
||||||
|
register zn_arg_t r1 asm(ASM_REG_A1) = a1;
|
||||||
|
register zn_arg_t r2 asm(ASM_REG_A2) = a2;
|
||||||
|
register zn_arg_t r3 asm(ASM_REG_A3) = a3;
|
||||||
|
register zn_arg_t r4 asm(ASM_REG_A4) = a4;
|
||||||
|
register zn_arg_t r5 asm(ASM_REG_A5) = a5;
|
||||||
|
asm volatile(ASM_SYSCALL
|
||||||
|
: "=r"(value)
|
||||||
|
: "r"(rnum), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
|
||||||
|
: "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define zn_syscall6(a0, a1, a2, a3, a4, a5, num) \
|
||||||
|
zn_syscall6((zn_arg_t)a0, (zn_arg_t)a1, (zn_arg_t)a2, (zn_arg_t)a3, (zn_arg_t)a4, (zn_arg_t)a5, num)
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall7(
|
||||||
|
zn_arg_t a0,
|
||||||
|
zn_arg_t a1,
|
||||||
|
zn_arg_t a2,
|
||||||
|
zn_arg_t a3,
|
||||||
|
zn_arg_t a4,
|
||||||
|
zn_arg_t a5,
|
||||||
|
zn_arg_t a6,
|
||||||
|
zn_syscall_t num
|
||||||
|
) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
register zn_arg_t r0 asm(ASM_REG_A0) = a0;
|
||||||
|
register zn_arg_t r1 asm(ASM_REG_A1) = a1;
|
||||||
|
register zn_arg_t r2 asm(ASM_REG_A2) = a2;
|
||||||
|
register zn_arg_t r3 asm(ASM_REG_A3) = a3;
|
||||||
|
register zn_arg_t r4 asm(ASM_REG_A4) = a4;
|
||||||
|
register zn_arg_t r5 asm(ASM_REG_A5) = a5;
|
||||||
|
register zn_arg_t r6 asm(ASM_REG_A6) = a6;
|
||||||
|
asm volatile(ASM_SYSCALL
|
||||||
|
: "=r"(value)
|
||||||
|
: "r"(rnum), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6)
|
||||||
|
: "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define zn_syscall7(a0, a1, a2, a3, a4, a5, a6, num) \
|
||||||
|
zn_syscall7((zn_arg_t)a0, (zn_arg_t)a1, (zn_arg_t)a2, (zn_arg_t)a3, (zn_arg_t)a4, (zn_arg_t)a5, (zn_arg_t)a6, num)
|
||||||
|
|
||||||
|
static inline zn_status_t zn_syscall8(
|
||||||
|
zn_arg_t a0,
|
||||||
|
zn_arg_t a1,
|
||||||
|
zn_arg_t a2,
|
||||||
|
zn_arg_t a3,
|
||||||
|
zn_arg_t a4,
|
||||||
|
zn_arg_t a5,
|
||||||
|
zn_arg_t a6,
|
||||||
|
zn_arg_t a7,
|
||||||
|
zn_syscall_t num
|
||||||
|
) {
|
||||||
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
|
register zn_arg_t r0 asm(ASM_REG_A0) = a0;
|
||||||
|
register zn_arg_t r1 asm(ASM_REG_A1) = a1;
|
||||||
|
register zn_arg_t r2 asm(ASM_REG_A2) = a2;
|
||||||
|
register zn_arg_t r3 asm(ASM_REG_A3) = a3;
|
||||||
|
register zn_arg_t r4 asm(ASM_REG_A4) = a4;
|
||||||
|
register zn_arg_t r5 asm(ASM_REG_A5) = a5;
|
||||||
|
register zn_arg_t r6 asm(ASM_REG_A6) = a6;
|
||||||
|
register zn_arg_t r7 asm(ASM_REG_A7) = a7;
|
||||||
|
asm volatile(ASM_SYSCALL
|
||||||
|
: "=r"(value)
|
||||||
|
: "r"(rnum), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
|
||||||
|
: "memory", ASM_CLOBBER);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
#define zn_syscall8(a0, a1, a2, a3, a4, a5, a6, a7, num) \
|
||||||
|
zn_syscall8( \
|
||||||
|
(zn_arg_t)a0, \
|
||||||
|
(zn_arg_t)a1, \
|
||||||
|
(zn_arg_t)a2, \
|
||||||
|
(zn_arg_t)a3, \
|
||||||
|
(zn_arg_t)a4, \
|
||||||
|
(zn_arg_t)a5, \
|
||||||
|
(zn_arg_t)a6, \
|
||||||
|
(zn_arg_t)a7, \
|
||||||
|
num \
|
||||||
|
)
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#ifndef ZINNIA_SYSCALL_NUMBERS_H
|
||||||
|
#define ZINNIA_SYSCALL_NUMBERS_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ZN_SYSCALL_LOG,
|
||||||
|
ZN_SYSCALL_ARCHCTL,
|
||||||
|
ZN_SYSCALL_PAGE_SIZE,
|
||||||
|
ZN_SYSCALL_TIME,
|
||||||
|
|
||||||
|
ZN_SYSCALL_HANDLE_VALIDATE,
|
||||||
|
ZN_SYSCALL_HANDLE_DROP,
|
||||||
|
ZN_SYSCALL_HANDLE_CLONE,
|
||||||
|
|
||||||
|
ZN_SYSCALL_VAS_CREATE,
|
||||||
|
|
||||||
|
ZN_SYSCALL_VMO_CREATE,
|
||||||
|
ZN_SYSCALL_VMO_CREATE_PHYS,
|
||||||
|
ZN_SYSCALL_VMO_MAP,
|
||||||
|
|
||||||
|
ZN_SYSCALL_CHANNEL_CREATE,
|
||||||
|
ZN_SYSCALL_CHANNEL_WAIT,
|
||||||
|
ZN_SYSCALL_CHANNEL_READ,
|
||||||
|
ZN_SYSCALL_CHANNEL_WRITE,
|
||||||
|
|
||||||
|
ZN_SYSCALL_THREAD_CREATE,
|
||||||
|
ZN_SYSCALL_THREAD_START,
|
||||||
|
ZN_SYSCALL_THREAD_EXIT,
|
||||||
|
|
||||||
|
ZN_SYSCALL_RANDOM_GET,
|
||||||
|
ZN_SYSCALL_RANDOM_ENTROPY,
|
||||||
|
|
||||||
|
ZN_SYSCALL_FUTEX_WAIT,
|
||||||
|
ZN_SYSCALL_FUTEX_WAKE,
|
||||||
|
} zn_syscall_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
#define ZINNIA_SYSTEM_H
|
#define ZINNIA_SYSTEM_H
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -20,9 +19,6 @@ size_t zn_page_size();
|
|||||||
|
|
||||||
zn_status_t zn_powerctl();
|
zn_status_t zn_powerctl();
|
||||||
|
|
||||||
// Returns the current timestamp in nanoseconds.
|
|
||||||
uint64_t zn_time();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#include <zinnia/archctl.h>
|
|
||||||
#include <kernel/vdso.h>
|
|
||||||
|
|
||||||
zn_status_t zn_archctl(zn_archctl_t op, void* value) {
|
|
||||||
return zn_syscall2(op, value, ZN_SYSCALL_ARCHCTL);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_archctl);
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#include <zinnia/channel.h>
|
|
||||||
#include <kernel/vdso.h>
|
|
||||||
|
|
||||||
zn_status_t zn_channel_create(enum zn_channel_flags flags, zn_handle_t* endpoint0, zn_handle_t* endpoint1) {
|
|
||||||
return zn_syscall3(flags, endpoint0, endpoint1, ZN_SYSCALL_CHANNEL_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_channel_create);
|
|
||||||
|
|
||||||
zn_status_t zn_channel_write(
|
|
||||||
zn_handle_t channel,
|
|
||||||
const zn_handle_t* handles,
|
|
||||||
const void* bytes,
|
|
||||||
size_t num_handles,
|
|
||||||
size_t num_bytes
|
|
||||||
) {
|
|
||||||
return zn_syscall5(channel, handles, bytes, num_handles, num_bytes, ZN_SYSCALL_CHANNEL_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_channel_write);
|
|
||||||
|
|
||||||
zn_status_t zn_channel_read(
|
|
||||||
zn_handle_t channel,
|
|
||||||
zn_handle_t* handles,
|
|
||||||
void* bytes,
|
|
||||||
size_t num_handles,
|
|
||||||
size_t num_bytes,
|
|
||||||
size_t* read_handles,
|
|
||||||
size_t* read_bytes
|
|
||||||
) {
|
|
||||||
return zn_syscall7(
|
|
||||||
channel,
|
|
||||||
handles,
|
|
||||||
bytes,
|
|
||||||
num_handles,
|
|
||||||
num_bytes,
|
|
||||||
read_handles,
|
|
||||||
read_bytes,
|
|
||||||
ZN_SYSCALL_CHANNEL_READ
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_channel_read);
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#include <zinnia/futex.h>
|
|
||||||
#include <kernel/vdso.h>
|
|
||||||
|
|
||||||
zn_status_t zn_futex_wait(int32_t* addr, int32_t expected) {
|
|
||||||
return zn_syscall2(addr, expected, ZN_SYSCALL_FUTEX_WAIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_futex_wait);
|
|
||||||
|
|
||||||
zn_status_t zn_futex_wake(int32_t* addr, int32_t count) {
|
|
||||||
return zn_syscall2(addr, count, ZN_SYSCALL_FUTEX_WAKE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_futex_wake);
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#include <zinnia/handle.h>
|
|
||||||
#include <kernel/vdso.h>
|
|
||||||
|
|
||||||
zn_status_t zn_handle_validate(zn_handle_t handle) {
|
|
||||||
return zn_syscall1(handle, ZN_SYSCALL_HANDLE_VALIDATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_handle_validate);
|
|
||||||
|
|
||||||
zn_status_t zn_handle_drop(zn_handle_t handle) {
|
|
||||||
return zn_syscall1(handle, ZN_SYSCALL_HANDLE_DROP);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_handle_drop);
|
|
||||||
|
|
||||||
zn_status_t zn_handle_clone(zn_handle_t handle, zn_rights_t cloned_rights, zn_handle_t* cloned) {
|
|
||||||
return zn_syscall3(handle, cloned_rights, cloned, ZN_SYSCALL_HANDLE_CLONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_handle_clone);
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#include <zinnia/mem.h>
|
|
||||||
#include <kernel/vdso.h>
|
|
||||||
|
|
||||||
zn_status_t zn_vmo_create(size_t length, zn_handle_t* out) {
|
|
||||||
return zn_syscall2(length, out, ZN_SYSCALL_VMO_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_vmo_create);
|
|
||||||
|
|
||||||
zn_status_t zn_vmo_create_phys(uintptr_t phys_addr, size_t length, zn_handle_t* out) {
|
|
||||||
return zn_syscall3(phys_addr, length, out, ZN_SYSCALL_VMO_CREATE_PHYS);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_vmo_create_phys);
|
|
||||||
|
|
||||||
zn_status_t zn_vmo_map(
|
|
||||||
zn_handle_t vmo,
|
|
||||||
zn_handle_t vas,
|
|
||||||
uintptr_t vmo_offset,
|
|
||||||
uintptr_t* addr,
|
|
||||||
size_t bytes,
|
|
||||||
enum zn_vm_flags flags
|
|
||||||
) {
|
|
||||||
return zn_syscall6(vmo, vas, vmo_offset, addr, bytes, flags, ZN_SYSCALL_VMO_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_vmo_map);
|
|
||||||
|
|
||||||
zn_status_t zn_vas_create(zn_handle_t* out) {
|
|
||||||
return zn_syscall1(out, ZN_SYSCALL_VAS_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_vas_create);
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#include <zinnia/namespace.h>
|
|
||||||
#include <kernel/vdso.h>
|
|
||||||
|
|
||||||
zn_status_t zn_ns_create(zn_handle_t* out) {
|
|
||||||
return ZN_ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_ns_create);
|
|
||||||
|
|
||||||
zn_status_t zn_ns_move(zn_handle_t handle, zn_handle_t target_ns) {
|
|
||||||
return ZN_ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_ns_move);
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
|
||||||
#include <kernel/vdso.h>
|
|
||||||
|
|
||||||
const char* zn_status_to_string(zn_status_t err) {
|
|
||||||
switch (err) {
|
|
||||||
case ZN_OK:
|
|
||||||
return "No error (OK)";
|
|
||||||
case ZN_ERR_INTERNAL:
|
|
||||||
return "An internal error occured (INTERNAL)";
|
|
||||||
case ZN_ERR_BAD_SYSCALL:
|
|
||||||
return "Syscall number is not a recognized syscall (BAD_SYSCALL)";
|
|
||||||
case ZN_ERR_UNSUPPORTED:
|
|
||||||
return "This operation is not supported or implemented yet (UNSUPPORTED)";
|
|
||||||
case ZN_ERR_NO_MEMORY:
|
|
||||||
return "System does not have enough free memory for this operation (NO_MEMORY)";
|
|
||||||
case ZN_ERR_NO_HANDLES:
|
|
||||||
return "Process can not own any more handles (NO_HANDLES)";
|
|
||||||
case ZN_ERR_INVALID:
|
|
||||||
return "One or more of the provided arguments is not valid (INVALID)";
|
|
||||||
case ZN_ERR_BAD_RANGE:
|
|
||||||
return "Argument is outside of the range for valid values (BAD_RANGE)";
|
|
||||||
case ZN_ERR_BAD_HANDLE:
|
|
||||||
return "Object handle does not name a valid object (BAD_HANDLE)";
|
|
||||||
case ZN_ERR_BAD_PERMS:
|
|
||||||
return "Object has insufficient permissions for this operation (BAD_PERMS)";
|
|
||||||
case ZN_ERR_BAD_BUFFER:
|
|
||||||
return "Buffer is not large enough or doesn't point to a valid memory region (BAD_BUFFER)";
|
|
||||||
case ZN_ERR_ALREADY_EXISTS:
|
|
||||||
return "The resource already exists (ALREADY_EXISTS)";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Unknown error code";
|
|
||||||
}
|
|
||||||
|
|
||||||
VDSO_SYMBOL(zn_status_to_string);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
libfreestanding = static_library(
|
|
||||||
'freestanding',
|
|
||||||
sources: [
|
|
||||||
'entry.c',
|
|
||||||
'vdso.c',
|
|
||||||
],
|
|
||||||
include_directories: common_includes,
|
|
||||||
)
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
#include <zinnia/archctl.h>
|
|
||||||
#include <zinnia/channel.h>
|
|
||||||
#include <zinnia/futex.h>
|
|
||||||
#include <zinnia/handle.h>
|
|
||||||
#include <zinnia/mem.h>
|
|
||||||
#include <zinnia/namespace.h>
|
|
||||||
#include <zinnia/random.h>
|
|
||||||
#include <zinnia/status.h>
|
|
||||||
#include <zinnia/system.h>
|
|
||||||
#include <zinnia/thread.h>
|
|
||||||
#include <common/elf.h>
|
|
||||||
#include <sys/auxv.h>
|
|
||||||
|
|
||||||
static uint8_t vdso_symbol_bind(uint8_t info) {
|
|
||||||
return ELF64_ST_BIND(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t vdso_symbol_type(uint8_t info) {
|
|
||||||
return ELF64_ST_TYPE(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vdso_info {
|
|
||||||
uintptr_t base;
|
|
||||||
const char* strings;
|
|
||||||
const struct elf64_sym* symbols;
|
|
||||||
size_t symbol_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool vdso_info_init(struct vdso_info* info) {
|
|
||||||
const uintptr_t base = getauxval(AT_SYSINFO_EHDR);
|
|
||||||
if (!base)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const struct elf64_ehdr* ehdr = (const void*)base;
|
|
||||||
if (ehdr->e_ident[EI_MAG0] != ELF_MAG[0] || ehdr->e_ident[EI_MAG1] != ELF_MAG[1] ||
|
|
||||||
ehdr->e_ident[EI_MAG2] != ELF_MAG[2] || ehdr->e_ident[EI_MAG3] != ELF_MAG[3] ||
|
|
||||||
ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
|
|
||||||
ehdr->e_machine != ELF_ARCH_MACHINE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const struct elf64_dyn* dynamic = nullptr;
|
|
||||||
for (size_t i = 0; i < ehdr->e_phnum; i++) {
|
|
||||||
const struct elf64_phdr* phdr = (const void*)(base + ehdr->e_phoff + (i * ehdr->e_phentsize));
|
|
||||||
if (phdr->p_type == PT_DYNAMIC) {
|
|
||||||
dynamic = (const void*)(base + phdr->p_vaddr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!dynamic)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const char* strings = nullptr;
|
|
||||||
const struct elf64_sym* symbols = nullptr;
|
|
||||||
const struct elf_hash* hash = nullptr;
|
|
||||||
|
|
||||||
for (const struct elf64_dyn* entry = dynamic; entry->d_tag != DT_NULL; entry++) {
|
|
||||||
switch (entry->d_tag) {
|
|
||||||
case DT_STRTAB:
|
|
||||||
strings = (const void*)(base + entry->d_un.d_ptr);
|
|
||||||
break;
|
|
||||||
case DT_SYMTAB:
|
|
||||||
symbols = (const void*)(base + entry->d_un.d_ptr);
|
|
||||||
break;
|
|
||||||
case DT_HASH:
|
|
||||||
hash = (const void*)(base + entry->d_un.d_ptr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strings || !symbols || !hash)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*info = (struct vdso_info){
|
|
||||||
.base = base,
|
|
||||||
.strings = strings,
|
|
||||||
.symbols = symbols,
|
|
||||||
.symbol_count = hash->n_chain,
|
|
||||||
};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* vdso_lookup(const char* name) {
|
|
||||||
struct vdso_info info;
|
|
||||||
if (!vdso_info_init(&info))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < info.symbol_count; i++) {
|
|
||||||
const struct elf64_sym* symbol = &info.symbols[i];
|
|
||||||
if (vdso_symbol_bind(symbol->st_info) != STB_GLOBAL || vdso_symbol_type(symbol->st_info) != STT_FUNC)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const char* symbol_name = info.strings + symbol->st_name;
|
|
||||||
const char* lhs = symbol_name;
|
|
||||||
const char* rhs = name;
|
|
||||||
while (*lhs && *lhs == *rhs) {
|
|
||||||
lhs++;
|
|
||||||
rhs++;
|
|
||||||
}
|
|
||||||
if (*lhs == 0 && *rhs == 0)
|
|
||||||
return (void*)(info.base + symbol->st_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VDSO_IFUNC(name) \
|
|
||||||
static typeof(name)* resolve_##name(void) { \
|
|
||||||
return (typeof(name)*)vdso_lookup("__vdso_" #name); \
|
|
||||||
} \
|
|
||||||
typeof(name) name __attribute__((ifunc("resolve_" #name)));
|
|
||||||
|
|
||||||
VDSO_IFUNC(zn_archctl);
|
|
||||||
VDSO_IFUNC(zn_channel_create);
|
|
||||||
VDSO_IFUNC(zn_channel_write);
|
|
||||||
VDSO_IFUNC(zn_channel_read);
|
|
||||||
VDSO_IFUNC(zn_futex_wait);
|
|
||||||
VDSO_IFUNC(zn_futex_wake);
|
|
||||||
VDSO_IFUNC(zn_handle_validate);
|
|
||||||
VDSO_IFUNC(zn_handle_drop);
|
|
||||||
VDSO_IFUNC(zn_handle_clone);
|
|
||||||
VDSO_IFUNC(zn_vmo_create);
|
|
||||||
VDSO_IFUNC(zn_vmo_create_phys);
|
|
||||||
VDSO_IFUNC(zn_vmo_map);
|
|
||||||
VDSO_IFUNC(zn_vas_create);
|
|
||||||
VDSO_IFUNC(zn_ns_create);
|
|
||||||
VDSO_IFUNC(zn_ns_move);
|
|
||||||
VDSO_IFUNC(zn_random_get);
|
|
||||||
VDSO_IFUNC(zn_random_entropy);
|
|
||||||
VDSO_IFUNC(zn_status_to_string);
|
|
||||||
VDSO_IFUNC(zn_log);
|
|
||||||
VDSO_IFUNC(zn_page_size);
|
|
||||||
VDSO_IFUNC(zn_powerctl);
|
|
||||||
VDSO_IFUNC(zn_time);
|
|
||||||
VDSO_IFUNC(zn_thread_create);
|
|
||||||
VDSO_IFUNC(zn_thread_start);
|
|
||||||
VDSO_IFUNC(zn_thread_exit);
|
|
||||||
@@ -1,3 +1 @@
|
|||||||
subdir('freestanding')
|
|
||||||
|
|
||||||
subdir('device')
|
subdir('device')
|
||||||
|
|||||||
Reference in New Issue
Block a user