vdso
This commit is contained in:
@@ -14,19 +14,19 @@
|
|||||||
#if defined(__has_builtin)
|
#if defined(__has_builtin)
|
||||||
#if __has_builtin(__builtin_types_compatible_p)
|
#if __has_builtin(__builtin_types_compatible_p)
|
||||||
// Get pointer to parent object given pointer to a struct or union member.
|
// Get pointer to parent object given pointer to a struct or union member.
|
||||||
#define CONTAINER_OF(ptr, type, member) \
|
#define containerof(ptr, type, member) \
|
||||||
({ \
|
({ \
|
||||||
_Static_assert( \
|
static_assert( \
|
||||||
__builtin_types_compatible_p(__typeof__(*(ptr)), __typeof__(((type*)0)->member)), \
|
__builtin_types_compatible_p(typeof(*(ptr)), typeof(((type*)0)->member)), \
|
||||||
"Incompatible types for CONTAINER_OF" \
|
"Incompatible types for containerof" \
|
||||||
); \
|
); \
|
||||||
(type*)((size_t)ptr - offsetof(type, member)); \
|
(type*)((size_t)ptr - offsetof(type, member)); \
|
||||||
})
|
})
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef CONTAINER_OF
|
#ifndef containerof
|
||||||
// Get pointer to parent object given pointer to a struct or union member.
|
// Get pointer to parent object given pointer to a struct or union member.
|
||||||
#define CONTAINER_OF(ptr, type, member) (type*)((size_t)ptr - offsetof(type, member))
|
#define containerof(ptr, type, member) (type*)((size_t)ptr - offsetof(type, member))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CONCAT(A, B) _CONCAT(A, B)
|
#define CONCAT(A, B) _CONCAT(A, B)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#define ZINNIA_ARCHCTL_H
|
#define ZINNIA_ARCHCTL_H
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_stubs.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -11,16 +10,14 @@ extern "C" {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
// Does nothing.
|
// Does nothing.
|
||||||
ZN_ARCHCTL_NONE = 0,
|
ZN_ARCHCTL_NONE = 0,
|
||||||
// On x86_64, sets the FSBASE MSR to the value.
|
// On x86_64, sets the FSBASE MSR.
|
||||||
ZN_ARCHCTL_SET_FSBASE = 1,
|
ZN_ARCHCTL_SET_FSBASE = 1,
|
||||||
// On x86_64, sets the GSBASE MSR to the value.
|
// On x86_64, sets the GSBASE MSR.
|
||||||
ZN_ARCHCTL_SET_GSBASE = 2,
|
ZN_ARCHCTL_SET_GSBASE = 2,
|
||||||
} zn_archctl_t;
|
} zn_archctl_t;
|
||||||
|
|
||||||
// Performs an architecture-dependent operation identified by `op`.
|
// Performs an architecture-dependent operation identified by `op`.
|
||||||
static inline zn_status_t zn_archctl(zn_archctl_t op, void* value) {
|
zn_status_t zn_archctl(zn_archctl_t op, void* value);
|
||||||
return zn_syscall2(op, value, ZN_SYSCALL_ARCHCTL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <zinnia/handle.h>
|
#include <zinnia/handle.h>
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_stubs.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -15,28 +14,20 @@ enum zn_channel_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Creates a new channel.
|
// Creates a new channel.
|
||||||
static inline zn_status_t zn_channel_create(
|
zn_status_t zn_channel_create(enum zn_channel_flags flags, zn_handle_t* endpoint0, zn_handle_t* endpoint1);
|
||||||
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.
|
||||||
static inline zn_status_t zn_channel_write(
|
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.
|
||||||
static inline zn_status_t zn_channel_read(
|
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,
|
||||||
@@ -44,18 +35,7 @@ static inline 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#define ZINNIA_FUTEX_H
|
#define ZINNIA_FUTEX_H
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_stubs.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -11,14 +10,10 @@ 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.
|
||||||
static inline zn_status_t zn_futex_wait(int32_t* addr, int32_t expected) {
|
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.
|
||||||
static inline zn_status_t zn_futex_wake(int32_t* addr, int32_t count) {
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-10
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <zinnia/rights.h>
|
#include <zinnia/rights.h>
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_stubs.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -20,22 +19,16 @@ 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.
|
||||||
static inline 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.
|
||||||
static inline 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.
|
||||||
static inline 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#ifndef ZINNIA_IPC_H
|
|
||||||
#define ZINNIA_IPC_H
|
|
||||||
|
|
||||||
#include <zinnia/handle.h>
|
|
||||||
#include <zinnia/rights.h>
|
|
||||||
#include <zinnia/status.h>
|
|
||||||
#include <zinnia/syscall_stubs.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Defines an IPC window.
|
|
||||||
struct zn_ipcw {
|
|
||||||
zn_handle_t handles[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline zn_status_t zn_ipcw_init(struct zn_ipcw** ipcw) {
|
|
||||||
return ZN_ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
+6
-15
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <zinnia/handle.h>
|
#include <zinnia/handle.h>
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_stubs.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ enum zn_vm_flags {
|
|||||||
ZN_VM_MAP_WRITE = 1 << 1,
|
ZN_VM_MAP_WRITE = 1 << 1,
|
||||||
// Mapping is executable.
|
// Mapping is executable.
|
||||||
ZN_VM_MAP_EXEC = 1 << 2,
|
ZN_VM_MAP_EXEC = 1 << 2,
|
||||||
// Shared memory (not cloned on calls to fork).
|
// Shared memory.
|
||||||
ZN_VM_MAP_SHARED = 1 << 3,
|
ZN_VM_MAP_SHARED = 1 << 3,
|
||||||
|
|
||||||
// Map at a fixed address, replacing whatever is in the way.
|
// Map at a fixed address, replacing whatever is in the way.
|
||||||
@@ -31,31 +30,23 @@ enum zn_vm_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Creates a new virtual memory object.
|
// Creates a new virtual memory object.
|
||||||
static inline zn_status_t zn_vmo_create(size_t length, zn_handle_t* out) {
|
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.
|
||||||
static inline zn_status_t zn_vmo_create_phys(uintptr_t phys_addr, size_t length, zn_handle_t* out) {
|
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`.
|
||||||
static inline zn_status_t zn_vmo_map(
|
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.
|
||||||
static inline zn_status_t zn_vas_create(zn_handle_t* out) {
|
zn_status_t zn_vas_create(zn_handle_t* out);
|
||||||
return zn_syscall1(out, ZN_SYSCALL_VAS_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,11 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Creates a new namespace.
|
// Creates a new namespace.
|
||||||
static inline zn_status_t zn_ns_create(zn_handle_t* out) {
|
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.
|
||||||
static inline zn_status_t zn_ns_move(zn_handle_t handle, zn_handle_t target_ns) {
|
zn_status_t zn_ns_move(zn_handle_t handle, zn_handle_t target_ns);
|
||||||
return ZN_ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#define ZINNIA_RANDOM_H
|
#define ZINNIA_RANDOM_H
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_stubs.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -14,14 +13,10 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Stores random bytes in a buffer.
|
// Stores random bytes in a buffer.
|
||||||
static inline zn_status_t zn_random_get(void* addr, size_t len) {
|
zn_status_t zn_random_get(void* addr, size_t len);
|
||||||
return zn_syscall2(addr, len, ZN_SYSCALL_RANDOM_GET);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds entropy to the RNG.
|
// Adds entropy to the RNG.
|
||||||
static inline zn_status_t zn_random_entropy(const void* addr, size_t len) {
|
zn_status_t zn_random_entropy(const void* addr, size_t len);
|
||||||
return zn_syscall2(addr, len, ZN_SYSCALL_RANDOM_ENTROPY);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-30
@@ -34,36 +34,7 @@ typedef enum {
|
|||||||
ZN_ERR_ALREADY_EXISTS = -11,
|
ZN_ERR_ALREADY_EXISTS = -11,
|
||||||
} zn_status_t;
|
} zn_status_t;
|
||||||
|
|
||||||
static inline const char* zn_status_to_string(zn_status_t err) {
|
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";
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-17
@@ -2,33 +2,24 @@
|
|||||||
#define ZINNIA_SYSTEM_H
|
#define ZINNIA_SYSTEM_H
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_stubs.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void zn_log(const char* message, size_t len) {
|
// Logs a message through the kernel.
|
||||||
zn_syscall2(message, len, ZN_SYSCALL_LOG);
|
// Messages longer than an unspecified size will get truncated by the kernel.
|
||||||
}
|
void zn_log(const char* message, size_t len);
|
||||||
|
|
||||||
// Returns the page size of the system.
|
// Returns the page size of the system.
|
||||||
static inline size_t zn_page_size() {
|
size_t zn_page_size();
|
||||||
size_t size = 0;
|
|
||||||
zn_syscall1(&size, ZN_SYSCALL_PAGE_SIZE);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline zn_status_t zn_powerctl() {
|
zn_status_t zn_powerctl();
|
||||||
return ZN_ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint64_t zn_time() {
|
// Returns the current timestamp in nanoseconds.
|
||||||
uint64_t time = 0;
|
uint64_t zn_time();
|
||||||
zn_syscall1(&time, ZN_SYSCALL_TIME);
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-11
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <zinnia/handle.h>
|
#include <zinnia/handle.h>
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_stubs.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -16,25 +15,19 @@ enum zn_thread_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Creates a new thread in the given namespace.
|
// Creates a new thread in the given namespace.
|
||||||
static inline zn_status_t zn_thread_create(
|
zn_status_t zn_thread_create(
|
||||||
zn_handle_t ns,
|
zn_handle_t ns,
|
||||||
const char* name,
|
const char* name,
|
||||||
size_t name_len,
|
size_t name_len,
|
||||||
enum zn_thread_flags flags,
|
enum zn_thread_flags flags,
|
||||||
zn_handle_t* out
|
zn_handle_t* out
|
||||||
) {
|
);
|
||||||
return zn_syscall5(ns, name, name_len, flags, out, ZN_SYSCALL_THREAD_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Starts executing a thread.
|
// Starts executing a thread.
|
||||||
static inline zn_status_t zn_thread_start(zn_handle_t thread, uintptr_t ip, uintptr_t sp, uintptr_t arg) {
|
zn_status_t zn_thread_start(zn_handle_t thread, uintptr_t ip, uintptr_t sp, uintptr_t arg);
|
||||||
return zn_syscall4(thread, ip, sp, arg, ZN_SYSCALL_THREAD_START);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stops execution of the calling thread.
|
// Stops execution of the calling thread.
|
||||||
static inline void zn_thread_exit(void) {
|
void zn_thread_exit(void);
|
||||||
zn_syscall0(ZN_SYSCALL_THREAD_EXIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ struct hpet {
|
|||||||
#define HPET_COUNTER (0xF0 / sizeof(uint64_t))
|
#define HPET_COUNTER (0xF0 / sizeof(uint64_t))
|
||||||
|
|
||||||
static void hpet_reset(struct clock* c) {
|
static void hpet_reset(struct clock* c) {
|
||||||
struct hpet* hpet = CONTAINER_OF(c, struct hpet, clock);
|
struct hpet* hpet = containerof(c, struct hpet, clock);
|
||||||
hpet->regs[HPET_COUNTER] = 0;
|
hpet->regs[HPET_COUNTER] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t hpet_get_elapsed_ns(struct clock* c) {
|
static uint64_t hpet_get_elapsed_ns(struct clock* c) {
|
||||||
struct hpet* hpet = CONTAINER_OF(c, struct hpet, clock);
|
struct hpet* hpet = containerof(c, struct hpet, clock);
|
||||||
uint64_t counter = hpet->regs[HPET_COUNTER];
|
uint64_t counter = hpet->regs[HPET_COUNTER];
|
||||||
return (counter * (uint64_t)hpet->period / 1'000'000);
|
return (counter * (uint64_t)hpet->period / 1'000'000);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -26,7 +26,7 @@ static zn_status_t load_server(
|
|||||||
struct task** out
|
struct task** out
|
||||||
) {
|
) {
|
||||||
struct vas* space;
|
struct vas* space;
|
||||||
zn_status_t status = vma_new(&space);
|
zn_status_t status = vas_new(&space);
|
||||||
if (status != ZN_OK)
|
if (status != ZN_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ static void kernel_main_task(uintptr_t arg0) {
|
|||||||
assert(channel_create(&init_ep, &other_ep) == ZN_OK, "Failed to create init channel\n");
|
assert(channel_create(&init_ep, &other_ep) == ZN_OK, "Failed to create init channel\n");
|
||||||
|
|
||||||
struct vas* init_space;
|
struct vas* init_space;
|
||||||
assert(vma_new(&init_space) == ZN_OK, "");
|
assert(vas_new(&init_space) == ZN_OK, "");
|
||||||
|
|
||||||
struct boot_file* file_data = &info->files[0];
|
struct boot_file* file_data = &info->files[0];
|
||||||
struct paged_vmo* init_file;
|
struct paged_vmo* init_file;
|
||||||
|
|||||||
+2
-2
@@ -67,7 +67,7 @@ zn_status_t elf_load(struct exec_info* info, struct task** out) {
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
// We map more than we copied so the rest is filled with zeroed pages.
|
// We map more than we copied so the rest is filled with zeroed pages.
|
||||||
status = vma_map_vmo(info->space, &phdr_obj->object, phdr.p_vaddr, phdr.p_memsz, prot, phdr.p_offset);
|
status = vas_map_vmo(info->space, &phdr_obj->object, phdr.p_vaddr, phdr.p_memsz, prot, phdr.p_offset);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ zn_status_t elf_load(struct exec_info* info, struct task** out) {
|
|||||||
uintptr_t argc = num_argv;
|
uintptr_t argc = num_argv;
|
||||||
vmo_write(&stack->object, stack_off, &argc, sizeof(argc), nullptr);
|
vmo_write(&stack->object, stack_off, &argc, sizeof(argc), nullptr);
|
||||||
|
|
||||||
status = vma_map_vmo(info->space, &stack->object, stack_start, stack_size, ZN_VM_MAP_READ | ZN_VM_MAP_WRITE, 0);
|
status = vas_map_vmo(info->space, &stack->object, stack_start, stack_size, ZN_VM_MAP_READ | ZN_VM_MAP_WRITE, 0);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
kernel_sources += files(
|
kernel_sources += files(
|
||||||
'channel.c',
|
'channel.c',
|
||||||
'clock.c',
|
'clock.c',
|
||||||
'futex.c',
|
|
||||||
'console.c',
|
'console.c',
|
||||||
'elf.c',
|
'elf.c',
|
||||||
|
'futex.c',
|
||||||
'irq.c',
|
'irq.c',
|
||||||
'namespace.c',
|
'namespace.c',
|
||||||
'panic.c',
|
'panic.c',
|
||||||
@@ -12,4 +12,5 @@ kernel_sources += files(
|
|||||||
'sched.c',
|
'sched.c',
|
||||||
'spin.c',
|
'spin.c',
|
||||||
'uacpi_glue.c',
|
'uacpi_glue.c',
|
||||||
|
'vdso.c',
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <zinnia/rights.h>
|
#include <zinnia/rights.h>
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <kernel/alloc.h>
|
#include <kernel/alloc.h>
|
||||||
|
#include <kernel/mutex.h>
|
||||||
#include <kernel/namespace.h>
|
#include <kernel/namespace.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ zn_status_t namespace_add_desc(struct namespace* namespace, struct namespace_des
|
|||||||
return ZN_ERR_INTERNAL;
|
return ZN_ERR_INTERNAL;
|
||||||
|
|
||||||
// Skip over handles that are already in use (e.g. hard-coded handles).
|
// Skip over handles that are already in use (e.g. hard-coded handles).
|
||||||
|
// mutex_lock(&namespace->mutex);
|
||||||
zn_handle_t handle;
|
zn_handle_t handle;
|
||||||
do {
|
do {
|
||||||
handle = atomic_fetch_add_explicit(&namespace->next_handle, 1, memory_order_acq_rel);
|
handle = atomic_fetch_add_explicit(&namespace->next_handle, 1, memory_order_acq_rel);
|
||||||
@@ -35,6 +37,8 @@ zn_status_t namespace_add_desc(struct namespace* namespace, struct namespace_des
|
|||||||
|
|
||||||
zn_status_t status =
|
zn_status_t status =
|
||||||
hashmap_insert(&namespace->descriptors, handle, desc, hashmap_hash_default, hashmap_eq_default);
|
hashmap_insert(&namespace->descriptors, handle, desc, hashmap_hash_default, hashmap_eq_default);
|
||||||
|
// mutex_unlock(&namespace->mutex);
|
||||||
|
|
||||||
if (status != ZN_OK)
|
if (status != ZN_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -45,6 +49,8 @@ zn_status_t namespace_add_desc(struct namespace* namespace, struct namespace_des
|
|||||||
zn_status_t namespace_add_desc_at(struct namespace* namespace, struct namespace_desc desc, zn_handle_t handle) {
|
zn_status_t namespace_add_desc_at(struct namespace* namespace, struct namespace_desc desc, zn_handle_t handle) {
|
||||||
if (!namespace)
|
if (!namespace)
|
||||||
return ZN_ERR_INTERNAL;
|
return ZN_ERR_INTERNAL;
|
||||||
|
|
||||||
|
// Skip Invalid or reserved handles.
|
||||||
if (handle <= ZN_HANDLE_INVALID)
|
if (handle <= ZN_HANDLE_INVALID)
|
||||||
return ZN_ERR_BAD_HANDLE;
|
return ZN_ERR_BAD_HANDLE;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include <common/compiler.h>
|
||||||
|
#include <kernel/vdso.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
[[__used, __section(".vdso")]]
|
||||||
|
const uint8_t vdso_bytes[] = {
|
||||||
|
#embed VDSO_PATH
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t vdso_length = sizeof(vdso_bytes);
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#ifndef ZINNIA_SYSCALL_NUMBERS_H
|
#pragma once
|
||||||
#define ZINNIA_SYSCALL_NUMBERS_H
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ZN_SYSCALL_LOG,
|
ZN_SYSCALL_LOG,
|
||||||
@@ -32,5 +31,3 @@ typedef enum {
|
|||||||
ZN_SYSCALL_FUTEX_WAIT,
|
ZN_SYSCALL_FUTEX_WAIT,
|
||||||
ZN_SYSCALL_FUTEX_WAKE,
|
ZN_SYSCALL_FUTEX_WAKE,
|
||||||
} zn_syscall_t;
|
} zn_syscall_t;
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
#ifndef ZINNIA_SYSCALL_STUBS_H
|
#pragma once
|
||||||
#define ZINNIA_SYSCALL_STUBS_H
|
|
||||||
|
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_numbers.h>
|
#include <kernel/syscall_numbers.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
typedef uint64_t zn_arg_t;
|
typedef uint64_t zn_arg_t;
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
@@ -78,6 +73,9 @@ typedef uint64_t zn_arg_t;
|
|||||||
#error "Unsupported architecture!"
|
#error "Unsupported architecture!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// These symbols should not be used in the kernel, ever.
|
||||||
|
#ifdef IN_VDSO
|
||||||
|
|
||||||
static inline zn_status_t zn_syscall0(zn_syscall_t num) {
|
static inline zn_status_t zn_syscall0(zn_syscall_t num) {
|
||||||
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
register zn_syscall_t rnum asm(ASM_REG_NUM) = num;
|
||||||
register zn_status_t value asm(ASM_REG_RET);
|
register zn_status_t value asm(ASM_REG_RET);
|
||||||
@@ -245,8 +243,4 @@ static inline zn_status_t zn_syscall8(
|
|||||||
num \
|
num \
|
||||||
)
|
)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -13,12 +13,12 @@ struct vas {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Try to create a new, empty virtual address space.
|
// Try to create a new, empty virtual address space.
|
||||||
zn_status_t vma_new(struct vas** out);
|
zn_status_t vas_new(struct vas** out);
|
||||||
|
|
||||||
// Delete a virtual address space.
|
// Delete a virtual address space.
|
||||||
void vma_delete(struct vas* vm);
|
void vas_delete(struct vas* vm);
|
||||||
|
|
||||||
zn_status_t vma_map_vmo(
|
zn_status_t vas_map_vmo(
|
||||||
struct vas* vm,
|
struct vas* vm,
|
||||||
struct vmo* vmo,
|
struct vmo* vmo,
|
||||||
uintptr_t addr,
|
uintptr_t addr,
|
||||||
@@ -28,12 +28,12 @@ zn_status_t vma_map_vmo(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Remove any mappings in the given address range.
|
// Remove any mappings in the given address range.
|
||||||
zn_status_t vma_unmap(struct vas* vm, uintptr_t vaddr, size_t size);
|
zn_status_t vas_unmap(struct vas* vm, uintptr_t vaddr, size_t size);
|
||||||
|
|
||||||
// Change the protection of an existing mapping.
|
// Change the protection of an existing mapping.
|
||||||
zn_status_t vma_protect(struct vas* vm, uintptr_t vaddr, size_t size, enum zn_vm_flags flags);
|
zn_status_t vas_protect(struct vas* vm, uintptr_t vaddr, size_t size, enum zn_vm_flags flags);
|
||||||
|
|
||||||
// Try to handle a page fault.
|
// Try to handle a page fault.
|
||||||
bool vma_page_fault(struct vas* vm, uintptr_t vaddr, enum zn_vm_flags access_type);
|
bool vas_page_fault(struct vas* vm, uintptr_t vaddr, enum zn_vm_flags access_type);
|
||||||
|
|
||||||
extern struct vas kernel_vas;
|
extern struct vas kernel_vas;
|
||||||
|
|||||||
@@ -1,6 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern uint8_t __ld_vdso_start[];
|
extern const uint8_t vdso_bytes[];
|
||||||
extern uint8_t __ld_vdso_end[];
|
extern const size_t vdso_length;
|
||||||
|
|
||||||
|
// Data which is shared between the kernel and VAS.
|
||||||
|
// The kernel updates its contents continuously, which is visible to every VAS.
|
||||||
|
struct vdso_kernel_data {
|
||||||
|
struct {
|
||||||
|
uint64_t sec;
|
||||||
|
uint64_t nsec;
|
||||||
|
} time;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef IN_VDSO
|
||||||
|
|
||||||
|
#include <kernel/syscall_numbers.h>
|
||||||
|
#include <kernel/syscall_stubs.h>
|
||||||
|
|
||||||
|
// Export a function under the current API version.
|
||||||
|
#define VDSO_SYMBOL(fn) asm(".symver " #fn ",__vdso_" #fn "@@ZINNIA_0")
|
||||||
|
// Export a function as a symbol for an older API version.
|
||||||
|
#define VDSO_SYMBOL_LEGACY(fn, symbol, ver) asm(".symver " #fn ",__vdso_" #symbol "@ZINNIA_" ver)
|
||||||
|
|
||||||
|
extern const volatile struct vdso_kernel_data vdso_data;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ SECTIONS
|
|||||||
KEEP(*(.cmdline))
|
KEEP(*(.cmdline))
|
||||||
__ld_cmdline_end = .;
|
__ld_cmdline_end = .;
|
||||||
|
|
||||||
|
__ld_vdso_start = .;
|
||||||
|
KEEP(*(.vdso))
|
||||||
|
__ld_vdso_end = .;
|
||||||
|
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
*(.got .got.*)
|
*(.got .got.*)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ kernel_sources += files(
|
|||||||
'pmm.c',
|
'pmm.c',
|
||||||
'slab.c',
|
'slab.c',
|
||||||
'usercopy.c',
|
'usercopy.c',
|
||||||
|
'vas.c',
|
||||||
'virt.c',
|
'virt.c',
|
||||||
'vma.c',
|
|
||||||
'vmo.c',
|
'vmo.c',
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
// Try to create a new, empty virtual address space.
|
// Try to create a new, empty virtual address space.
|
||||||
zn_status_t vma_new(struct vas** out) {
|
zn_status_t vas_new(struct vas** out) {
|
||||||
debug_assert(out != nullptr, "Missing out");
|
debug_assert(out != nullptr, "Missing out");
|
||||||
|
|
||||||
zn_status_t res;
|
zn_status_t res;
|
||||||
@@ -30,23 +30,23 @@ err0:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete a virtual address space.
|
// Delete a virtual address space.
|
||||||
void vma_delete(struct vas* vm) {}
|
void vas_delete(struct vas* vm) {}
|
||||||
|
|
||||||
// Remove any mappings in the given address range.
|
// Remove any mappings in the given address range.
|
||||||
// May fail if there is no memory and a mapping needs to be split.
|
// May fail if there is no memory and a mapping needs to be split.
|
||||||
zn_status_t vma_unmap(struct vas* vm, uintptr_t vaddr, size_t size);
|
zn_status_t vas_unmap(struct vas* vm, uintptr_t vaddr, size_t size);
|
||||||
|
|
||||||
// Change the protection of an existing mapping.
|
// Change the protection of an existing mapping.
|
||||||
// May fail if there is no memory and a mapping needs to be split.
|
// May fail if there is no memory and a mapping needs to be split.
|
||||||
zn_status_t vma_protect(struct vas* vm, uintptr_t vaddr, size_t size, enum zn_vm_flags flags);
|
zn_status_t vas_protect(struct vas* vm, uintptr_t vaddr, size_t size, enum zn_vm_flags flags);
|
||||||
|
|
||||||
// Try to handle a page fault.
|
// Try to handle a page fault.
|
||||||
bool vma_page_fault(struct vas* vm, uintptr_t vaddr, enum zn_vm_flags access_type) {
|
bool vas_page_fault(struct vas* vm, uintptr_t vaddr, enum zn_vm_flags access_type) {
|
||||||
// TODO
|
// TODO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
zn_status_t vma_map_vmo(
|
zn_status_t vas_map_vmo(
|
||||||
struct vas* vas,
|
struct vas* vas,
|
||||||
struct vmo* vmo,
|
struct vmo* vmo,
|
||||||
uintptr_t addr,
|
uintptr_t addr,
|
||||||
+2
-2
@@ -101,7 +101,7 @@ zn_status_t vmo_copy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static zn_status_t paged_get_page(struct vmo* vmo, uintptr_t offset_idx, struct page** out) {
|
static zn_status_t paged_get_page(struct vmo* vmo, uintptr_t offset_idx, struct page** out) {
|
||||||
struct paged_vmo* paged = CONTAINER_OF(vmo, struct paged_vmo, object);
|
struct paged_vmo* paged = containerof(vmo, struct paged_vmo, object);
|
||||||
|
|
||||||
// Try to find the requested page in the cache.
|
// Try to find the requested page in the cache.
|
||||||
struct page_list* iter;
|
struct page_list* iter;
|
||||||
@@ -177,7 +177,7 @@ struct phys_range_vmo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static zn_status_t phys_range_get_page(struct vmo* vmo, uintptr_t offset_idx, struct page** out) {
|
static zn_status_t phys_range_get_page(struct vmo* vmo, uintptr_t offset_idx, struct page** out) {
|
||||||
struct phys_range_vmo* p = CONTAINER_OF(vmo, struct phys_range_vmo, object);
|
struct phys_range_vmo* p = containerof(vmo, struct phys_range_vmo, object);
|
||||||
*out = &vm_pfndb[(p->start / arch_mem_page_size()) + offset_idx];
|
*out = &vm_pfndb[(p->start / arch_mem_page_size()) + offset_idx];
|
||||||
return ZN_OK;
|
return ZN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -34,6 +34,7 @@ subdir('core')
|
|||||||
subdir('syscalls')
|
subdir('syscalls')
|
||||||
|
|
||||||
subdir('klibc')
|
subdir('klibc')
|
||||||
|
subdir('vdso')
|
||||||
|
|
||||||
executable(
|
executable(
|
||||||
'zinnia',
|
'zinnia',
|
||||||
@@ -44,11 +45,12 @@ executable(
|
|||||||
],
|
],
|
||||||
c_args: kernel_c_args,
|
c_args: kernel_c_args,
|
||||||
link_args: kernel_link_args,
|
link_args: kernel_link_args,
|
||||||
link_depends: kernel_lds,
|
link_depends: [
|
||||||
|
kernel_lds,
|
||||||
|
vdso,
|
||||||
|
],
|
||||||
sources: [
|
sources: [
|
||||||
kernel_sources,
|
kernel_sources,
|
||||||
uacpi_sources,
|
uacpi_sources,
|
||||||
],
|
],
|
||||||
install: true,
|
|
||||||
install_dir: '/boot',
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <zinnia/syscall_numbers.h>
|
|
||||||
#include <common/compiler.h>
|
#include <common/compiler.h>
|
||||||
#include <common/utils.h>
|
#include <common/utils.h>
|
||||||
#include <kernel/print.h>
|
#include <kernel/print.h>
|
||||||
#include <kernel/sched.h>
|
#include <kernel/sched.h>
|
||||||
|
#include <kernel/syscall_numbers.h>
|
||||||
#include <kernel/syscalls.h>
|
#include <kernel/syscalls.h>
|
||||||
#include <kernel/types.h>
|
#include <kernel/types.h>
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ zn_status_t syscall_vmo_map(struct arch_context* ctx) {
|
|||||||
if (!usercopy_write(addr, &target_addr, sizeof(target_addr)))
|
if (!usercopy_write(addr, &target_addr, sizeof(target_addr)))
|
||||||
return ZN_ERR_BAD_BUFFER;
|
return ZN_ERR_BAD_BUFFER;
|
||||||
}
|
}
|
||||||
vma_map_vmo(vas, vmo, target_addr, bytes, flags, vmo_offset);
|
vas_map_vmo(vas, vmo, target_addr, bytes, flags, vmo_offset);
|
||||||
|
|
||||||
return ZN_OK;
|
return ZN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#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);
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#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);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#include <common/compiler.h>
|
||||||
|
#include <kernel/vdso.h>
|
||||||
|
|
||||||
|
[[__used, __section(".vdso_data")]]
|
||||||
|
const volatile struct vdso_kernel_data vdso_data = {0};
|
||||||
|
|
||||||
|
static_assert(sizeof(vdso_data) <= 0x1000);
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#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);
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#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);
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
vdso_c_args = [
|
||||||
|
'-ffreestanding',
|
||||||
|
'-fno-stack-protector',
|
||||||
|
'-fno-omit-frame-pointer',
|
||||||
|
'-fPIE',
|
||||||
|
'-fPIC',
|
||||||
|
'-nostdinc',
|
||||||
|
'-DIN_VDSO',
|
||||||
|
]
|
||||||
|
|
||||||
|
vdso_lds = meson.current_source_dir() / 'vdso.ld'
|
||||||
|
|
||||||
|
vdso_link_args = [
|
||||||
|
'-ffreestanding',
|
||||||
|
'-nostdlib',
|
||||||
|
'-static',
|
||||||
|
'-T' + vdso_lds,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Build a shared library, which we are going to embed next.
|
||||||
|
# TODO: We need to ensure there are no relocations inside the vDSO.
|
||||||
|
vdso = shared_library(
|
||||||
|
'zinnia-vdso',
|
||||||
|
name_prefix: '',
|
||||||
|
c_args: vdso_c_args,
|
||||||
|
include_directories: [
|
||||||
|
common_includes,
|
||||||
|
kernel_includes,
|
||||||
|
],
|
||||||
|
link_args: vdso_link_args,
|
||||||
|
link_depends: vdso_lds,
|
||||||
|
sources: [
|
||||||
|
'archctl.c',
|
||||||
|
'channel.c',
|
||||||
|
'data.c',
|
||||||
|
'futex.c',
|
||||||
|
'handle.c',
|
||||||
|
'mem.c',
|
||||||
|
'namespace.c',
|
||||||
|
'random.c',
|
||||||
|
'status.c',
|
||||||
|
'system.c',
|
||||||
|
'thread.c',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Tell the kernel where the built binary lives so we can #embed it.
|
||||||
|
kernel_c_args += ['-DVDSO_PATH="' + vdso.full_path() + '"']
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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);
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#include <zinnia/random.h>
|
||||||
|
#include <kernel/vdso.h>
|
||||||
|
|
||||||
|
zn_status_t zn_random_get(void* addr, size_t len) {
|
||||||
|
return zn_syscall2(addr, len, ZN_SYSCALL_RANDOM_GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_random_get);
|
||||||
|
|
||||||
|
zn_status_t zn_random_entropy(const void* addr, size_t len) {
|
||||||
|
return zn_syscall2(addr, len, ZN_SYSCALL_RANDOM_ENTROPY);
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_random_entropy);
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#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);
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#include <zinnia/system.h>
|
||||||
|
#include <kernel/vdso.h>
|
||||||
|
|
||||||
|
void zn_log(const char* message, size_t len) {
|
||||||
|
zn_syscall2(message, len, ZN_SYSCALL_LOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_log);
|
||||||
|
|
||||||
|
size_t zn_page_size() {
|
||||||
|
size_t size = 0;
|
||||||
|
zn_syscall1(&size, ZN_SYSCALL_PAGE_SIZE);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_page_size);
|
||||||
|
|
||||||
|
zn_status_t zn_powerctl() {
|
||||||
|
return ZN_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_powerctl);
|
||||||
|
|
||||||
|
uint64_t zn_time() {
|
||||||
|
return vdso_data.time.nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_time);
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#include <zinnia/thread.h>
|
||||||
|
#include <kernel/vdso.h>
|
||||||
|
|
||||||
|
zn_status_t zn_thread_create(
|
||||||
|
zn_handle_t ns,
|
||||||
|
const char* name,
|
||||||
|
size_t name_len,
|
||||||
|
enum zn_thread_flags flags,
|
||||||
|
zn_handle_t* out
|
||||||
|
) {
|
||||||
|
return zn_syscall5(ns, name, name_len, flags, out, ZN_SYSCALL_THREAD_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_thread_create);
|
||||||
|
|
||||||
|
zn_status_t zn_thread_start(zn_handle_t thread, uintptr_t ip, uintptr_t sp, uintptr_t arg) {
|
||||||
|
return zn_syscall4(thread, ip, sp, arg, ZN_SYSCALL_THREAD_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_thread_start);
|
||||||
|
|
||||||
|
void zn_thread_exit(void) {
|
||||||
|
zn_syscall0(ZN_SYSCALL_THREAD_EXIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
VDSO_SYMBOL(zn_thread_exit);
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
VERSION {
|
||||||
|
ZINNIA_0 {
|
||||||
|
global:
|
||||||
|
__vdso*;
|
||||||
|
local: *;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
PHDRS {
|
||||||
|
text PT_LOAD FILEHDR PHDRS FLAGS(5);
|
||||||
|
dynamic PT_DYNAMIC FLAGS(4);
|
||||||
|
note PT_NOTE FLAGS(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = SIZEOF_HEADERS;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text .text.*)
|
||||||
|
*(.plt .plt.*)
|
||||||
|
} :text
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
*(.got .got.*)
|
||||||
|
} :text
|
||||||
|
|
||||||
|
.data ALIGN(CONSTANT(MAXPAGESIZE)) : {
|
||||||
|
*(.vdso_data)
|
||||||
|
} :text
|
||||||
|
|
||||||
|
.dynsym : {
|
||||||
|
*(.dynsym)
|
||||||
|
} :text
|
||||||
|
|
||||||
|
.dynstr : {
|
||||||
|
*(.dynstr)
|
||||||
|
} :text
|
||||||
|
|
||||||
|
.dynamic : {
|
||||||
|
*(.dynamic)
|
||||||
|
} :text :dynamic
|
||||||
|
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(.data*)
|
||||||
|
*(.bss*)
|
||||||
|
*(.comment*)
|
||||||
|
*(.eh_frame*)
|
||||||
|
*(.rel.eh_frame*)
|
||||||
|
*(.gcc_except_table*)
|
||||||
|
*(.note.gnu.property)
|
||||||
|
*(.interp)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
libzinnia = static_library(
|
||||||
|
'zinnia',
|
||||||
|
sources: [
|
||||||
|
'vdso.c',
|
||||||
|
],
|
||||||
|
include_directories: common_includes,
|
||||||
|
)
|
||||||
|
|||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
#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);
|
||||||
@@ -11,5 +11,6 @@ executable(
|
|||||||
common_includes,
|
common_includes,
|
||||||
uacpi_includes,
|
uacpi_includes,
|
||||||
],
|
],
|
||||||
|
link_with: libzinnia,
|
||||||
install: true,
|
install: true,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ executable(
|
|||||||
'main.c',
|
'main.c',
|
||||||
# The init process is linked statically because the dynamic loader can't be read before posixd is up.
|
# The init process is linked statically because the dynamic loader can't be read before posixd is up.
|
||||||
link_args: '-static',
|
link_args: '-static',
|
||||||
|
link_with: libzinnia,
|
||||||
include_directories: common_includes,
|
include_directories: common_includes,
|
||||||
install: true,
|
install: true,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <zinnia/archctl.h>
|
||||||
#include <zinnia/channel.h>
|
#include <zinnia/channel.h>
|
||||||
#include <zinnia/handle.h>
|
#include <zinnia/handle.h>
|
||||||
#include <zinnia/mem.h>
|
#include <zinnia/mem.h>
|
||||||
@@ -54,6 +55,7 @@ int other_fn(void* arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[], char* envp[]) {
|
int main(int argc, char* argv[], char* envp[]) {
|
||||||
|
zn_archctl(ZN_ARCHCTL_SET_FSBASE, nullptr);
|
||||||
zn_printf("unix: starting...\n");
|
zn_printf("unix: starting...\n");
|
||||||
const char* thread_name = "unix_second_thread";
|
const char* thread_name = "unix_second_thread";
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ executable(
|
|||||||
'unix',
|
'unix',
|
||||||
'main.c',
|
'main.c',
|
||||||
'uname.c',
|
'uname.c',
|
||||||
link_args: '-static',
|
link_with: libzinnia,
|
||||||
include_directories: [common_includes, 'include'],
|
include_directories: [common_includes, 'include'],
|
||||||
install: true,
|
install: true,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user