fixes
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/channel.h>
|
||||
#include <zinnia/handle.h>
|
||||
#include <common/utils.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ZN_IPC_NUM(group, num) ((uint32_t)(group) << 24u) | ((uint32_t)(num) & 0xffffffu)
|
||||
|
||||
#define ZN_IPC(name, group, num, num_handles) \
|
||||
name##_inner; \
|
||||
constexpr uint32_t name##_num = ZN_IPC_NUM(group, num); \
|
||||
typedef struct { \
|
||||
uint32_t id; \
|
||||
zn_handle_t handles[num_handles]; \
|
||||
name##_inner inner; \
|
||||
} name
|
||||
|
||||
#define zn_ipc_write(channel, obj) \
|
||||
zn_channel_write(channel, (obj)->handles, &(obj)->inner, ARRAY_SIZE((obj)->handles), sizeof((obj)->inner))
|
||||
|
||||
#define zn_ipc_read(channel, obj) \
|
||||
zn_channel_read( \
|
||||
channel, \
|
||||
(obj)->handles, \
|
||||
&(obj)->inner, \
|
||||
ARRAY_SIZE((obj)->handles), \
|
||||
sizeof((obj)->inner), \
|
||||
nullptr, \
|
||||
nullptr \
|
||||
)
|
||||
|
||||
#define zn_ipc_new(name) \
|
||||
(zn_ipc_fw_rsdp) { \
|
||||
.id = name##_num \
|
||||
}
|
||||
@@ -13,6 +13,7 @@ extern "C" {
|
||||
|
||||
enum zn_channel_flags {
|
||||
ZN_CHANNEL_NONE = 0,
|
||||
ZN_CHANNEL_NONBLOCK = 1 << 0,
|
||||
};
|
||||
|
||||
// Creates a new channel.
|
||||
|
||||
@@ -40,7 +40,7 @@ struct arch_context {
|
||||
uint64_t ss;
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct arch_context) == 176);
|
||||
static_assert(sizeof(struct arch_context) == 22 * sizeof(uint64_t));
|
||||
|
||||
#define ARCH_CTX_NUM rax
|
||||
#define ARCH_CTX_A0 rdi
|
||||
|
||||
@@ -30,6 +30,8 @@ union ia32_star {
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(union ia32_star) == 8);
|
||||
|
||||
static void setup_cpu(struct percpu* cpu) {
|
||||
asm_wrmsr(MSR_GS_BASE, (uint64_t)cpu);
|
||||
asm_wrmsr(MSR_FS_BASE, 0);
|
||||
|
||||
@@ -82,7 +82,7 @@ bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct u
|
||||
"clac\n"
|
||||
"ret\n"
|
||||
:
|
||||
: "i"(&read_region)
|
||||
: "i"(&write_region)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ zn_status_t channel_read(struct channel* ch, struct channel_msg** msg_out) {
|
||||
return ZN_OK;
|
||||
}
|
||||
|
||||
// No message and peer is gone — nothing will ever arrive.
|
||||
// No message and peer is gone.
|
||||
if (!ch->peer) {
|
||||
spin_unlock(&ch->lock);
|
||||
return ZN_ERR_BAD_HANDLE;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
// Like the standard C assert, but also active in debug builds.
|
||||
#define assert(expr, msg, ...) \
|
||||
({ \
|
||||
do { \
|
||||
if (__unlikely(!(expr))) { \
|
||||
panic( \
|
||||
"In function \"%s\" (%s:%u):\n" \
|
||||
@@ -17,7 +17,7 @@
|
||||
##__VA_ARGS__ \
|
||||
); \
|
||||
} \
|
||||
})
|
||||
} while (0)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define debug_assert(...) assert(__VA_ARGS__)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/channel.h>
|
||||
#include <zinnia/status.h>
|
||||
#include <kernel/spin.h>
|
||||
#include <kernel/tailq.h>
|
||||
@@ -19,6 +22,7 @@ struct channel_msg {
|
||||
struct channel {
|
||||
struct channel* peer;
|
||||
struct spinlock lock;
|
||||
enum zn_channel_flags flags;
|
||||
tailq_head(struct channel_msg) messages;
|
||||
struct wait_queue waiters;
|
||||
};
|
||||
|
||||
@@ -6,32 +6,34 @@ typedef zn_status_t (*syscall_fn_t)(struct arch_context* ctx);
|
||||
|
||||
void syscall_dispatch(struct arch_context* ctx);
|
||||
|
||||
zn_status_t syscall_log(struct arch_context* ctx);
|
||||
zn_status_t syscall_archctl(struct arch_context* ctx);
|
||||
zn_status_t syscall_page_size(struct arch_context* ctx);
|
||||
zn_status_t syscall_time(struct arch_context* ctx);
|
||||
#define DEFINE_SYSCALL(name) zn_status_t syscall_##name(struct arch_context* ctx)
|
||||
|
||||
zn_status_t syscall_handle_validate(struct arch_context* ctx);
|
||||
zn_status_t syscall_handle_drop(struct arch_context* ctx);
|
||||
zn_status_t syscall_handle_clone(struct arch_context* ctx);
|
||||
DEFINE_SYSCALL(log);
|
||||
DEFINE_SYSCALL(archctl);
|
||||
DEFINE_SYSCALL(page_size);
|
||||
DEFINE_SYSCALL(time);
|
||||
|
||||
zn_status_t syscall_vas_create(struct arch_context* ctx);
|
||||
DEFINE_SYSCALL(handle_validate);
|
||||
DEFINE_SYSCALL(handle_drop);
|
||||
DEFINE_SYSCALL(handle_clone);
|
||||
|
||||
zn_status_t syscall_vmo_create(struct arch_context* ctx);
|
||||
zn_status_t syscall_vmo_create_phys(struct arch_context* ctx);
|
||||
zn_status_t syscall_vmo_map(struct arch_context* ctx);
|
||||
DEFINE_SYSCALL(vas_create);
|
||||
|
||||
zn_status_t syscall_channel_create(struct arch_context* ctx);
|
||||
zn_status_t syscall_channel_wait(struct arch_context* ctx);
|
||||
zn_status_t syscall_channel_read(struct arch_context* ctx);
|
||||
zn_status_t syscall_channel_write(struct arch_context* ctx);
|
||||
DEFINE_SYSCALL(vmo_create);
|
||||
DEFINE_SYSCALL(vmo_create_phys);
|
||||
DEFINE_SYSCALL(vmo_map);
|
||||
|
||||
zn_status_t syscall_thread_create(struct arch_context* ctx);
|
||||
zn_status_t syscall_thread_start(struct arch_context* ctx);
|
||||
zn_status_t syscall_thread_exit(struct arch_context* ctx);
|
||||
DEFINE_SYSCALL(channel_create);
|
||||
DEFINE_SYSCALL(channel_wait);
|
||||
DEFINE_SYSCALL(channel_read);
|
||||
DEFINE_SYSCALL(channel_write);
|
||||
|
||||
zn_status_t syscall_random_get(struct arch_context* ctx);
|
||||
zn_status_t syscall_random_entropy(struct arch_context* ctx);
|
||||
DEFINE_SYSCALL(thread_create);
|
||||
DEFINE_SYSCALL(thread_start);
|
||||
DEFINE_SYSCALL(thread_exit);
|
||||
|
||||
zn_status_t syscall_futex_wait(struct arch_context* ctx);
|
||||
zn_status_t syscall_futex_wake(struct arch_context* ctx);
|
||||
DEFINE_SYSCALL(random_get);
|
||||
DEFINE_SYSCALL(random_entropy);
|
||||
|
||||
DEFINE_SYSCALL(futex_wait);
|
||||
DEFINE_SYSCALL(futex_wake);
|
||||
|
||||
+25
-19
@@ -12,8 +12,14 @@
|
||||
#include <kernel/usercopy.h>
|
||||
|
||||
zn_status_t syscall_channel_create(struct arch_context* ctx) {
|
||||
__user zn_handle_t* end0 = (__user zn_handle_t*)ctx->ARCH_CTX_A1;
|
||||
__user zn_handle_t* end1 = (__user zn_handle_t*)ctx->ARCH_CTX_A2;
|
||||
auto flags = (enum zn_channel_flags)ctx->a0;
|
||||
auto end0 = (__user zn_handle_t*)ctx->a1;
|
||||
auto end1 = (__user zn_handle_t*)ctx->a2;
|
||||
|
||||
// Validate flags before doing anything.
|
||||
if (flags & !(ZN_CHANNEL_NONE | ZN_CHANNEL_NONBLOCK)) {
|
||||
return ZN_ERR_INVALID;
|
||||
}
|
||||
|
||||
struct channel* ep0;
|
||||
struct channel* ep1;
|
||||
@@ -61,11 +67,11 @@ zn_status_t syscall_channel_create(struct arch_context* ctx) {
|
||||
}
|
||||
|
||||
zn_status_t syscall_channel_write(struct arch_context* ctx) {
|
||||
zn_handle_t ch_handle = ctx->ARCH_CTX_A0;
|
||||
__user zn_handle_t* handles = (__user zn_handle_t*)ctx->ARCH_CTX_A1;
|
||||
__user void* bytes = (__user void*)ctx->ARCH_CTX_A2;
|
||||
size_t num_handles = ctx->ARCH_CTX_A3;
|
||||
size_t num_bytes = ctx->ARCH_CTX_A4;
|
||||
auto ch_handle = (zn_handle_t)ctx->a0;
|
||||
auto handles = (__user zn_handle_t*)ctx->a0;
|
||||
auto bytes = (__user void*)ctx->a2;
|
||||
size_t num_handles = ctx->a3;
|
||||
size_t num_bytes = ctx->a4;
|
||||
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
|
||||
@@ -95,7 +101,7 @@ zn_status_t syscall_channel_write(struct arch_context* ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
// Copy and transfer handles (move semantics).
|
||||
// Copy and transfer handles.
|
||||
struct namespace_desc* descs = nullptr;
|
||||
if (num_handles > 0) {
|
||||
if (!handles) {
|
||||
@@ -155,13 +161,13 @@ zn_status_t syscall_channel_write(struct arch_context* ctx) {
|
||||
}
|
||||
|
||||
zn_status_t syscall_channel_read(struct arch_context* ctx) {
|
||||
zn_handle_t ch_handle = ctx->ARCH_CTX_A0;
|
||||
__user zn_handle_t* handles = (__user zn_handle_t*)ctx->ARCH_CTX_A1;
|
||||
__user void* bytes = (__user void*)ctx->ARCH_CTX_A2;
|
||||
size_t num_handles = ctx->ARCH_CTX_A3;
|
||||
size_t num_bytes = ctx->ARCH_CTX_A4;
|
||||
__user size_t* read_handles = (__user size_t*)ctx->ARCH_CTX_A5;
|
||||
__user size_t* read_bytes = (__user size_t*)ctx->ARCH_CTX_A6;
|
||||
zn_handle_t ch_handle = ctx->a0;
|
||||
__user zn_handle_t* handles = (__user zn_handle_t*)ctx->a1;
|
||||
__user void* bytes = (__user void*)ctx->a2;
|
||||
size_t num_handles = ctx->a3;
|
||||
size_t num_bytes = ctx->a4;
|
||||
__user size_t* read_handles = (__user size_t*)ctx->a5;
|
||||
__user size_t* read_bytes = (__user size_t*)ctx->a6;
|
||||
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
struct sched_percpu* sched = &percpu_get()->sched;
|
||||
@@ -183,7 +189,7 @@ zn_status_t syscall_channel_read(struct arch_context* ctx) {
|
||||
|
||||
if (status == ZN_OK) {
|
||||
// Copy byte data to userspace.
|
||||
size_t bytes_to_copy = msg->num_bytes < num_bytes ? msg->num_bytes : num_bytes;
|
||||
size_t bytes_to_copy = MIN(msg->num_bytes, num_bytes);
|
||||
if (bytes_to_copy > 0 && bytes) {
|
||||
if (!usercopy_write(bytes, msg->data, bytes_to_copy)) {
|
||||
channel_msg_free(msg);
|
||||
@@ -192,7 +198,7 @@ zn_status_t syscall_channel_read(struct arch_context* ctx) {
|
||||
}
|
||||
|
||||
// Transfer handle descriptors into the reader's namespace.
|
||||
size_t handles_to_copy = msg->num_handles < num_handles ? msg->num_handles : num_handles;
|
||||
size_t handles_to_copy = MIN(msg->num_handles, num_handles);
|
||||
if (handles_to_copy > 0 && handles) {
|
||||
for (size_t i = 0; i < handles_to_copy; i++) {
|
||||
zn_handle_t new_handle;
|
||||
@@ -231,13 +237,13 @@ zn_status_t syscall_channel_read(struct arch_context* ctx) {
|
||||
if (status == ZN_ERR_BAD_HANDLE)
|
||||
return status;
|
||||
|
||||
// Empty but peer alive — block until a message arrives or peer closes.
|
||||
// Block until a message arrives or peer closes.
|
||||
sched_block(sched, &ch->waiters);
|
||||
}
|
||||
}
|
||||
|
||||
zn_status_t syscall_channel_wait(struct arch_context* ctx) {
|
||||
zn_handle_t ch_handle = ctx->ARCH_CTX_A0;
|
||||
zn_handle_t ch_handle = ctx->a0;
|
||||
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
struct sched_percpu* sched = &percpu_get()->sched;
|
||||
|
||||
+13
-13
@@ -15,8 +15,8 @@
|
||||
#include <stdatomic.h>
|
||||
|
||||
zn_status_t syscall_vmo_create(struct arch_context* ctx) {
|
||||
size_t length = ctx->ARCH_CTX_A0;
|
||||
__user zn_handle_t* out = (__user zn_handle_t*)ctx->ARCH_CTX_A1;
|
||||
size_t length = ctx->a0;
|
||||
__user zn_handle_t* out = (__user zn_handle_t*)ctx->a1;
|
||||
|
||||
// Allocate new VMO.
|
||||
struct paged_vmo* vmo;
|
||||
@@ -43,9 +43,9 @@ zn_status_t syscall_vmo_create(struct arch_context* ctx) {
|
||||
}
|
||||
|
||||
zn_status_t syscall_vmo_create_phys(struct arch_context* ctx) {
|
||||
uintptr_t addr = ctx->ARCH_CTX_A0;
|
||||
size_t length = ctx->ARCH_CTX_A1;
|
||||
__user zn_handle_t* out = (__user zn_handle_t*)ctx->ARCH_CTX_A2;
|
||||
uintptr_t addr = ctx->a0;
|
||||
size_t length = ctx->a1;
|
||||
__user zn_handle_t* out = (__user zn_handle_t*)ctx->a2;
|
||||
|
||||
struct vmo* vmo;
|
||||
zn_status_t status = vmo_new_phys_range(addr, length, &vmo);
|
||||
@@ -71,12 +71,12 @@ zn_status_t syscall_vmo_create_phys(struct arch_context* ctx) {
|
||||
}
|
||||
|
||||
zn_status_t syscall_vmo_map(struct arch_context* ctx) {
|
||||
zn_handle_t vmo_handle = ctx->ARCH_CTX_A0;
|
||||
zn_handle_t vas_handle = ctx->ARCH_CTX_A1;
|
||||
uintptr_t vmo_offset = ctx->ARCH_CTX_A2;
|
||||
__user uintptr_t* addr = (__user uintptr_t*)ctx->ARCH_CTX_A3;
|
||||
size_t bytes = ctx->ARCH_CTX_A4;
|
||||
enum zn_vm_flags flags = ctx->ARCH_CTX_A5;
|
||||
zn_handle_t vmo_handle = ctx->a0;
|
||||
zn_handle_t vas_handle = ctx->a1;
|
||||
uintptr_t vmo_offset = ctx->a2;
|
||||
auto addr = (__user uintptr_t*)ctx->a3;
|
||||
size_t bytes = ctx->a4;
|
||||
enum zn_vm_flags flags = ctx->a5;
|
||||
|
||||
struct task* current = percpu_get()->sched.current;
|
||||
|
||||
@@ -112,8 +112,8 @@ zn_status_t syscall_vmo_map(struct arch_context* ctx) {
|
||||
|
||||
// TODO: Use actual allocator for user task.
|
||||
if (target_addr == 0) {
|
||||
static uintptr_t map_offset = 0xA000'0000;
|
||||
target_addr = atomic_fetch_add(&map_offset, ALIGN_UP(bytes, arch_mem_page_size()));
|
||||
static _Atomic uintptr_t map_offset = 0xA000'0000;
|
||||
target_addr = atomic_fetch_add((volatile uintptr_t*)&map_offset, ALIGN_UP(bytes, arch_mem_page_size()));
|
||||
}
|
||||
|
||||
if (addr != nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user