diff options
author | dzwdz | 2024-05-19 20:59:38 +0200 |
---|---|---|
committer | dzwdz | 2024-05-19 20:59:38 +0200 |
commit | 317da94139c592d20e90a4f74cdb67c620d72d4a (patch) | |
tree | 14c9a306914e4f38baddd227ed55d346929f0d96 /src | |
parent | 8fdf6a24736fd676cbd28de11b21a31b2fd6664e (diff) |
kernel: implement /dev/bintime
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/tests/kernel/time.c | 49 | ||||
-rw-r--r-- | src/cmd/tests/tests.c | 1 | ||||
-rw-r--r-- | src/cmd/tests/tests.h | 1 | ||||
-rw-r--r-- | src/kernel/arch/amd64/boot.c | 1 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/driver.h | 1 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/time.c | 80 |
6 files changed, 133 insertions, 0 deletions
diff --git a/src/cmd/tests/kernel/time.c b/src/cmd/tests/kernel/time.c new file mode 100644 index 0000000..476a90a --- /dev/null +++ b/src/cmd/tests/kernel/time.c @@ -0,0 +1,49 @@ +#include "../tests.h" +#include <camellia.h> + +static void +test_settime(void) { + uint64_t ns = 1000000000; + uint64_t base = 1337 * ns; + union { + uint64_t t; + char buf[8]; + } u; + + hid_t h = camellia_open("/dev/bintime", OPEN_RW); + + /* check if time is reasonable */ + test(h >= 0); + test(_sys_read(h, u.buf, 8, 0) == 8); + test(0 < u.t); + test(u.t < ns); /* this should've taken less than a second */ + + /* try changing the time */ + u.t = base; + test(_sys_write(h, u.buf, 8, 0, 0) == 8); + + /* did we succeed? */ + u.t = 0; + test(_sys_read(h, u.buf, 8, 0) == 8); + test(base < u.t); + test(u.t < base + ns); + + /* clone the handle */ + hid_t h2 = _sys_dup(h, 0, DUP_SEARCH | DUP_RDONLY); + test(h2 >= 0); + + /* i shouldn't be able to write to it */ + u.t = 0; + test(_sys_write(h2, u.buf, 8, 0, 0) == -EACCES); + + /* but reads should be fine */ + test(_sys_read(h2, u.buf, 8, 0) == 8); + test(base < u.t); + test(u.t < base + ns); +} + +void +r_k_time(void) +{ + run_test(test_settime); +} diff --git a/src/cmd/tests/tests.c b/src/cmd/tests/tests.c index 2b7ba01..2b66b43 100644 --- a/src/cmd/tests/tests.c +++ b/src/cmd/tests/tests.c @@ -54,6 +54,7 @@ int main(void) { r_k_misc(); r_k_path(); r_k_threads(); + r_k_time(); r_libc_esemaphore(); r_libc_setjmp(); r_libc_string(); diff --git a/src/cmd/tests/tests.h b/src/cmd/tests/tests.h index bbf5309..f562d27 100644 --- a/src/cmd/tests/tests.h +++ b/src/cmd/tests/tests.h @@ -13,6 +13,7 @@ void r_k_misc(void); void r_k_miscsyscall(void); void r_k_path(void); void r_k_threads(void); +void r_k_time(void); void r_libc_esemaphore(void); void r_libc_setjmp(void); void r_libc_string(void); diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c index 19f249a..14690a8 100644 --- a/src/kernel/arch/amd64/boot.c +++ b/src/kernel/arch/amd64/boot.c @@ -70,6 +70,7 @@ void kmain_early(void *mbi) { serial_init(); video_init(vid); pata_init(); + time_init(); { struct multiboot_tag_old_acpi *mod; diff --git a/src/kernel/arch/amd64/driver/driver.h b/src/kernel/arch/amd64/driver/driver.h index 0c4ecd5..6f862cf 100644 --- a/src/kernel/arch/amd64/driver/driver.h +++ b/src/kernel/arch/amd64/driver/driver.h @@ -14,5 +14,6 @@ struct GfxInfo { void pata_init(void); void ps2_init(void); void rtl8139_init(uint32_t bdf); +void time_init(void); void vfs_root_init(void); void video_init(GfxInfo); diff --git a/src/kernel/arch/amd64/driver/time.c b/src/kernel/arch/amd64/driver/time.c new file mode 100644 index 0000000..8ae6fb2 --- /dev/null +++ b/src/kernel/arch/amd64/driver/time.c @@ -0,0 +1,80 @@ +/* This is already sort of deprecated as I introduce it -- + * it doesn't seem to provide much benefit over _sys_time, which I think I + * have to keep anyways, so processes in an empty namespace can still keep + * time. */ +#include <camellia/errno.h> +#include <camellia/fsutil.h> +#include <kernel/arch/amd64/driver/driver.h> +#include <kernel/arch/amd64/driver/util.h> +#include <kernel/malloc.h> +#include <kernel/panic.h> +#include <kernel/proc.h> +#include <kernel/util.h> +#include <kernel/vfs/mount.h> +#include <kernel/vfs/request.h> +#include <shared/mem.h> + +typedef struct { + uint64_t base; +} TimeObj; + +static long +handle(VfsReq *req) +{ + TimeObj *h; + if (req->type == VFSOP_OPEN) { + if (reqpathcmp(req, "")) { + h = kmalloc(sizeof *h, "dev/time"); + h->base = uptime_ns(); + return (uintptr_t)h; + } else { + return -ENOENT; + } + } + h = (__force void*)req->id; + + if (req->type == VFSOP_CLOSE) { + assert(h); + kfree(h); + return 0; + } + + uint64_t now = uptime_ns(); + + union { + char buf[8]; + uint64_t t; + } u; + switch (req->type) { + case VFSOP_READ: + u.t = now - h->base; + return req_readcopy(req, u.buf, sizeof u.buf); + case VFSOP_GETSIZE: + return 8; + case VFSOP_WRITE: + if (req->input.len == 8) { + assert(!req->input.kern); + if (pcpy_from(req->caller, u.buf, req->input.buf, sizeof u.buf) != sizeof(u.buf)) { + return -EGENERIC; + } + h->base = now - u.t; + assert(u.t == now - h->base); + return 8; + } + return -EGENERIC; + default: + return -ENOSYS; + } +} + +static void +accept(VfsReq *req) +{ + vfsreq_finish_short(req, handle(req)); +} + +void +time_init(void) +{ + vfs_root_register("/dev/bintime", accept); +} |