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 {
|
enum zn_channel_flags {
|
||||||
ZN_CHANNEL_NONE = 0,
|
ZN_CHANNEL_NONE = 0,
|
||||||
|
ZN_CHANNEL_NONBLOCK = 1 << 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates a new channel.
|
// Creates a new channel.
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ struct arch_context {
|
|||||||
uint64_t ss;
|
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_NUM rax
|
||||||
#define ARCH_CTX_A0 rdi
|
#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) {
|
static void setup_cpu(struct percpu* cpu) {
|
||||||
asm_wrmsr(MSR_GS_BASE, (uint64_t)cpu);
|
asm_wrmsr(MSR_GS_BASE, (uint64_t)cpu);
|
||||||
asm_wrmsr(MSR_FS_BASE, 0);
|
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"
|
"clac\n"
|
||||||
"ret\n"
|
"ret\n"
|
||||||
:
|
:
|
||||||
: "i"(&read_region)
|
: "i"(&write_region)
|
||||||
: "memory"
|
: "memory"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ zn_status_t channel_read(struct channel* ch, struct channel_msg** msg_out) {
|
|||||||
return ZN_OK;
|
return ZN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No message and peer is gone — nothing will ever arrive.
|
// No message and peer is gone.
|
||||||
if (!ch->peer) {
|
if (!ch->peer) {
|
||||||
spin_unlock(&ch->lock);
|
spin_unlock(&ch->lock);
|
||||||
return ZN_ERR_BAD_HANDLE;
|
return ZN_ERR_BAD_HANDLE;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
// Like the standard C assert, but also active in debug builds.
|
// Like the standard C assert, but also active in debug builds.
|
||||||
#define assert(expr, msg, ...) \
|
#define assert(expr, msg, ...) \
|
||||||
({ \
|
do { \
|
||||||
if (__unlikely(!(expr))) { \
|
if (__unlikely(!(expr))) { \
|
||||||
panic( \
|
panic( \
|
||||||
"In function \"%s\" (%s:%u):\n" \
|
"In function \"%s\" (%s:%u):\n" \
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
##__VA_ARGS__ \
|
##__VA_ARGS__ \
|
||||||
); \
|
); \
|
||||||
} \
|
} \
|
||||||
})
|
} while (0)
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define debug_assert(...) assert(__VA_ARGS__)
|
#define debug_assert(...) assert(__VA_ARGS__)
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <zinnia/channel.h>
|
||||||
#include <zinnia/status.h>
|
#include <zinnia/status.h>
|
||||||
#include <kernel/spin.h>
|
#include <kernel/spin.h>
|
||||||
#include <kernel/tailq.h>
|
#include <kernel/tailq.h>
|
||||||
@@ -19,6 +22,7 @@ struct channel_msg {
|
|||||||
struct channel {
|
struct channel {
|
||||||
struct channel* peer;
|
struct channel* peer;
|
||||||
struct spinlock lock;
|
struct spinlock lock;
|
||||||
|
enum zn_channel_flags flags;
|
||||||
tailq_head(struct channel_msg) messages;
|
tailq_head(struct channel_msg) messages;
|
||||||
struct wait_queue waiters;
|
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);
|
void syscall_dispatch(struct arch_context* ctx);
|
||||||
|
|
||||||
zn_status_t syscall_log(struct arch_context* ctx);
|
#define DEFINE_SYSCALL(name) zn_status_t syscall_##name(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);
|
|
||||||
|
|
||||||
zn_status_t syscall_handle_validate(struct arch_context* ctx);
|
DEFINE_SYSCALL(log);
|
||||||
zn_status_t syscall_handle_drop(struct arch_context* ctx);
|
DEFINE_SYSCALL(archctl);
|
||||||
zn_status_t syscall_handle_clone(struct arch_context* ctx);
|
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);
|
DEFINE_SYSCALL(vas_create);
|
||||||
zn_status_t syscall_vmo_create_phys(struct arch_context* ctx);
|
|
||||||
zn_status_t syscall_vmo_map(struct arch_context* ctx);
|
|
||||||
|
|
||||||
zn_status_t syscall_channel_create(struct arch_context* ctx);
|
DEFINE_SYSCALL(vmo_create);
|
||||||
zn_status_t syscall_channel_wait(struct arch_context* ctx);
|
DEFINE_SYSCALL(vmo_create_phys);
|
||||||
zn_status_t syscall_channel_read(struct arch_context* ctx);
|
DEFINE_SYSCALL(vmo_map);
|
||||||
zn_status_t syscall_channel_write(struct arch_context* ctx);
|
|
||||||
|
|
||||||
zn_status_t syscall_thread_create(struct arch_context* ctx);
|
DEFINE_SYSCALL(channel_create);
|
||||||
zn_status_t syscall_thread_start(struct arch_context* ctx);
|
DEFINE_SYSCALL(channel_wait);
|
||||||
zn_status_t syscall_thread_exit(struct arch_context* ctx);
|
DEFINE_SYSCALL(channel_read);
|
||||||
|
DEFINE_SYSCALL(channel_write);
|
||||||
|
|
||||||
zn_status_t syscall_random_get(struct arch_context* ctx);
|
DEFINE_SYSCALL(thread_create);
|
||||||
zn_status_t syscall_random_entropy(struct arch_context* ctx);
|
DEFINE_SYSCALL(thread_start);
|
||||||
|
DEFINE_SYSCALL(thread_exit);
|
||||||
|
|
||||||
zn_status_t syscall_futex_wait(struct arch_context* ctx);
|
DEFINE_SYSCALL(random_get);
|
||||||
zn_status_t syscall_futex_wake(struct arch_context* ctx);
|
DEFINE_SYSCALL(random_entropy);
|
||||||
|
|
||||||
|
DEFINE_SYSCALL(futex_wait);
|
||||||
|
DEFINE_SYSCALL(futex_wake);
|
||||||
|
|||||||
+25
-19
@@ -12,8 +12,14 @@
|
|||||||
#include <kernel/usercopy.h>
|
#include <kernel/usercopy.h>
|
||||||
|
|
||||||
zn_status_t syscall_channel_create(struct arch_context* ctx) {
|
zn_status_t syscall_channel_create(struct arch_context* ctx) {
|
||||||
__user zn_handle_t* end0 = (__user zn_handle_t*)ctx->ARCH_CTX_A1;
|
auto flags = (enum zn_channel_flags)ctx->a0;
|
||||||
__user zn_handle_t* end1 = (__user zn_handle_t*)ctx->ARCH_CTX_A2;
|
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* ep0;
|
||||||
struct channel* ep1;
|
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_status_t syscall_channel_write(struct arch_context* ctx) {
|
||||||
zn_handle_t ch_handle = ctx->ARCH_CTX_A0;
|
auto ch_handle = (zn_handle_t)ctx->a0;
|
||||||
__user zn_handle_t* handles = (__user zn_handle_t*)ctx->ARCH_CTX_A1;
|
auto handles = (__user zn_handle_t*)ctx->a0;
|
||||||
__user void* bytes = (__user void*)ctx->ARCH_CTX_A2;
|
auto bytes = (__user void*)ctx->a2;
|
||||||
size_t num_handles = ctx->ARCH_CTX_A3;
|
size_t num_handles = ctx->a3;
|
||||||
size_t num_bytes = ctx->ARCH_CTX_A4;
|
size_t num_bytes = ctx->a4;
|
||||||
|
|
||||||
struct task* current = percpu_get()->sched.current;
|
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;
|
struct namespace_desc* descs = nullptr;
|
||||||
if (num_handles > 0) {
|
if (num_handles > 0) {
|
||||||
if (!handles) {
|
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_status_t syscall_channel_read(struct arch_context* ctx) {
|
||||||
zn_handle_t ch_handle = ctx->ARCH_CTX_A0;
|
zn_handle_t ch_handle = ctx->a0;
|
||||||
__user zn_handle_t* handles = (__user zn_handle_t*)ctx->ARCH_CTX_A1;
|
__user zn_handle_t* handles = (__user zn_handle_t*)ctx->a1;
|
||||||
__user void* bytes = (__user void*)ctx->ARCH_CTX_A2;
|
__user void* bytes = (__user void*)ctx->a2;
|
||||||
size_t num_handles = ctx->ARCH_CTX_A3;
|
size_t num_handles = ctx->a3;
|
||||||
size_t num_bytes = ctx->ARCH_CTX_A4;
|
size_t num_bytes = ctx->a4;
|
||||||
__user size_t* read_handles = (__user size_t*)ctx->ARCH_CTX_A5;
|
__user size_t* read_handles = (__user size_t*)ctx->a5;
|
||||||
__user size_t* read_bytes = (__user size_t*)ctx->ARCH_CTX_A6;
|
__user size_t* read_bytes = (__user size_t*)ctx->a6;
|
||||||
|
|
||||||
struct task* current = percpu_get()->sched.current;
|
struct task* current = percpu_get()->sched.current;
|
||||||
struct sched_percpu* sched = &percpu_get()->sched;
|
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) {
|
if (status == ZN_OK) {
|
||||||
// Copy byte data to userspace.
|
// 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 (bytes_to_copy > 0 && bytes) {
|
||||||
if (!usercopy_write(bytes, msg->data, bytes_to_copy)) {
|
if (!usercopy_write(bytes, msg->data, bytes_to_copy)) {
|
||||||
channel_msg_free(msg);
|
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.
|
// 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) {
|
if (handles_to_copy > 0 && handles) {
|
||||||
for (size_t i = 0; i < handles_to_copy; i++) {
|
for (size_t i = 0; i < handles_to_copy; i++) {
|
||||||
zn_handle_t new_handle;
|
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)
|
if (status == ZN_ERR_BAD_HANDLE)
|
||||||
return status;
|
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);
|
sched_block(sched, &ch->waiters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zn_status_t syscall_channel_wait(struct arch_context* ctx) {
|
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 task* current = percpu_get()->sched.current;
|
||||||
struct sched_percpu* sched = &percpu_get()->sched;
|
struct sched_percpu* sched = &percpu_get()->sched;
|
||||||
|
|||||||
+13
-13
@@ -15,8 +15,8 @@
|
|||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
zn_status_t syscall_vmo_create(struct arch_context* ctx) {
|
zn_status_t syscall_vmo_create(struct arch_context* ctx) {
|
||||||
size_t length = ctx->ARCH_CTX_A0;
|
size_t length = ctx->a0;
|
||||||
__user zn_handle_t* out = (__user zn_handle_t*)ctx->ARCH_CTX_A1;
|
__user zn_handle_t* out = (__user zn_handle_t*)ctx->a1;
|
||||||
|
|
||||||
// Allocate new VMO.
|
// Allocate new VMO.
|
||||||
struct paged_vmo* 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) {
|
zn_status_t syscall_vmo_create_phys(struct arch_context* ctx) {
|
||||||
uintptr_t addr = ctx->ARCH_CTX_A0;
|
uintptr_t addr = ctx->a0;
|
||||||
size_t length = ctx->ARCH_CTX_A1;
|
size_t length = ctx->a1;
|
||||||
__user zn_handle_t* out = (__user zn_handle_t*)ctx->ARCH_CTX_A2;
|
__user zn_handle_t* out = (__user zn_handle_t*)ctx->a2;
|
||||||
|
|
||||||
struct vmo* vmo;
|
struct vmo* vmo;
|
||||||
zn_status_t status = vmo_new_phys_range(addr, length, &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_status_t syscall_vmo_map(struct arch_context* ctx) {
|
||||||
zn_handle_t vmo_handle = ctx->ARCH_CTX_A0;
|
zn_handle_t vmo_handle = ctx->a0;
|
||||||
zn_handle_t vas_handle = ctx->ARCH_CTX_A1;
|
zn_handle_t vas_handle = ctx->a1;
|
||||||
uintptr_t vmo_offset = ctx->ARCH_CTX_A2;
|
uintptr_t vmo_offset = ctx->a2;
|
||||||
__user uintptr_t* addr = (__user uintptr_t*)ctx->ARCH_CTX_A3;
|
auto addr = (__user uintptr_t*)ctx->a3;
|
||||||
size_t bytes = ctx->ARCH_CTX_A4;
|
size_t bytes = ctx->a4;
|
||||||
enum zn_vm_flags flags = ctx->ARCH_CTX_A5;
|
enum zn_vm_flags flags = ctx->a5;
|
||||||
|
|
||||||
struct task* current = percpu_get()->sched.current;
|
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.
|
// TODO: Use actual allocator for user task.
|
||||||
if (target_addr == 0) {
|
if (target_addr == 0) {
|
||||||
static uintptr_t map_offset = 0xA000'0000;
|
static _Atomic uintptr_t map_offset = 0xA000'0000;
|
||||||
target_addr = atomic_fetch_add(&map_offset, ALIGN_UP(bytes, arch_mem_page_size()));
|
target_addr = atomic_fetch_add((volatile uintptr_t*)&map_offset, ALIGN_UP(bytes, arch_mem_page_size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr != nullptr) {
|
if (addr != nullptr) {
|
||||||
|
|||||||
Reference in New Issue
Block a user