From 94aaa83e0cadf744afca486d306de73cec502928 Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 15 Nov 2023 17:11:05 +1100 Subject: [PATCH 01/23] Disable ethernet in Kitty system's graphics VM --- examples/kitty/kitty.system | 4 ---- examples/kitty/src/vmm/images/linux.dts | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/kitty/kitty.system b/examples/kitty/kitty.system index 5761efb7..cfeb715a 100644 --- a/examples/kitty/kitty.system +++ b/examples/kitty/kitty.system @@ -57,12 +57,8 @@ - - - - diff --git a/examples/kitty/src/vmm/images/linux.dts b/examples/kitty/src/vmm/images/linux.dts index 7c5cb174..71b02e7c 100644 --- a/examples/kitty/src/vmm/images/linux.dts +++ b/examples/kitty/src/vmm/images/linux.dts @@ -162,7 +162,7 @@ clock-names = "stmmaceth\0clkin0\0clkin1\0timing-adjustment"; rx-fifo-depth = <0x1000>; tx-fifo-depth = <0x800>; - status = "okay"; + status = "disabled"; power-domains = <0x03 0x06>; pinctrl-0 = <0x07 0x08>; pinctrl-names = "default"; From 32b90b19d67ad0d39f3761f345ed6c0d14525fc9 Mon Sep 17 00:00:00 2001 From: James Archer Date: Fri, 17 Nov 2023 14:33:15 +1100 Subject: [PATCH 02/23] Add NFS client with Micropython stdlib support --- .gitmodules | 13 +- examples/kitty/Makefile | 79 ++- examples/kitty/kitty.system | 76 ++- examples/kitty/src/micropython/Makefile | 24 +- examples/kitty/src/micropython/micropython.c | 45 +- examples/kitty/src/micropython/micropython.h | 5 + examples/kitty/src/micropython/modtime.c | 6 +- examples/kitty/src/micropython/mpconfigport.h | 41 +- examples/kitty/src/micropython/sddf_fs.c | 199 +++++++ examples/kitty/src/micropython/sddf_fs.h | 56 ++ examples/kitty/src/micropython/vfs_sddf_fs.c | 281 +++++++++ examples/kitty/src/micropython/vfs_sddf_fs.h | 10 + .../kitty/src/micropython/vfs_sddf_fs_file.c | 191 ++++++ fs/include/fs/protocol.h | 48 ++ fs/nfs/Makefile | 129 ++++ fs/nfs/fd.c | 212 +++++++ fs/nfs/fd.h | 19 + fs/nfs/lwip_include/arch/cc.h | 74 +++ fs/nfs/lwip_include/lwipopts.h | 67 +++ fs/nfs/nfs.c | 90 +++ fs/nfs/nfs.h | 4 + fs/nfs/op.c | 528 +++++++++++++++++ fs/nfs/posix.c | 390 ++++++++++++ fs/nfs/posix.h | 2 + fs/nfs/tcp.c | 556 ++++++++++++++++++ fs/nfs/tcp.h | 17 + fs/nfs/util.h | 41 ++ libnfs | 1 + musllibc | 1 + 29 files changed, 3153 insertions(+), 52 deletions(-) create mode 100644 examples/kitty/src/micropython/sddf_fs.c create mode 100644 examples/kitty/src/micropython/sddf_fs.h create mode 100644 examples/kitty/src/micropython/vfs_sddf_fs.c create mode 100644 examples/kitty/src/micropython/vfs_sddf_fs.h create mode 100644 examples/kitty/src/micropython/vfs_sddf_fs_file.c create mode 100644 fs/include/fs/protocol.h create mode 100644 fs/nfs/Makefile create mode 100644 fs/nfs/fd.c create mode 100644 fs/nfs/fd.h create mode 100644 fs/nfs/lwip_include/arch/cc.h create mode 100644 fs/nfs/lwip_include/lwipopts.h create mode 100644 fs/nfs/nfs.c create mode 100644 fs/nfs/nfs.h create mode 100644 fs/nfs/op.c create mode 100644 fs/nfs/posix.c create mode 100644 fs/nfs/posix.h create mode 100644 fs/nfs/tcp.c create mode 100644 fs/nfs/tcp.h create mode 100644 fs/nfs/util.h create mode 160000 libnfs create mode 160000 musllibc diff --git a/.gitmodules b/.gitmodules index b9bb8d2c..82968620 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,19 @@ [submodule "libvmm"] path = vmm url = https://github.com/au-ts/libvmm.git - branch = main + branch = main [submodule "sddf"] path = sddf url = https://github.com/au-ts/sddf.git - branch = kiss + branch = kiss [submodule "micropython"] path = micropython url = https://github.com/Ivan-Velickovic/micropython.git - branch = kiss + branch = kiss +[submodule "musllibc"] + path = musllibc + url = git@github.com:au-ts/musllibc.git + branch = sel4 +[submodule "libnfs"] + path = libnfs + url = git@github.com:au-ts/libnfs.git diff --git a/examples/kitty/Makefile b/examples/kitty/Makefile index 1611343a..fd47f8b0 100644 --- a/examples/kitty/Makefile +++ b/examples/kitty/Makefile @@ -8,6 +8,10 @@ ifeq ($(strip $(MICROKIT_SDK)),) $(error MICROKIT_SDK must be specified) endif +ifeq ($(strip $(LIBGCC)),) +$(error LIBGCC must be specified: this should be the directory where libgcc.a can be found) +endif + MICROKIT_CONFIG ?= debug BUILD_DIR ?= $(abspath build) MICROKIT_BOARD := odroidc4 @@ -30,10 +34,14 @@ INITRD := $(VMM_IMAGE_DIR)/rootfs.cpio.gz DTS := $(VMM_IMAGE_DIR)/linux.dts DTB := $(BUILD_DIR)/linux.dtb -IMAGES := main.elf micropython.elf timer.elf vmm.elf -CFLAGS := -mtune=$(CPU) -mstrict-align -ffreestanding -g3 -O3 -Wall -Wno-unused-function -I$(BOARD_DIR)/include -target $(TARGET) \ - -I$(LIBVMM)/src/arch/aarch64 -I$(LIBVMM)/src -I$(LIBVMM)/src/util -DBOARD_$(MICROKIT_BOARD) -LDFLAGS := -L$(BOARD_DIR)/lib +LWIP=$(SDDF)/network/ipstacks/lwip/src +LIBNFS=../../libnfs +NFS=../../fs/nfs +MUSL=../../musllibc + +IMAGES := main.elf timer.elf vmm.elf ethernet.elf micropython.elf nfs.elf +CFLAGS := -mtune=$(CPU) -mstrict-align -ffreestanding -g -O0 -Wall -Wno-unused-function -I$(BOARD_DIR)/include -target $(TARGET) -I$(LIBVMM)/src/arch/aarch64 -I$(LIBVMM)/src -I$(LIBVMM)/src/util -DBOARD_$(MICROKIT_BOARD) +LDFLAGS := -L$(BOARD_DIR)/lib LIBS := -lmicrokit -Tmicrokit.ld IMAGE_FILE := $(BUILD_DIR)/kitty.img @@ -50,7 +58,7 @@ TIMER_DRIVER := $(SDDF)/drivers/clock/meson PACKAGE_PYTHON_SCRIPTS := src/package_python_scripts.S -all: $(BUILD_DIR) $(IMAGE_FILE) +all: $(DIRECTORIES) $(BUILD_DIR) $(IMAGE_FILE) $(BUILD_DIR): mkdir -p $(BUILD_DIR) @@ -102,13 +110,70 @@ $(BUILD_DIR)/package_python_scripts.o: $(PACKAGE_PYTHON_SCRIPTS) src/kitty.py -target $(TARGET) \ $< -o $@ -$(BUILD_DIR)/micropython.elf:$(BUILD_DIR)/package_python_scripts.o +$(BUILD_DIR)/micropython.elf: FORCE $(BUILD_DIR)/package_python_scripts.o $(BUILD_DIR)/sddf_timer_client.o make -C src/micropython -j$(nproc) \ MICROKIT_SDK=$(MICROKIT_SDK) \ MICROKIT_BOARD=$(MICROKIT_BOARD) \ MICROKIT_CONFIG=$(MICROKIT_CONFIG) \ - BUILD=$(BUILD_DIR) \ + BUILD=$(abspath $(BUILD_DIR)) \ PACKAGE_PYTHON_SCRIPTS=package_python_scripts.o +ETHERNET=$(SDDF)/drivers/network/meson/ +$(BUILD_DIR)/meson_ethernet.o: FORCE + BUILD_DIR=$(abspath $(BUILD_DIR)) MICROKIT_INCLUDE=$(BOARD_DIR)/include make -C $(ETHERNET) + +LIBSHAREDRINGBUFFER=$(SDDF)/network/libethsharedringbuffer/ +$(BUILD_DIR)/sddf_network_sharedringbuffer.o: FORCE + BUILD_DIR=$(abspath $(BUILD_DIR)) MICROKIT_INCLUDE=$(BOARD_DIR)/include make -C $(LIBSHAREDRINGBUFFER) + +$(BUILD_DIR)/sddf_timer_client.o: FORCE + BUILD_DIR=$(abspath $(BUILD_DIR)) MICROKIT_INCLUDE=$(BOARD_DIR)/include TIMER_CHANNEL=9 make -C $(SDDF)/timer/client + +$(BUILD_DIR)/musllibc/lib/libc.a: + make -C $(MUSL) \ + C_COMPILER=aarch64-none-elf-gcc \ + TOOLPREFIX=aarch64-none-elf- \ + CONFIG_ARCH_AARCH64=y \ + STAGE_DIR=$(abspath $(BUILD_DIR)/musllibc) \ + SOURCE_DIR=. + +$(BUILD_DIR)/libnfs/lib/libnfs.a: $(BUILD_DIR)/musllibc/lib/libc.a + MUSL=$(abspath $(BUILD_DIR)/musllibc) cmake -S ../../libnfs -B $(BUILD_DIR)/libnfs + cmake --build $(BUILD_DIR)/libnfs + +$(BUILD_DIR)/nfs/nfs.a: FORCE $(BUILD_DIR)/musllibc/lib/libc.a + make -C $(NFS) \ + BUILD_DIR=$(abspath $(BUILD_DIR)/nfs) \ + MICROKIT_INCLUDE=$(BOARD_DIR)/include \ + MUSLLIBC_INCLUDE=$(abspath $(BUILD_DIR)/musllibc/include) \ + LIBNFS_INCLUDE=$(abspath ../..//libnfs/include) + +$(BUILD_DIR)/nfs.elf: $(BUILD_DIR)/nfs/nfs.a $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/sddf_timer_client.o $(BUILD_DIR)/libnfs/lib/libnfs.a $(BUILD_DIR)/musllibc/lib/libc.a + $(LD) \ + $(LDFLAGS) \ + $(BUILD_DIR)/nfs/nfs.a \ + $(BUILD_DIR)/sddf_network_sharedringbuffer.o \ + $(BUILD_DIR)/sddf_timer_client.o \ + -L$(BUILD_DIR)/libnfs/lib \ + -L$(BUILD_DIR)/musllibc/lib \ + -L$(LIBGCC) \ + -lgcc \ + -lc \ + $(LIBS) \ + -lnfs \ + -o $(BUILD_DIR)/nfs.elf + +$(BUILD_DIR)/ethernet.elf: $(BUILD_DIR)/meson_ethernet.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o + $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ + +directories: + $(info $(shell mkdir -p $(BUILD_DIR)/lwip/src)) \ + $(info $(shell mkdir -p $(BUILD_DIR)/lwip/src/core)) \ + $(info $(shell mkdir -p $(BUILD_DIR)/lwip/src/netif)) \ + $(info $(shell mkdir -p $(BUILD_DIR)/lwip/src/core/ipv4)) \ + $(info $(shell mkdir -p $(BUILD_DIR)/nfs)) + $(IMAGE_FILE) $(REPORT_FILE): $(addprefix $(BUILD_DIR)/, $(IMAGES)) kitty.system $(MICROKIT_TOOL) kitty.system --search-path $(BUILD_DIR) --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) + +FORCE: ; diff --git a/examples/kitty/kitty.system b/examples/kitty/kitty.system index cfeb715a..c6a7894b 100644 --- a/examples/kitty/kitty.system +++ b/examples/kitty/kitty.system @@ -3,13 +3,16 @@ + + + - + - + @@ -22,7 +25,17 @@ + + + + + + + + + + @@ -79,6 +92,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/kitty/src/micropython/sddf_fs.c b/examples/kitty/src/micropython/sddf_fs.c index bbdc2d11..5621300b 100644 --- a/examples/kitty/src/micropython/sddf_fs.c +++ b/examples/kitty/src/micropython/sddf_fs.c @@ -6,8 +6,10 @@ struct open_response sddf_fs_open(const char *filename) { - strcpy(nfs_share, filename); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_OPEN, 1)); + uint32_t cmd = SDDF_FS_CMD_OPEN; + memcpy(nfs_share, &cmd, 4); + strcpy(nfs_share + 4, filename); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -24,17 +26,23 @@ struct open_response sddf_fs_open(const char *filename) int sddf_fs_close(uint64_t fd) { - microkit_mr_set(0, (uint64_t)fd); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_CLOSE, 1)); + uint32_t cmd = SDDF_FS_CMD_CLOSE; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + microkit_notify(NFS_CH); + await(mp_event_source_nfs); + return *(int *)nfs_share; } struct read_response sddf_fs_pread(uint64_t fd, uint64_t nbyte, uint64_t offset) { - microkit_mr_set(0, (uint64_t)fd); - microkit_mr_set(1, nbyte); - microkit_mr_set(2, offset); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_PREAD, 3)); + uint32_t cmd = SDDF_FS_CMD_PREAD; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + memcpy(nfs_share + 12, &nbyte, 8); + memcpy(nfs_share + 20, &offset, 8); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -51,11 +59,13 @@ struct read_response sddf_fs_pread(uint64_t fd, uint64_t nbyte, uint64_t offset) } int sddf_fs_pwrite(uint64_t fd, const char *buf, uint64_t nbyte, uint64_t offset) { - memcpy(nfs_share, buf, nbyte); - microkit_mr_set(0, (uint64_t)fd); - microkit_mr_set(1, nbyte); - microkit_mr_set(2, offset); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_PWRITE, 3)); + uint32_t cmd = SDDF_FS_CMD_PWRITE; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + memcpy(nfs_share + 12, &nbyte, 8); + memcpy(nfs_share + 20, &offset, 8); + memcpy(nfs_share + 28, buf, nbyte); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -63,10 +73,11 @@ int sddf_fs_pwrite(uint64_t fd, const char *buf, uint64_t nbyte, uint64_t offset return status; } -struct stat_response sddf_fs_stat(const char *filename) -{ - strcpy(nfs_share, filename); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_STAT, 0)); +struct stat_response sddf_fs_stat(const char *filename) { + uint32_t cmd = SDDF_FS_CMD_STAT; + memcpy(nfs_share, &cmd, 4); + strcpy(nfs_share + 4, filename); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -81,13 +92,15 @@ struct stat_response sddf_fs_stat(const char *filename) } int sddf_fs_rename(const char *oldpath, const char *newpath) { - int oldpath_len = strlen(oldpath); - int newpath_len = strlen(newpath); - strcpy(nfs_share, oldpath); - strcpy(nfs_share + oldpath_len + 1, newpath); - microkit_mr_set(0, 0); - microkit_mr_set(1, oldpath_len + 1); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_RENAME, 2)); + uint32_t cmd = SDDF_FS_CMD_RENAME; + uint64_t oldpath_offset = 20; + uint64_t newpath_offset = oldpath_offset + strlen(oldpath) + 1; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &oldpath_offset, 8); + memcpy(nfs_share + 12, &newpath_offset, 8); + strcpy(nfs_share + oldpath_offset, oldpath); + strcpy(nfs_share + newpath_offset, newpath); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -96,8 +109,10 @@ int sddf_fs_rename(const char *oldpath, const char *newpath) { } int sddf_fs_unlink(const char *path) { - strcpy(nfs_share, path); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_UNLINK, 0)); + uint32_t cmd = SDDF_FS_CMD_UNLINK; + memcpy(nfs_share, &cmd, 4); + strcpy(nfs_share + 4, path); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -106,8 +121,10 @@ int sddf_fs_unlink(const char *path) { } int sddf_fs_mkdir(const char *path) { - strcpy(nfs_share, path); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_MKDIR, 0)); + uint32_t cmd = SDDF_FS_CMD_MKDIR; + memcpy(nfs_share, &cmd, 4); + strcpy(nfs_share + 4, path); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -116,8 +133,10 @@ int sddf_fs_mkdir(const char *path) { } int sddf_fs_rmdir(const char *path) { - strcpy(nfs_share, path); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_RMDIR, 0)); + uint32_t cmd = SDDF_FS_CMD_RMDIR; + memcpy(nfs_share, &cmd, 4); + strcpy(nfs_share + 4, path); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -126,8 +145,10 @@ int sddf_fs_rmdir(const char *path) { } int sddf_fs_closedir(uint64_t fd) { - microkit_mr_set(0, fd); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_CLOSEDIR, 1)); + uint32_t cmd = SDDF_FS_CMD_CLOSEDIR; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -136,8 +157,10 @@ int sddf_fs_closedir(uint64_t fd) { } int sddf_fs_fsync(uint64_t fd) { - microkit_mr_set(0, fd); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_FSYNC, 1)); + uint32_t cmd = SDDF_FS_CMD_FSYNC; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -146,16 +169,20 @@ int sddf_fs_fsync(uint64_t fd) { } void sddf_fs_seekdir(uint64_t fd, long loc) { - microkit_mr_set(0, fd); - microkit_mr_set(1, loc); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_SEEKDIR, 2)); + uint32_t cmd = SDDF_FS_CMD_CLOSEDIR; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + memcpy(nfs_share + 12, &loc, 8); + microkit_notify(NFS_CH); await(mp_event_source_nfs); } long sddf_fs_telldir(uint64_t fd) { - microkit_mr_set(0, fd); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_TELLDIR, 1)); + uint32_t cmd = SDDF_FS_CMD_TELLDIR; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -164,15 +191,19 @@ long sddf_fs_telldir(uint64_t fd) { } void sddf_fs_rewinddir(uint64_t fd) { - microkit_mr_set(0, fd); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_REWINDDIR, 1)); + uint32_t cmd = SDDF_FS_CMD_REWINDDIR; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + microkit_notify(NFS_CH); await(mp_event_source_nfs); } int sddf_fs_opendir(const char *in_path, uint64_t *out_fd) { - strcpy(nfs_share, in_path); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_OPENDIR, 0)); + uint32_t cmd = SDDF_FS_CMD_OPENDIR; + memcpy(nfs_share, &cmd, 4); + strcpy(nfs_share + 4, in_path); + microkit_notify(NFS_CH); await(mp_event_source_nfs); @@ -185,8 +216,10 @@ int sddf_fs_opendir(const char *in_path, uint64_t *out_fd) { } int sddf_fs_readdir(uint64_t fd, char **out_name) { - microkit_mr_set(0, fd); - microkit_ppcall(NFS_CH, microkit_msginfo_new(SDDF_FS_CMD_READDIR, 1)); + uint32_t cmd = SDDF_FS_CMD_READDIR; + memcpy(nfs_share, &cmd, 4); + memcpy(nfs_share + 4, &fd, 8); + microkit_notify(NFS_CH); await(mp_event_source_nfs); diff --git a/fs/nfs/nfs.c b/fs/nfs/nfs.c index 36d8f710..990fab70 100644 --- a/fs/nfs/nfs.c +++ b/fs/nfs/nfs.c @@ -35,11 +35,6 @@ void nfs_init(void) { dlogp(err, "failed to connect to nfs server"); } -seL4_MessageInfo_t protected(microkit_channel ch, microkit_msginfo msginfo) { - nfs_protected(ch, msginfo); - return microkit_msginfo_new(0, 0); -} - void notified(microkit_channel ch) { sddf_timer_set_timeout(TIMEOUT); switch (ch) { @@ -74,6 +69,7 @@ void notified(microkit_channel ch) { tcp_process_rx(); break; case CLIENT_CHANNEL: { + nfs_notified(); break; } default: diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index fd574455..b8c7095c 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -1,4 +1,4 @@ extern char *client_share; extern struct nfs_context *nfs; -void nfs_protected(microkit_channel ch, microkit_msginfo msginfo); +void nfs_notified(void); diff --git a/fs/nfs/op.c b/fs/nfs/op.c index 603ffa69..e85e0e4e 100644 --- a/fs/nfs/op.c +++ b/fs/nfs/op.c @@ -181,7 +181,7 @@ void pwrite_cb(int status, struct nfs_context *nfs, void *data, void *private_da microkit_notify(CLIENT_CHANNEL); } -void handle_pwrite(fd_t fd, uint64_t nbyte, uint64_t offset) { +void handle_pwrite(fd_t fd, char *buf, uint64_t nbyte, uint64_t offset) { int err; struct nfsfh *file_handle = NULL; @@ -191,7 +191,7 @@ void handle_pwrite(fd_t fd, uint64_t nbyte, uint64_t offset) { goto fail_begin; } - err = nfs_pwrite_async(nfs, file_handle, offset, nbyte, client_share, pwrite_cb, (void *)fd); + err = nfs_pwrite_async(nfs, file_handle, offset, nbyte, buf, pwrite_cb, (void *)fd); if (err) { dlog("failed to enqueue command"); goto fail_enqueue; @@ -437,92 +437,108 @@ void handle_rewinddir(fd_t fd) { microkit_notify(CLIENT_CHANNEL); } -void nfs_protected(microkit_channel ch, microkit_msginfo msginfo) { - switch (microkit_msginfo_get_label(msginfo)) { - case SDDF_FS_CMD_STAT: { - handle_stat64(client_share); +void nfs_notified(void) { + uint32_t cmd; + memcpy(&cmd, client_share, 4); + switch (cmd) { + case SDDF_FS_CMD_OPEN: { + handle_open(client_share + 4, O_RDWR | O_CREAT, O_RDWR); break; } - case SDDF_FS_CMD_OPEN: { - handle_open(client_share, O_RDWR | O_CREAT, O_RDWR); + case SDDF_FS_CMD_STAT: { + handle_stat64(client_share + 4); break; } case SDDF_FS_CMD_CLOSE: { - fd_t fd = (int)microkit_mr_get(0); + fd_t fd; + memcpy(&fd, client_share + 4, 8); handle_close(fd); break; } case SDDF_FS_CMD_PREAD: { - fd_t fd = (int)microkit_mr_get(0); - uint64_t nbyte = microkit_mr_get(1); - uint64_t offset = microkit_mr_get(2); + fd_t fd; + uint64_t nbyte, offset; + memcpy(&fd, client_share + 4, 8); + memcpy(&nbyte, client_share + 12, 8); + memcpy(&offset, client_share + 20, 8); handle_pread(fd, nbyte, offset); break; } case SDDF_FS_CMD_PWRITE: { - fd_t fd = (int)microkit_mr_get(0); - uint64_t nbyte = microkit_mr_get(1); - uint64_t offset = microkit_mr_get(2); - handle_pwrite(fd, nbyte, offset); + fd_t fd; + uint64_t nbyte, offset; + memcpy(&fd, client_share + 4, 8); + memcpy(&nbyte, client_share + 12, 8); + memcpy(&offset, client_share + 20, 8); + char *buf = client_share + 28; + handle_pwrite(fd, buf, nbyte, offset); break; } case SDDF_FS_CMD_RENAME: { - int oldpath_offset = microkit_mr_get(0); - int newpath_offset = microkit_mr_get(1); - const char *oldpath = client_share + oldpath_offset; - const char *newpath = client_share + newpath_offset; + uint64_t oldpath_offset, newpath_offset; + memcpy(&oldpath_offset, client_share + 4, 8); + memcpy(&newpath_offset, client_share + 12, 8); + char *oldpath = client_share + oldpath_offset; + char *newpath = client_share + newpath_offset; handle_rename(oldpath, newpath); break; } case SDDF_FS_CMD_UNLINK: { - handle_unlink(client_share); + handle_unlink(client_share + 4); break; } case SDDF_FS_CMD_MKDIR: { - handle_mkdir(client_share); + handle_mkdir(client_share + 4); break; } case SDDF_FS_CMD_RMDIR: { - handle_rmdir(client_share); + handle_rmdir(client_share + 4); break; } case SDDF_FS_CMD_OPENDIR: { - handle_opendir(client_share); + handle_opendir(client_share + 4); break; } case SDDF_FS_CMD_CLOSEDIR: { - fd_t fd = (fd_t)microkit_mr_get(0); + fd_t fd; + memcpy(&fd, client_share + 4, 8); handle_closedir(fd); break; } case SDDF_FS_CMD_READDIR: { - fd_t fd = microkit_mr_get(0); + fd_t fd; + memcpy(&fd, client_share + 4, 8); handle_readdir(fd); break; } case SDDF_FS_CMD_FSYNC: { - fd_t fd = (fd_t)microkit_mr_get(0); + fd_t fd; + memcpy(&fd, client_share + 4, 8); handle_fsync(fd); break; } case SDDF_FS_CMD_SEEKDIR: { - fd_t fd = (fd_t)microkit_mr_get(0); - long loc = (fd_t)microkit_mr_get(1); + fd_t fd; + int64_t loc; + memcpy(&fd, client_share + 4, 8); + memcpy(&loc, client_share + 12, 8); handle_seekdir(fd, loc); break; } case SDDF_FS_CMD_TELLDIR: { - fd_t fd = (fd_t)microkit_mr_get(0); + fd_t fd; + memcpy(&fd, client_share + 4, 8); handle_telldir(fd); break; } case SDDF_FS_CMD_REWINDDIR: { - fd_t fd = (fd_t)microkit_mr_get(0); + fd_t fd; + memcpy(&fd, client_share + 4, 8); handle_rewinddir(fd); break; } default: - dlog("unknown ppcall operation"); + dlog("unknown fs operation"); break; } } From f7fd34a945dd81a46e95826b0299edc3328d3bf1 Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 08:36:15 +1100 Subject: [PATCH 04/23] Make NFS client API asynchronous This commit modifies the NFS client to: - provide an asynchronous API; - use ringbuffers for communicating with clients; - support running multiple operations concurrently; - bounds-check client-provided buffers; - allocate continuations from a pool instead of using malloc. It also modifies the MicroPython FS support to the new NFS client interface. --- examples/kitty/Makefile | 9 +- examples/kitty/kitty.system | 8 +- examples/kitty/src/micropython/Makefile | 2 +- examples/kitty/src/micropython/sddf_fs.c | 273 ++++------ examples/kitty/src/micropython/sddf_fs.h | 21 +- fs/include/fs/protocol.h | 58 ++- fs/nfs/nfs.c | 4 +- fs/nfs/nfs.h | 2 +- fs/nfs/op.c | 621 +++++++++++++++++------ fs/protocol/Makefile | 25 + fs/protocol/protocol.c | 24 + 11 files changed, 676 insertions(+), 371 deletions(-) create mode 100644 fs/protocol/Makefile create mode 100644 fs/protocol/protocol.c diff --git a/examples/kitty/Makefile b/examples/kitty/Makefile index fd47f8b0..b411a342 100644 --- a/examples/kitty/Makefile +++ b/examples/kitty/Makefile @@ -110,7 +110,7 @@ $(BUILD_DIR)/package_python_scripts.o: $(PACKAGE_PYTHON_SCRIPTS) src/kitty.py -target $(TARGET) \ $< -o $@ -$(BUILD_DIR)/micropython.elf: FORCE $(BUILD_DIR)/package_python_scripts.o $(BUILD_DIR)/sddf_timer_client.o +$(BUILD_DIR)/micropython.elf: FORCE $(BUILD_DIR)/package_python_scripts.o $(BUILD_DIR)/sddf_timer_client.o $(BUILD_DIR)/sddf_fs_protocol.o make -C src/micropython -j$(nproc) \ MICROKIT_SDK=$(MICROKIT_SDK) \ MICROKIT_BOARD=$(MICROKIT_BOARD) \ @@ -129,6 +129,10 @@ $(BUILD_DIR)/sddf_network_sharedringbuffer.o: FORCE $(BUILD_DIR)/sddf_timer_client.o: FORCE BUILD_DIR=$(abspath $(BUILD_DIR)) MICROKIT_INCLUDE=$(BOARD_DIR)/include TIMER_CHANNEL=9 make -C $(SDDF)/timer/client +SDDF_FS_PROTOCOL=../../fs/protocol/ +$(BUILD_DIR)/sddf_fs_protocol.o: FORCE + BUILD_DIR=$(abspath $(BUILD_DIR)) make -C $(SDDF_FS_PROTOCOL) + $(BUILD_DIR)/musllibc/lib/libc.a: make -C $(MUSL) \ C_COMPILER=aarch64-none-elf-gcc \ @@ -148,12 +152,13 @@ $(BUILD_DIR)/nfs/nfs.a: FORCE $(BUILD_DIR)/musllibc/lib/libc.a MUSLLIBC_INCLUDE=$(abspath $(BUILD_DIR)/musllibc/include) \ LIBNFS_INCLUDE=$(abspath ../..//libnfs/include) -$(BUILD_DIR)/nfs.elf: $(BUILD_DIR)/nfs/nfs.a $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/sddf_timer_client.o $(BUILD_DIR)/libnfs/lib/libnfs.a $(BUILD_DIR)/musllibc/lib/libc.a +$(BUILD_DIR)/nfs.elf: $(BUILD_DIR)/nfs/nfs.a $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/sddf_timer_client.o $(BUILD_DIR)/sddf_fs_protocol.o $(BUILD_DIR)/libnfs/lib/libnfs.a $(BUILD_DIR)/musllibc/lib/libc.a $(LD) \ $(LDFLAGS) \ $(BUILD_DIR)/nfs/nfs.a \ $(BUILD_DIR)/sddf_network_sharedringbuffer.o \ $(BUILD_DIR)/sddf_timer_client.o \ + $(BUILD_DIR)/sddf_fs_protocol.o \ -L$(BUILD_DIR)/libnfs/lib \ -L$(BUILD_DIR)/musllibc/lib \ -L$(LIBGCC) \ diff --git a/examples/kitty/kitty.system b/examples/kitty/kitty.system index 294094a2..4c61be95 100644 --- a/examples/kitty/kitty.system +++ b/examples/kitty/kitty.system @@ -3,13 +3,17 @@ - + + + + + @@ -129,6 +133,8 @@ + + diff --git a/examples/kitty/src/micropython/Makefile b/examples/kitty/src/micropython/Makefile index 7db25672..7415f4cf 100644 --- a/examples/kitty/src/micropython/Makefile +++ b/examples/kitty/src/micropython/Makefile @@ -49,7 +49,7 @@ SRC_C = \ SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c modmyport.c modfb.c vfs_sddf_fs_file.c vfs_sddf_fs.c # Define the required object files. -OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) ../../build/sddf_timer_client.o +OBJ = $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) ../../build/sddf_timer_client.o ../../build/sddf_fs_protocol.o all: $(BUILD)/micropython.elf diff --git a/examples/kitty/src/micropython/sddf_fs.c b/examples/kitty/src/micropython/sddf_fs.c index 5621300b..4f63435e 100644 --- a/examples/kitty/src/micropython/sddf_fs.c +++ b/examples/kitty/src/micropython/sddf_fs.c @@ -1,232 +1,177 @@ #include #include +#include +#include #include #include "sddf_fs.h" #include "micropython.h" -struct open_response sddf_fs_open(const char *filename) -{ - uint32_t cmd = SDDF_FS_CMD_OPEN; - memcpy(nfs_share, &cmd, 4); - strcpy(nfs_share + 4, filename); +#define NFS_SHARE_BUF_SIZE 4096 + +struct sddf_fs_queue *nfs_command_queue; +struct sddf_fs_queue *nfs_completion_queue; + +uint64_t curr_request_id = 0; + +uint64_t nfs_share_buf_offset[] = { + NFS_SHARE_BUF_SIZE, + NFS_SHARE_BUF_SIZE * 2, + NFS_SHARE_BUF_SIZE * 3, + NFS_SHARE_BUF_SIZE * 4 +}; + +char *nfs_share_buf(int n) { + return nfs_share + nfs_share_buf_offset[n]; +} + +struct sddf_fs_completion cmd_await(uint32_t cmd_type, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3) { + union sddf_fs_message message; + + message.command = (struct sddf_fs_command) { + .request_id = curr_request_id, + .cmd_type = cmd_type, + .args = { + [0] = arg0, + [1] = arg1, + [2] = arg2, + [3] = arg3, + } + }; + bool success = sddf_fs_queue_push(nfs_command_queue, message); + assert(success); microkit_notify(NFS_CH); await(mp_event_source_nfs); - int status = *(int *)nfs_share; - if (status) { - return (struct open_response){ .status = status }; - } else { - return (struct open_response){ - .status = status, - .fd = *(uint64_t *)(nfs_share + 4) - }; + success = sddf_fs_queue_pop(nfs_completion_queue, &message); + assert(success); + assert(message.completion.request_id == curr_request_id); + curr_request_id++; + return message.completion; +} + +struct open_response sddf_fs_open(const char *path) +{ + strcpy(nfs_share_buf(0), path); + uint64_t path_len = strlen(path) + 1; + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_OPEN, nfs_share_buf_offset[0], path_len, 0, 0); + + struct open_response response; + response.status = cmpl.status; + if (cmpl.status == 0) { + response.fd = cmpl.data[0]; } + return response; } int sddf_fs_close(uint64_t fd) { - uint32_t cmd = SDDF_FS_CMD_CLOSE; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - return *(int *)nfs_share; + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_CLOSE, fd, 0, 0, 0); + return cmpl.status; } struct read_response sddf_fs_pread(uint64_t fd, uint64_t nbyte, uint64_t offset) { - uint32_t cmd = SDDF_FS_CMD_PREAD; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - memcpy(nfs_share + 12, &nbyte, 8); - memcpy(nfs_share + 20, &offset, 8); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_PREAD, fd, nfs_share_buf_offset[0], nbyte, offset); - int status = *(int *)nfs_share; - if (status < 0) { - return (struct read_response){ .status = status }; - } else { - return (struct read_response){ - .status = status, - .data = nfs_share + 4, - .len = status - }; + struct read_response response; + response.status = cmpl.status; + if (cmpl.status >= 0) { + response.data = nfs_share_buf(0); + response.len = cmpl.status; } + return response; } int sddf_fs_pwrite(uint64_t fd, const char *buf, uint64_t nbyte, uint64_t offset) { - uint32_t cmd = SDDF_FS_CMD_PWRITE; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - memcpy(nfs_share + 12, &nbyte, 8); - memcpy(nfs_share + 20, &offset, 8); - memcpy(nfs_share + 28, buf, nbyte); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - int status = *(int *)nfs_share; - return status; + memcpy(nfs_share_buf(0), buf, nbyte); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_PWRITE, fd, nfs_share_buf_offset[0], nbyte, offset); + return cmpl.status; } struct stat_response sddf_fs_stat(const char *filename) { - uint32_t cmd = SDDF_FS_CMD_STAT; - memcpy(nfs_share, &cmd, 4); - strcpy(nfs_share + 4, filename); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - int status = *(int *)nfs_share; - if (status) { - return (struct stat_response){ .status = status }; - } else { - struct stat_response response = { .status = status }; - memcpy(&response.stat, nfs_share + 4, sizeof (struct sddf_fs_stat_64)); - return response; + uint64_t path_len = strlen(filename) + 1; + strcpy(nfs_share_buf(0), filename); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_STAT, nfs_share_buf_offset[0], path_len,nfs_share_buf_offset[1], 0); + + struct stat_response response; + response.status = cmpl.status; + if (cmpl.status == 0) { + memcpy(&response.stat, nfs_share_buf(1), sizeof (struct sddf_fs_stat_64)); } + return response; } int sddf_fs_rename(const char *oldpath, const char *newpath) { - uint32_t cmd = SDDF_FS_CMD_RENAME; - uint64_t oldpath_offset = 20; - uint64_t newpath_offset = oldpath_offset + strlen(oldpath) + 1; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &oldpath_offset, 8); - memcpy(nfs_share + 12, &newpath_offset, 8); - strcpy(nfs_share + oldpath_offset, oldpath); - strcpy(nfs_share + newpath_offset, newpath); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - int status = *(int *)nfs_share; - return status; + uint64_t oldpath_len = strlen(oldpath) + 1; + uint64_t newpath_len = strlen(newpath) + 1; + strcpy(nfs_share_buf(0), oldpath); + strcpy(nfs_share_buf(1), newpath); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_RENAME, nfs_share_buf_offset[0], oldpath_len, nfs_share_buf_offset[1], newpath_len); + return cmpl.status; } int sddf_fs_unlink(const char *path) { - uint32_t cmd = SDDF_FS_CMD_UNLINK; - memcpy(nfs_share, &cmd, 4); - strcpy(nfs_share + 4, path); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - int status = *(int *)nfs_share; - return status; + uint64_t path_len = strlen(path) + 1; + strcpy(nfs_share_buf(0), path); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_UNLINK, nfs_share_buf_offset[0], path_len, 0, 0); + return cmpl.status; } int sddf_fs_mkdir(const char *path) { - uint32_t cmd = SDDF_FS_CMD_MKDIR; - memcpy(nfs_share, &cmd, 4); - strcpy(nfs_share + 4, path); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - int status = *(int *)nfs_share; - return status; + uint64_t path_len = strlen(path) + 1; + strcpy(nfs_share_buf(0), path); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_MKDIR, nfs_share_buf_offset[0], path_len, 0, 0); + return cmpl.status; } int sddf_fs_rmdir(const char *path) { - uint32_t cmd = SDDF_FS_CMD_RMDIR; - memcpy(nfs_share, &cmd, 4); - strcpy(nfs_share + 4, path); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - int status = *(int *)nfs_share; - return status; + uint64_t path_len = strlen(path) + 1; + strcpy(nfs_share_buf(0), path); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_RMDIR, nfs_share_buf_offset[0], path_len, 0, 0); + return cmpl.status; } int sddf_fs_closedir(uint64_t fd) { - uint32_t cmd = SDDF_FS_CMD_CLOSEDIR; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - int status = *(int *)nfs_share; - return status; + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_CLOSEDIR, fd, 0, 0, 0); + return cmpl.status; } int sddf_fs_fsync(uint64_t fd) { - uint32_t cmd = SDDF_FS_CMD_FSYNC; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - int status = *(int *)nfs_share; - return status; + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_FSYNC, fd, 0, 0, 0); + return cmpl.status; } void sddf_fs_seekdir(uint64_t fd, long loc) { - uint32_t cmd = SDDF_FS_CMD_CLOSEDIR; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - memcpy(nfs_share + 12, &loc, 8); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); + cmd_await(SDDF_FS_CMD_SEEKDIR, fd, loc, 0, 0); } long sddf_fs_telldir(uint64_t fd) { - uint32_t cmd = SDDF_FS_CMD_TELLDIR; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); - - long loc = *(long *)nfs_share; - return loc; + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_TELLDIR, fd, 0, 0, 0); + return cmpl.status ? cmpl.status : cmpl.data[0]; } void sddf_fs_rewinddir(uint64_t fd) { - uint32_t cmd = SDDF_FS_CMD_REWINDDIR; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); + cmd_await(SDDF_FS_CMD_REWINDDIR, fd, 0, 0, 0); } -int sddf_fs_opendir(const char *in_path, uint64_t *out_fd) { - uint32_t cmd = SDDF_FS_CMD_OPENDIR; - memcpy(nfs_share, &cmd, 4); - strcpy(nfs_share + 4, in_path); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); +int sddf_fs_opendir(const char *path, uint64_t *fd) { + uint64_t path_len = strlen(path) + 1; + strcpy(nfs_share_buf(0), path); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_OPENDIR, nfs_share_buf_offset[0], path_len, 0, 0); - int status; - memcpy(&status, nfs_share, 4); + int status = cmpl.status; if (status == 0) { - memcpy(out_fd, nfs_share + 4, 8); + *fd = cmpl.data[0]; } return status; } int sddf_fs_readdir(uint64_t fd, char **out_name) { - uint32_t cmd = SDDF_FS_CMD_READDIR; - memcpy(nfs_share, &cmd, 4); - memcpy(nfs_share + 4, &fd, 8); - microkit_notify(NFS_CH); - - await(mp_event_source_nfs); + struct sddf_fs_completion cmpl = cmd_await(SDDF_FS_CMD_READDIR, fd, nfs_share_buf_offset[0], NFS_SHARE_BUF_SIZE, 0); - int status; - memcpy(&status, nfs_share, 4); + int status = cmpl.status; if (status == 0) { - *out_name = nfs_share + 4; + *out_name = nfs_share_buf(0); } return status; } diff --git a/examples/kitty/src/micropython/sddf_fs.h b/examples/kitty/src/micropython/sddf_fs.h index 7b8e3acd..33b82967 100644 --- a/examples/kitty/src/micropython/sddf_fs.h +++ b/examples/kitty/src/micropython/sddf_fs.h @@ -1,24 +1,5 @@ #include - -struct sddf_fs_stat_64 { - uint64_t dev; - uint64_t ino; - uint64_t mode; - uint64_t nlink; - uint64_t uid; - uint64_t gid; - uint64_t rdev; - uint64_t size; - uint64_t blksize; - uint64_t blocks; - uint64_t atime; - uint64_t mtime; - uint64_t ctime; - uint64_t atime_nsec; - uint64_t mtime_nsec; - uint64_t ctime_nsec; - uint64_t used; -}; +#include struct stat_response { struct sddf_fs_stat_64 stat; diff --git a/fs/include/fs/protocol.h b/fs/include/fs/protocol.h index feaffd8b..c0617bd7 100644 --- a/fs/include/fs/protocol.h +++ b/fs/include/fs/protocol.h @@ -1,5 +1,10 @@ #pragma once +#include +#include + +#define SDDF_FS_QUEUE_CAPACITY 5 + enum { SDDF_FS_CMD_OPEN, SDDF_FS_CMD_CLOSE, @@ -19,30 +24,49 @@ enum { SDDF_FS_CMD_REWINDDIR, }; -struct sddf_fs_path { - char str[4096]; - int len; +struct sddf_fs_command { + uint64_t request_id; + uint64_t cmd_type; + uint64_t args[4]; }; -struct sddf_fs_filename { - char str[255]; - int len; +struct sddf_fs_completion { + uint64_t request_id; + uint64_t data[2]; + int32_t status; }; -struct sddf_fs_opendir_request { - struct sddf_fs_path path; +union sddf_fs_message { + struct sddf_fs_command command; + struct sddf_fs_completion completion; }; -struct sddf_fs_opendir_response { - uint64_t fd; - int status; +struct sddf_fs_queue { + union sddf_fs_message buffer[SDDF_FS_QUEUE_CAPACITY]; + uint32_t read_index; + uint32_t write_index; + uint32_t size; }; -struct sddf_fs_readdir_request { - uint64_t fd; -}; +bool sddf_fs_queue_push(struct sddf_fs_queue *queue, union sddf_fs_message message); +bool sddf_fs_queue_pop(struct sddf_fs_queue *queue, union sddf_fs_message *message); -struct sddf_fs_readdir_response { - struct sddf_fs_filename filename; - int status; +struct sddf_fs_stat_64 { + uint64_t dev; + uint64_t ino; + uint64_t mode; + uint64_t nlink; + uint64_t uid; + uint64_t gid; + uint64_t rdev; + uint64_t size; + uint64_t blksize; + uint64_t blocks; + uint64_t atime; + uint64_t mtime; + uint64_t ctime; + uint64_t atime_nsec; + uint64_t mtime_nsec; + uint64_t ctime_nsec; + uint64_t used; }; diff --git a/fs/nfs/nfs.c b/fs/nfs/nfs.c index 990fab70..56dd05c8 100644 --- a/fs/nfs/nfs.c +++ b/fs/nfs/nfs.c @@ -9,6 +9,7 @@ #include #include +#include "nfs.h" #include "util.h" #include "fd.h" #include "tcp.h" @@ -16,7 +17,6 @@ #define TIMEOUT (30 * NS_IN_MS) -char *client_share; struct nfs_context *nfs; void nfs_connect_cb(int err, struct nfs_context *nfs_ctx, void *data, void *private_data) { @@ -80,7 +80,7 @@ void notified(microkit_channel ch) { void init(void) { syscalls_init(); - dlog("nfs init!"); + continuation_pool_init(); tcp_init_0(); sddf_timer_set_timeout(TIMEOUT); } diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index b8c7095c..7bbdace0 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -1,4 +1,4 @@ -extern char *client_share; extern struct nfs_context *nfs; +void continuation_pool_init(void); void nfs_notified(void); diff --git a/fs/nfs/op.c b/fs/nfs/op.c index e85e0e4e..f1ab9f6a 100644 --- a/fs/nfs/op.c +++ b/fs/nfs/op.c @@ -19,42 +19,117 @@ #include "util.h" #include "fd.h" +#define MAX_CONCURRENT_OPS 100 +#define CLIENT_SHARE_SIZE 0x200000 + +struct sddf_fs_queue *command_queue; +struct sddf_fs_queue *completion_queue; +void *client_share; + +struct continuation { + uint64_t request_id; + uint64_t data[4]; + struct continuation *next_free; +}; + +struct continuation continuation_pool[MAX_CONCURRENT_OPS]; +struct continuation *first_free_cont; + +void continuation_pool_init(void) { + first_free_cont = &continuation_pool[0]; + for (int i = 0; i + 1 < MAX_CONCURRENT_OPS; i++) { + continuation_pool[i].next_free = &continuation_pool[i+1]; + } +} + +struct continuation *continuation_alloc(void) { + struct continuation *cont = first_free_cont; + if (cont != NULL) { + first_free_cont = cont->next_free; + cont->next_free = NULL; + } + return cont; +} + +void continuation_free(struct continuation *cont) { + assert(cont >= continuation_pool); + assert(cont < continuation_pool + MAX_CONCURRENT_OPS); + assert(cont->next_free == NULL); + cont->next_free = first_free_cont; + first_free_cont = cont; +} + +void reply(uint64_t request_id, uint64_t status, uint64_t data0, uint64_t data1) { + union sddf_fs_message message = { + .completion = { + .request_id = request_id, + .status = status, + .data = { + [0] = data0, + [1] = data1, + } + } + }; + sddf_fs_queue_push(completion_queue, message); + microkit_notify(CLIENT_CHANNEL); +} + static void stat64_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { - memcpy(client_share, &status, 4); + struct continuation *cont = private_data; + void *buf = (void *)cont->data[0]; + if (status == 0) { - struct nfs_stat_64 *st = (struct nfs_stat_64 *)data; - memcpy(client_share + 4, st, sizeof *st); + memcpy(buf, data, sizeof (struct nfs_stat_64)); } else { dlog("failed to stat file (%d): %s", status, data); } - microkit_notify(CLIENT_CHANNEL); + + continuation_free(cont); + reply(cont->request_id, status, 0, 0); } -void handle_stat64(const char *path) { - int err = nfs_stat64_async(nfs, path, stat64_cb, (void *)CLIENT_CHANNEL); +void handle_stat64(uint64_t request_id, const char *path, void *buf) { + int err = 0; + + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + cont->data[0] = (uint64_t)buf; + + err = nfs_stat64_async(nfs, path, stat64_cb, cont); if (err) { dlog("failed to enqueue command"); - memcpy(client_share, &err, 4); - microkit_notify(CLIENT_CHANNEL); } + + return; + +fail_enqueue: + continuation_free(cont); +fail_continuation: + reply(request_id, err, 0, 0); } void open_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { + struct continuation *cont = private_data; struct nfsfh *file = data; - fd_t fd = (fd_t)private_data; + fd_t fd = cont->data[0]; if (status == 0) { fd_set_file(fd, file); - memcpy(client_share + 4, &fd, 8); + reply(cont->request_id, status, fd, 0); } else { dlog("failed to open file\n"); + reply(cont->request_id, status, 0, 0); fd_free(fd); } - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + continuation_free(cont); } -void handle_open(const char *path, int flags, int mode) { +void handle_open(uint64_t request_id, const char *path, int flags, int mode) { int err; fd_t fd; @@ -63,41 +138,49 @@ void handle_open(const char *path, int flags, int mode) { dlog("no free fds"); goto fail_alloc; } - err = nfs_open2_async(nfs, path, flags, mode, open_cb, (void *)fd); + + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + cont->data[0] = fd; + + err = nfs_open2_async(nfs, path, flags, mode, open_cb, cont); if (err) { dlog("failed to enqueue command"); goto fail_enqueue; } + return; fail_enqueue: + continuation_free(cont); +fail_continuation: fd_free(fd); fail_alloc: - memcpy(client_share, &err, sizeof err); - microkit_notify(CLIENT_CHANNEL); + reply(cont->request_id, err, 0, 0); } -struct close_data { - fd_t fd; - struct nfsfh *file_handle; -}; - void close_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { - dlogp(status != 0, "failed to close file: %d (%s)", status, nfs_get_error(nfs)); + struct continuation *cont = private_data; + fd_t fd = cont->data[0]; + struct nfsfh *fh = (struct nfsfh *)cont->data[1]; - struct close_data *close_data = private_data; if (status == 0) { - fd_free(close_data->fd); + fd_free(fd); } else { - fd_set_file(close_data->fd, close_data->file_handle); + dlog("failed to close file: %d (%s)", status, nfs_get_error(nfs)); + fd_set_file(fd, fh); } - free(close_data); - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + reply(cont->request_id, status, 0, 0); + continuation_free(cont); } -void handle_close(fd_t fd) { +void handle_close(uint64_t request_id, fd_t fd) { int err = 0; struct nfsfh *file_handle = NULL; @@ -114,10 +197,17 @@ void handle_close(fd_t fd) { goto fail_unset; } - struct close_data *close_data = malloc(sizeof *close_data); - close_data->fd = fd; - close_data->file_handle = file_handle; - err = nfs_close_async(nfs, file_handle, close_cb, (void *)close_data); + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + err = 1; + dlog("no free continuations"); + goto fail_continuation; + } + cont->request_id = request_id; + cont->data[0] = fd; + cont->data[1] = (uint64_t)file_handle; + + err = nfs_close_async(nfs, file_handle, close_cb, cont); if (err) { dlog("failed to enqueue command"); goto fail_enqueue; @@ -126,28 +216,33 @@ void handle_close(fd_t fd) { return; fail_enqueue: + continuation_free(cont); +fail_continuation: fd_set_file(fd, file_handle); fail_unset: fail_begin: - memcpy(client_share, &err, sizeof err); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, err, 0, 0); } void pread_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { - dlogp(status < 0, "failed to read file: %d (%s)", status, data); + struct continuation *cont = private_data; + fd_t fd = cont->data[0]; + char *buf = (char *)cont->data[1]; - fd_t fd = (fd_t)private_data; if (status >= 0) { int len_read = status; - memcpy(client_share + 4, data, len_read); + memcpy(buf, data, len_read); + reply(cont->request_id, status, len_read, 0); + } else { + reply(cont->request_id, status, 0, 0); + dlog("failed to read file: %d (%s)", status, data); } fd_end_op(fd); - memcpy(client_share, &status, sizeof status); - microkit_notify(CLIENT_CHANNEL); + continuation_free(cont); } -void handle_pread(fd_t fd, uint64_t nbyte, uint64_t offset) { +void handle_pread(uint64_t request_id, fd_t fd, const char *buf, uint64_t nbyte, uint64_t offset) { int err; struct nfsfh *file_handle = NULL; @@ -157,7 +252,17 @@ void handle_pread(fd_t fd, uint64_t nbyte, uint64_t offset) { goto fail_begin; } - err = nfs_pread_async(nfs, file_handle, offset, nbyte, pread_cb, (void *)fd); + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + cont->data[0] = fd; + cont->data[1] = (uint64_t)buf; + + err = nfs_pread_async(nfs, file_handle, offset, nbyte, pread_cb, cont); if (err) { dlog("failed to enqueue command"); goto fail_enqueue; @@ -166,22 +271,25 @@ void handle_pread(fd_t fd, uint64_t nbyte, uint64_t offset) { return; fail_enqueue: + continuation_free(cont); +fail_continuation: fd_end_op(fd); fail_begin: - memcpy(client_share, &err, sizeof err); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, err, 0, 0); } void pwrite_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { + struct continuation *cont = private_data; + fd_t fd = cont->data[0]; + dlogp(status < 0, "failed to write to file: %d (%s)", status, data); - fd_t fd = (fd_t)private_data; fd_end_op(fd); - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + reply(cont->request_id, status, 0, 0); + continuation_free(cont); } -void handle_pwrite(fd_t fd, char *buf, uint64_t nbyte, uint64_t offset) { +void handle_pwrite(uint64_t request_id, fd_t fd, char *buf, uint64_t nbyte, uint64_t offset) { int err; struct nfsfh *file_handle = NULL; @@ -191,7 +299,16 @@ void handle_pwrite(fd_t fd, char *buf, uint64_t nbyte, uint64_t offset) { goto fail_begin; } - err = nfs_pwrite_async(nfs, file_handle, offset, nbyte, buf, pwrite_cb, (void *)fd); + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + cont->data[0] = fd; + + err = nfs_pwrite_async(nfs, file_handle, offset, nbyte, buf, pwrite_cb, cont); if (err) { dlog("failed to enqueue command"); goto fail_enqueue; @@ -200,117 +317,200 @@ void handle_pwrite(fd_t fd, char *buf, uint64_t nbyte, uint64_t offset) { return; fail_enqueue: + continuation_free(cont); +fail_continuation: fd_end_op(fd); fail_begin: - memcpy(client_share, &err, 4); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, err, 0, 0); } void rename_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { + struct continuation *cont = private_data; dlogp(status != 0, "failed to write to file: %d (%s)", status, data); - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + reply(cont->request_id, status, 0, 0); + continuation_free(cont); } -void handle_rename(const char *oldpath, const char *newpath) { - int err = nfs_rename_async(nfs, oldpath, newpath, rename_cb, NULL); +void handle_rename(uint64_t request_id, const char *oldpath, const char *newpath) { + int err = 0; + + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + err = nfs_rename_async(nfs, oldpath, newpath, rename_cb, cont); if (err) { dlog("failed to enqueue command"); - microkit_notify(CLIENT_CHANNEL); + goto fail_enqueue; } + + return; + +fail_enqueue: + continuation_free(cont); +fail_continuation: + reply(request_id, err, 0, 0); } void unlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { - dlogp(status != 0, "failed to write to file: %d (%s)", status, data); - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + struct continuation *cont = private_data; + dlogp(status != 0, "failed to unlink file"); + reply(cont->request_id, status, 0, 0); + continuation_free(cont); } -void handle_unlink(const char *path) { - int err = nfs_unlink_async(nfs, path, unlink_cb, NULL); +void handle_unlink(uint64_t request_id, const char *path) { + int err = 0; + + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + err = nfs_unlink_async(nfs, path, unlink_cb, cont); if (err) { dlog("failed to enqueue command"); - microkit_notify(CLIENT_CHANNEL); + goto fail_enqueue; } + + return; + +fail_enqueue: + continuation_free(cont); +fail_continuation: + reply(request_id, err, 0, 0); } -void fsync_cb(int status, struct nfs_context *nfs, void *data, void *private_data) -{ +void fsync_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { + struct continuation *cont = private_data; dlogp(status != 0, "fsync failed: %d (%s)", status, data); - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + reply(cont->request_id, status, 0, 0); + continuation_free(cont); } -void handle_fsync(fd_t fd) { +void handle_fsync(uint64_t request_id, fd_t fd) { int err = 0; struct nfsfh *file_handle = NULL; err = fd_begin_op_file(fd, &file_handle); if (err) { dlog("invalid fd"); - goto fail; + err = 1; + goto fail_begin; } - err = nfs_fsync_async(nfs, file_handle, fsync_cb, NULL); + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + + err = nfs_fsync_async(nfs, file_handle, fsync_cb, cont); if (err) { dlog("failed to enqueue command"); - goto fail; + goto fail_enqueue; } return; -fail: - memcpy(client_share, &err, sizeof err); - microkit_notify(CLIENT_CHANNEL); +fail_enqueue: + continuation_free(cont); +fail_continuation: + fd_end_op(fd); +fail_begin: + reply(request_id, err, 0, 0); } void mkdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { + struct continuation *cont = private_data; dlogp(status != 0, "failed to write to file: %d (%s)", status, data); - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + reply(cont->request_id, status, 0, 0); + continuation_free(cont); } -void handle_mkdir(const char *path) { - int err = nfs_mkdir_async(nfs, path, mkdir_cb, NULL); +void handle_mkdir(uint64_t request_id, const char *path) { + int err; + + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + + err = nfs_mkdir_async(nfs, path, mkdir_cb, NULL); if (err) { dlog("failed to enqueue command"); - microkit_notify(CLIENT_CHANNEL); + goto fail_enqueue; } + + return; + +fail_enqueue: + continuation_free(cont); +fail_continuation: + reply(request_id, err, 0, 0); } void rmdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { + struct continuation *cont = continuation_alloc(); dlogp(status != 0, "failed to write to file: %d (%s)", status, data); - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + reply(cont->request_id, status, 0, 0); + continuation_free(cont); } -void handle_rmdir(const char *path) { - int err = nfs_rmdir_async(nfs, path, rmdir_cb, NULL); +void handle_rmdir(uint64_t request_id, const char *path) { + int err = 0; + + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + + err = nfs_rmdir_async(nfs, path, rmdir_cb, cont); if (err) { dlog("failed to enqueue command"); - memcpy(client_share, &err, 4); - microkit_notify(CLIENT_CHANNEL); + goto fail_enqueue; } + + return; + +fail_enqueue: + continuation_free(cont); +fail_continuation: + reply(request_id, err, 0, 0); } -void opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) -{ +void opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) { + struct continuation *cont = private_data; + + fd_t fd = cont->data[0]; struct nfsdir *dir = data; - fd_t fd = (fd_t)private_data; if (status == 0) { fd_set_dir(fd, dir); - memcpy(client_share + 4, &fd, 8); + reply(cont->request_id, status, fd, 0); } else { dlog("failed to open directory: %d (%s)", status, data); + reply(cont->request_id, status, 0, 0); fd_free(fd); } - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + continuation_free(cont); } -void handle_opendir(const char *path) { +void handle_opendir(uint64_t request_id, const char *path) { int err = 0; fd_t fd; @@ -320,7 +520,16 @@ void handle_opendir(const char *path) { goto fail_alloc; } - err = nfs_opendir_async(nfs, path, opendir_cb, (void *)fd); + struct continuation *cont = continuation_alloc(); + if (cont == NULL) { + dlog("no free continuations"); + err = 1; + goto fail_continuation; + } + cont->request_id = request_id; + cont->data[0] = fd; + + err = nfs_opendir_async(nfs, path, opendir_cb, cont); if (err) { dlog("failed to enqueue command"); goto fail_enqueue; @@ -329,13 +538,14 @@ void handle_opendir(const char *path) { return; fail_enqueue: + continuation_free(cont); +fail_continuation: fd_free(fd); fail_alloc: - memcpy(client_share, &err, 4); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, err, 0, 0); } -void handle_closedir(fd_t fd) { +void handle_closedir(uint64_t request_id, fd_t fd) { int err = 0; struct nfsdir *dir_handle = NULL; @@ -348,19 +558,17 @@ void handle_closedir(fd_t fd) { err = fd_unset(fd); if (err) { - dlog("trying to close fd with outstanding operations: %d\n"); + dlog("trying to close fd with outstanding operations"); goto fail; } nfs_closedir(nfs, dir_handle); fd_free(fd); - fail: - memcpy(client_share, &err, sizeof err); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, err, 0, 0); } -void handle_readdir(fd_t fd) { +void handle_readdir(uint64_t request_id, fd_t fd, char *buf, uint64_t buf_size) { struct nfsdir *dir_handle = NULL; int status = fd_begin_op_dir(fd, &dir_handle); if (status) { @@ -373,19 +581,24 @@ void handle_readdir(fd_t fd) { dlog("failed to read dir"); status = -1; goto fail_readdir; - } else { } - strcpy(client_share + 4, dirent->name); + uint64_t name_len = strlen(dirent->name) + 1; + if (name_len > buf_size) { + dlog("buffer not large enough"); + status = -1; + goto fail_strcpy; + } + strcpy(buf, dirent->name); +fail_strcpy: fail_readdir: fd_end_op(fd); fail_begin: - memcpy(client_share, &status, 4); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, status, 0, 0); } -void handle_seekdir(fd_t fd, long loc) { +void handle_seekdir(uint64_t request_id, fd_t fd, long loc) { int err = 0; struct nfsdir *dir_handle = NULL; @@ -398,11 +611,10 @@ void handle_seekdir(fd_t fd, long loc) { fd_end_op(fd); fail: - memcpy(client_share, &err, sizeof err); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, err, 0, 0); } -void handle_telldir(fd_t fd) { +void handle_telldir(uint64_t request_id, fd_t fd) { int err = 0; struct nfsdir *dir_handle = NULL; @@ -412,15 +624,13 @@ void handle_telldir(fd_t fd) { goto fail; } long loc = nfs_telldir(nfs, dir_handle); - memcpy(client_share + 4, &loc, sizeof loc); fd_end_op(fd); fail: - memcpy(client_share, &err, sizeof err); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, err, loc, 0); } -void handle_rewinddir(fd_t fd) { +void handle_rewinddir(uint64_t request_id, fd_t fd) { int err = 0; struct nfsdir *dir_handle = NULL; @@ -433,108 +643,193 @@ void handle_rewinddir(fd_t fd) { fd_end_op(fd); fail: - memcpy(client_share, &err, 4); - microkit_notify(CLIENT_CHANNEL); + reply(request_id, err, 0, 0); } void nfs_notified(void) { - uint32_t cmd; - memcpy(&cmd, client_share, 4); - switch (cmd) { + union sddf_fs_message message; + bool success = sddf_fs_queue_pop(command_queue, &message); + assert(success); + + struct sddf_fs_command cmd = message.command; + uint64_t request_id = cmd.request_id; + switch (cmd.cmd_type) { case SDDF_FS_CMD_OPEN: { - handle_open(client_share + 4, O_RDWR | O_CREAT, O_RDWR); + uint64_t path_offset = cmd.args[0]; + char *path = client_share + path_offset; + uint64_t path_len = cmd.args[1]; + if (path_offset + path_len >= CLIENT_SHARE_SIZE) { + reply(request_id, 1, 0, 0); + break; + } + path[path_len - 1] = '\0'; + handle_open(request_id, path, O_RDWR | O_CREAT, O_RDWR); break; } case SDDF_FS_CMD_STAT: { - handle_stat64(client_share + 4); + uint64_t path_offset = cmd.args[0]; + char *path = client_share + path_offset; + uint64_t path_len = cmd.args[1]; + if (path_offset + path_len >= CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + path[path_len - 1] = '\0'; + uint64_t buf_offset = cmd.args[2]; + if (buf_offset + sizeof (struct sddf_fs_stat_64) > CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + char *buf = client_share + buf_offset; + handle_stat64(request_id, path, buf); break; } case SDDF_FS_CMD_CLOSE: { - fd_t fd; - memcpy(&fd, client_share + 4, 8); - handle_close(fd); + fd_t fd = cmd.args[0]; + handle_close(request_id, fd); break; } case SDDF_FS_CMD_PREAD: { - fd_t fd; - uint64_t nbyte, offset; - memcpy(&fd, client_share + 4, 8); - memcpy(&nbyte, client_share + 12, 8); - memcpy(&offset, client_share + 20, 8); - handle_pread(fd, nbyte, offset); + fd_t fd = cmd.args[0]; + uint64_t buf_offset = cmd.args[1]; + const char *buf = client_share + buf_offset; + uint64_t nbyte = cmd.args[2]; + uint64_t offset = cmd.args[3]; + if (buf_offset + nbyte > CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + handle_pread(request_id, fd, buf, nbyte, offset); break; } case SDDF_FS_CMD_PWRITE: { - fd_t fd; - uint64_t nbyte, offset; - memcpy(&fd, client_share + 4, 8); - memcpy(&nbyte, client_share + 12, 8); - memcpy(&offset, client_share + 20, 8); - char *buf = client_share + 28; - handle_pwrite(fd, buf, nbyte, offset); + fd_t fd = cmd.args[0]; + uint64_t buf_offset = cmd.args[1]; + char *buf = client_share + buf_offset; + uint64_t nbyte = cmd.args[2]; + uint64_t offset = cmd.args[3]; + if (buf_offset > nbyte > CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + handle_pwrite(request_id, fd, buf, nbyte, offset); break; } case SDDF_FS_CMD_RENAME: { - uint64_t oldpath_offset, newpath_offset; - memcpy(&oldpath_offset, client_share + 4, 8); - memcpy(&newpath_offset, client_share + 12, 8); + uint64_t oldpath_offset = cmd.args[0]; + uint64_t oldpath_len = cmd.args[1]; + uint64_t newpath_offset = cmd.args[2]; + uint64_t newpath_len = cmd.args[3]; + if ((oldpath_offset + oldpath_len > CLIENT_SHARE_SIZE) || (newpath_offset + newpath_len > CLIENT_SHARE_SIZE)) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } char *oldpath = client_share + oldpath_offset; char *newpath = client_share + newpath_offset; - handle_rename(oldpath, newpath); + oldpath[oldpath_len - 1] = '\0'; + newpath[newpath_len - 1] = '\0'; + + handle_rename(request_id, oldpath, newpath); break; } case SDDF_FS_CMD_UNLINK: { - handle_unlink(client_share + 4); + uint64_t path_offset = cmd.args[0]; + uint64_t path_len = cmd.args[1]; + if (path_offset + path_len > CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + char *path = client_share + path_offset; + path[path_len - 1] = '\0'; + + handle_unlink(request_id, path); break; } case SDDF_FS_CMD_MKDIR: { - handle_mkdir(client_share + 4); + uint64_t path_offset = cmd.args[0]; + uint64_t path_len = cmd.args[1]; + if (path_offset + path_len > CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + char *path = client_share + path_offset; + path[path_len - 1] = '\0'; + + handle_mkdir(request_id, path); break; } case SDDF_FS_CMD_RMDIR: { - handle_rmdir(client_share + 4); + uint64_t path_offset = cmd.args[0]; + uint64_t path_len = cmd.args[1]; + if (path_offset + path_len > CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + char *path = client_share + path_offset; + path[path_len - 1] = '\0'; + + handle_rmdir(request_id, path); break; } case SDDF_FS_CMD_OPENDIR: { - handle_opendir(client_share + 4); + uint64_t path_offset = cmd.args[0]; + uint64_t path_len = cmd.args[1]; + if (path_offset + path_len > CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + char *path = client_share + path_offset; + path[path_len - 1] = '\0'; + + handle_opendir(request_id, path); break; } case SDDF_FS_CMD_CLOSEDIR: { - fd_t fd; - memcpy(&fd, client_share + 4, 8); - handle_closedir(fd); + fd_t fd = cmd.args[0]; + handle_closedir(request_id, fd); break; } case SDDF_FS_CMD_READDIR: { - fd_t fd; - memcpy(&fd, client_share + 4, 8); - handle_readdir(fd); + fd_t fd = cmd.args[0]; + uint64_t buf_offset = cmd.args[1]; + uint64_t buf_size = cmd.args[2]; + if (buf_offset + buf_size > CLIENT_SHARE_SIZE) { + dlog("bad buffer provided"); + reply(request_id, 1, 0, 0); + break; + } + char *buf = client_share + buf_offset; + handle_readdir(request_id, fd, buf, buf_size); break; } case SDDF_FS_CMD_FSYNC: { - fd_t fd; - memcpy(&fd, client_share + 4, 8); - handle_fsync(fd); + fd_t fd = cmd.args[0]; + handle_fsync(request_id, fd); break; } case SDDF_FS_CMD_SEEKDIR: { - fd_t fd; - int64_t loc; - memcpy(&fd, client_share + 4, 8); - memcpy(&loc, client_share + 12, 8); - handle_seekdir(fd, loc); + fd_t fd = cmd.args[0]; + int64_t loc = cmd.args[1]; + handle_seekdir(request_id, fd, loc); break; } case SDDF_FS_CMD_TELLDIR: { - fd_t fd; - memcpy(&fd, client_share + 4, 8); - handle_telldir(fd); + fd_t fd = cmd.args[0]; + handle_telldir(request_id, fd); break; } case SDDF_FS_CMD_REWINDDIR: { - fd_t fd; - memcpy(&fd, client_share + 4, 8); - handle_rewinddir(fd); + fd_t fd = cmd.args[0]; + handle_rewinddir(request_id, fd); break; } default: diff --git a/fs/protocol/Makefile b/fs/protocol/Makefile new file mode 100644 index 00000000..92fff5c4 --- /dev/null +++ b/fs/protocol/Makefile @@ -0,0 +1,25 @@ +# +# Copyright 2023, UNSW +# +# SPDX-License-Identifier: BSD-2-Clause +# + +BUILD_DIR ?= . + +CC := clang +TARGET := aarch64-none-elf + +CFLAGS := \ + -target $(TARGET) \ + -mstrict-align \ + -ffreestanding \ + -I../include + +all: $(BUILD_DIR)/sddf_fs_protocol.o + +$(BUILD_DIR)/sddf_fs_protocol.o: protocol.c ../include/fs/protocol.h + $(CC) -c $(CFLAGS) protocol.c -o $(BUILD_DIR)/sddf_fs_protocol.o + +.PHONY: clean +clean: + rm $(BUILD_DIR)/sddf_fs_protocol.o diff --git a/fs/protocol/protocol.c b/fs/protocol/protocol.c new file mode 100644 index 00000000..ba6021ef --- /dev/null +++ b/fs/protocol/protocol.c @@ -0,0 +1,24 @@ +#include +#include + +#include + +bool sddf_fs_queue_push(struct sddf_fs_queue *queue, union sddf_fs_message message) { + if (queue->size == SDDF_FS_QUEUE_CAPACITY) { + return false; + } + queue->buffer[queue->write_index] = message; + queue->write_index = (queue->write_index + 1) % SDDF_FS_QUEUE_CAPACITY; + queue->size++; + return true; +} + +bool sddf_fs_queue_pop(struct sddf_fs_queue *queue, union sddf_fs_message *message) { + if (queue->size == 0) { + return false; + } + *message = queue->buffer[queue->read_index]; + queue->read_index = (queue->read_index + 1) % SDDF_FS_QUEUE_CAPACITY; + queue->size--; + return true; +} From 6d19a70338ed806c837c149688fcdc9a43c2b861 Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 12:08:35 +1100 Subject: [PATCH 05/23] Disable ENOENT error messages in NFS client --- fs/nfs/op.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/op.c b/fs/nfs/op.c index f1ab9f6a..a0d1c53e 100644 --- a/fs/nfs/op.c +++ b/fs/nfs/op.c @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -80,7 +81,7 @@ static void stat64_cb(int status, struct nfs_context *nfs, void *data, void *pri if (status == 0) { memcpy(buf, data, sizeof (struct nfs_stat_64)); - } else { + } else if (status != -ENOENT) { dlog("failed to stat file (%d): %s", status, data); } @@ -578,7 +579,6 @@ void handle_readdir(uint64_t request_id, fd_t fd, char *buf, uint64_t buf_size) struct nfsdirent *dirent = nfs_readdir(nfs, dir_handle); if (dirent == NULL) { - dlog("failed to read dir"); status = -1; goto fail_readdir; } From f7de70ca7f9a4bd7cfa8074ddb049fca3bacc35e Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 12:28:14 +1100 Subject: [PATCH 06/23] Move includes to top of file --- fs/nfs/lwip_include/arch/cc.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/nfs/lwip_include/arch/cc.h b/fs/nfs/lwip_include/arch/cc.h index 57138533..8ada021a 100644 --- a/fs/nfs/lwip_include/arch/cc.h +++ b/fs/nfs/lwip_include/arch/cc.h @@ -4,6 +4,8 @@ */ #include +#include +#include typedef uint8_t u8_t; typedef uint16_t u16_t; @@ -53,9 +55,6 @@ typedef uintptr_t mem_ptr_t; #define LWIP_PLATFORM_HTONL(x) ( (((u32_t)(x))>>24) | (((x)&0xFF0000)>>8) \ | (((x)&0xFF00)<<8) | (((x)&0xFF)<<24) ) -#include -#include - #define LWIP_RAND rand /* Plaform specific diagnostic output */ From 358769805615ff04b27b03bfaa48f01d83e222ce Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 12:31:37 +1100 Subject: [PATCH 07/23] Use int64_t instead of long --- fs/nfs/op.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/op.c b/fs/nfs/op.c index a0d1c53e..700aaa60 100644 --- a/fs/nfs/op.c +++ b/fs/nfs/op.c @@ -598,7 +598,7 @@ void handle_readdir(uint64_t request_id, fd_t fd, char *buf, uint64_t buf_size) reply(request_id, status, 0, 0); } -void handle_seekdir(uint64_t request_id, fd_t fd, long loc) { +void handle_seekdir(uint64_t request_id, fd_t fd, int64_t loc) { int err = 0; struct nfsdir *dir_handle = NULL; @@ -623,7 +623,7 @@ void handle_telldir(uint64_t request_id, fd_t fd) { dlog("invalid fd"); goto fail; } - long loc = nfs_telldir(nfs, dir_handle); + int64_t loc = nfs_telldir(nfs, dir_handle); fd_end_op(fd); fail: From a2c9a4354605c4e82dc7aae84b9930d526e34138 Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 12:39:18 +1100 Subject: [PATCH 08/23] Clean up posix.c --- fs/nfs/posix.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/fs/nfs/posix.c b/fs/nfs/posix.c index 7b9f2383..2507bde4 100644 --- a/fs/nfs/posix.c +++ b/fs/nfs/posix.c @@ -70,24 +70,15 @@ static size_t output(void *data, size_t count) long sys_brk(va_list ap) { - uintptr_t ret; uintptr_t newbrk = va_arg(ap, uintptr_t); - /*if the newbrk is 0, return the bottom of the heap*/ - if (!newbrk) - { - ret = morecore_base; - } - else if (newbrk < morecore_top && newbrk > (uintptr_t)&morecore_area[0]) - { - ret = morecore_base = newbrk; + /* if the newbrk is 0, return the bottom of the heap */ + if (!newbrk) { + return morecore_base; + } else if (newbrk < morecore_top && newbrk > (uintptr_t)&morecore_area[0]) { + return morecore_base = newbrk; } - else - { - ret = 0; - } - - return ret; + return 0; } uintptr_t align_addr(uintptr_t addr) @@ -137,10 +128,8 @@ long sys_write(va_list ap) } return count; } - else - { - return -1; - } + + return -1; } long sys_clock_gettime(va_list ap) From e78aa1220ec7aa4051e9744ddc0057a15571d44f Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 12:39:34 +1100 Subject: [PATCH 09/23] Log musl calls to ioctl --- fs/nfs/posix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/posix.c b/fs/nfs/posix.c index 2507bde4..081b454e 100644 --- a/fs/nfs/posix.c +++ b/fs/nfs/posix.c @@ -155,6 +155,7 @@ long sys_ioctl(va_list ap) int fd = va_arg(ap, int); int request = va_arg(ap, int); (void)request; + dlog("musl called ioctl on fd %d", fd); /* muslc does some ioctls to stdout, so just allow these to silently go through */ if (fd == STDOUT_FD) From 7c0b090cef8206d08dc3548e7d425ae8aa35af42 Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 12:41:46 +1100 Subject: [PATCH 10/23] Fix typo --- fs/nfs/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/tcp.c b/fs/nfs/tcp.c index 899e1d2f..92bb55cd 100644 --- a/fs/nfs/tcp.c +++ b/fs/nfs/tcp.c @@ -33,7 +33,7 @@ typedef enum typedef struct ethernet_buffer { - /* The acutal underlying memory of the buffer */ + /* The actual underlying memory of the buffer */ uintptr_t buffer; /* The physical size of the buffer */ size_t size; From 146ceb4d111977078498f9bd9ba085a90ef452e1 Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 12:56:56 +1100 Subject: [PATCH 11/23] Add copyright notices to NFS client files --- fs/nfs/fd.c | 4 ++++ fs/nfs/fd.h | 5 +++++ fs/nfs/nfs.c | 5 +++++ fs/nfs/nfs.h | 5 +++++ fs/nfs/op.c | 5 +++++ fs/nfs/posix.c | 5 +++++ fs/nfs/posix.h | 5 +++++ fs/nfs/tcp.c | 5 +++++ fs/nfs/tcp.h | 5 +++++ fs/nfs/util.h | 2 +- 10 files changed, 45 insertions(+), 1 deletion(-) diff --git a/fs/nfs/fd.c b/fs/nfs/fd.c index d6d0c982..ca274a87 100644 --- a/fs/nfs/fd.c +++ b/fs/nfs/fd.c @@ -1,3 +1,7 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ #include #include diff --git a/fs/nfs/fd.h b/fs/nfs/fd.h index a709e9fb..a013b162 100644 --- a/fs/nfs/fd.h +++ b/fs/nfs/fd.h @@ -1,3 +1,8 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + #pragma once #include diff --git a/fs/nfs/nfs.c b/fs/nfs/nfs.c index 56dd05c8..afe3c056 100644 --- a/fs/nfs/nfs.c +++ b/fs/nfs/nfs.c @@ -1,3 +1,8 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + #include #include diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index 7bbdace0..765980bd 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -1,3 +1,8 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + extern struct nfs_context *nfs; void continuation_pool_init(void); diff --git a/fs/nfs/op.c b/fs/nfs/op.c index 700aaa60..601a09ef 100644 --- a/fs/nfs/op.c +++ b/fs/nfs/op.c @@ -1,3 +1,8 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + #include #include diff --git a/fs/nfs/posix.c b/fs/nfs/posix.c index 081b454e..d14117b7 100644 --- a/fs/nfs/posix.c +++ b/fs/nfs/posix.c @@ -1,3 +1,8 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + #include #include diff --git a/fs/nfs/posix.h b/fs/nfs/posix.h index 6d82a83a..771ebb00 100644 --- a/fs/nfs/posix.h +++ b/fs/nfs/posix.h @@ -1,2 +1,7 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + void syscalls_init(void); int socket_index_of_fd(int fd); diff --git a/fs/nfs/tcp.c b/fs/nfs/tcp.c index 92bb55cd..0db7d0d2 100644 --- a/fs/nfs/tcp.c +++ b/fs/nfs/tcp.c @@ -1,3 +1,8 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + #include #include diff --git a/fs/nfs/tcp.h b/fs/nfs/tcp.h index 48dd66cc..a14f558d 100644 --- a/fs/nfs/tcp.h +++ b/fs/nfs/tcp.h @@ -1,3 +1,8 @@ +/* + * Copyright 2023, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + #define MAX_SOCKETS 10 #define SOCKET_BUF_SIZE 0x200000 diff --git a/fs/nfs/util.h b/fs/nfs/util.h index b406b353..1a86087c 100644 --- a/fs/nfs/util.h +++ b/fs/nfs/util.h @@ -1,5 +1,5 @@ /* - * Copyright 2022, UNSW + * Copyright 2023, UNSW * SPDX-License-Identifier: BSD-2-Clause */ From 553ff4320d9b1644f7545e85d7275f597274d505 Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 13:16:46 +1100 Subject: [PATCH 12/23] Add readme to NFS client with outstanding issues --- fs/nfs/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 fs/nfs/README.md diff --git a/fs/nfs/README.md b/fs/nfs/README.md new file mode 100644 index 00000000..28255d20 --- /dev/null +++ b/fs/nfs/README.md @@ -0,0 +1,13 @@ +* Issues + +- os.listdir() on some directories causes a crash (IP=NULL), e.g. os.listdir('content/images'). +- need a proper asynchronous client library +- need examples in the README on how to use it +- dependency on libgcc +- libnfs doesn't work with clang +- libnfs doesn't build on macos due to unsupported flag +- some stuff not implemented, e.g. file modes +- using musl instead of our own libc +- musl calls into gettime() to get real-time clock, but we don't have an rtc +- unsure of memory lifetimes of libnfs, i.e. how robust is our heap management to long-running sessions? +- unsure of socket lifetimes, i.e. do we need to do anything extra to handle disconnects/reconnects etc? From 4d887e1dd45d389fd613e207c281daafe90f2972 Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 13:22:24 +1100 Subject: [PATCH 13/23] Remove unused code from NFS client's util.h --- fs/nfs/util.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/fs/nfs/util.h b/fs/nfs/util.h index 1a86087c..73575805 100644 --- a/fs/nfs/util.h +++ b/fs/nfs/util.h @@ -10,25 +10,10 @@ #include #include -#define STAT 0x98 -#define TRANSMIT 0x40 -#define STAT_TDRE (1 << 14) - #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) -#ifdef __GNUC__ -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else -#define likely(x) (!!(x)) -#define unlikely(x) (!!(x)) -#endif - -#define MASK(x) ((1 << (x)) - 1) -#define BIT(x) (1 << (x)) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define ABS(a) ((a) < 0) ? -(a) : (a) #define dlogp(pred, fmt, ...) do { \ if (pred) { \ From 53290eadf0c2d692ee589ff4977e3b80c2e8ed1b Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 29 Nov 2023 14:24:53 +1100 Subject: [PATCH 14/23] Update SDDF submodule --- .gitmodules | 2 +- sddf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 82968620..364432db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,7 +5,7 @@ [submodule "sddf"] path = sddf url = https://github.com/au-ts/sddf.git - branch = kiss + branch = lionsos [submodule "micropython"] path = micropython url = https://github.com/Ivan-Velickovic/micropython.git diff --git a/sddf b/sddf index 1b508f05..b4a9a795 160000 --- a/sddf +++ b/sddf @@ -1 +1 @@ -Subproject commit 1b508f05d209d13a7b884d9ff9e1c990abcd2f77 +Subproject commit b4a9a795e61b48cdd6f56637aef89564c53db23b From f15742a4295cc09f42a3c6f8efef58f2f6b88a9f Mon Sep 17 00:00:00 2001 From: James Archer Date: Tue, 12 Dec 2023 17:55:58 +1100 Subject: [PATCH 15/23] Add ethernet multiplexing to system This commit enables multiplexing of the ethernet between the NFS client and MicroPython. In order to do this, the NFS client's ethernet support needed to be updated to reflect the latest sDDF protocol. The sDDF submodule commit was also updated. --- examples/kitty/Makefile | 68 +++++++- examples/kitty/kitty.system | 240 ++++++++++++++++++++++---- fs/nfs/Makefile | 4 +- fs/nfs/nfs.c | 8 +- fs/nfs/nfs.h | 6 + fs/nfs/tcp.c | 330 ++++++++++++++++++------------------ fs/nfs/tcp.h | 2 +- sddf | 2 +- 8 files changed, 448 insertions(+), 212 deletions(-) diff --git a/examples/kitty/Makefile b/examples/kitty/Makefile index b411a342..c86c73b1 100644 --- a/examples/kitty/Makefile +++ b/examples/kitty/Makefile @@ -39,8 +39,22 @@ LIBNFS=../../libnfs NFS=../../fs/nfs MUSL=../../musllibc -IMAGES := main.elf timer.elf vmm.elf ethernet.elf micropython.elf nfs.elf -CFLAGS := -mtune=$(CPU) -mstrict-align -ffreestanding -g -O0 -Wall -Wno-unused-function -I$(BOARD_DIR)/include -target $(TARGET) -I$(LIBVMM)/src/arch/aarch64 -I$(LIBVMM)/src -I$(LIBVMM)/src/util -DBOARD_$(MICROKIT_BOARD) +IMAGES := main.elf timer.elf vmm.elf ethernet.elf micropython.elf nfs.elf copy.elf mux_rx.elf mux_tx.elf arp.elf +CFLAGS := \ + -mtune=$(CPU) \ + -mstrict-align \ + -ffreestanding \ + -g \ + -O0 \ + -Wall \ + -Wno-unused-function \ + -I$(BOARD_DIR)/include \ + -target $(TARGET) \ + -I$(LIBVMM)/src/arch/aarch64 \ + -I$(LIBVMM)/src \ + -I$(LIBVMM)/src/util \ + -DBOARD_$(MICROKIT_BOARD) \ + -I$(SDDF)/include LDFLAGS := -L$(BOARD_DIR)/lib LIBS := -lmicrokit -Tmicrokit.ld @@ -171,6 +185,56 @@ $(BUILD_DIR)/nfs.elf: $(BUILD_DIR)/nfs/nfs.a $(BUILD_DIR)/sddf_network_sharedrin $(BUILD_DIR)/ethernet.elf: $(BUILD_DIR)/meson_ethernet.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ +NETWORK_COMPONENTS := $(SDDF)/network/components +NETWORK_COMPONENT_CFLAGS := \ + -I$(SDDF)/include \ + -I$(SDDF)/util/include \ + -I$(BOARD_DIR)/include \ + -I$(LWIP)/include \ + -I$(LWIP)/include/ipv4 \ + -mtune=$(CPU) \ + -mstrict-align \ + -ffreestanding \ + -g \ + -O0 \ + -Wall \ + -Wno-unused-function \ + -I$(LIBVMM)/src/arch/aarch64 \ + -I$(LIBVMM)/src \ + -I$(LIBVMM)/src/util \ + -DBOARD_$(MICROKIT_BOARD) +NETWORK_COMPONENTS_LDFLAGS := \ + -L$(BOARD_DIR)/lib \ + -L$(SDDF)/lib +NETWORK_COMPONENTS_LIBS := \ + -lmicrokit \ + -Tmicrokit.ld \ + -lc + +$(BUILD_DIR)/copy.o: $(NETWORK_COMPONENTS)/copy.c + aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ + +$(BUILD_DIR)/mux_rx.o: $(NETWORK_COMPONENTS)/mux_rx.c + aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ + +$(BUILD_DIR)/mux_tx.o: $(NETWORK_COMPONENTS)/mux_tx.c + aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ + +$(BUILD_DIR)/arp.o: $(NETWORK_COMPONENTS)/arp.c + aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ + +$(BUILD_DIR)/copy.elf: $(BUILD_DIR)/copy.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o + $(LD) $(NETWORK_COMPONENTS_LDFLAGS) build/sddf_network_sharedringbuffer.o build/copy.o $(NETWORK_COMPONENTS_LIBS) -o build/copy.elf + +$(BUILD_DIR)/mux_rx.elf: $(BUILD_DIR)/mux_rx.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o + $(LD) $(NETWORK_COMPONENTS_LDFLAGS) build/sddf_network_sharedringbuffer.o build/mux_rx.o $(NETWORK_COMPONENTS_LIBS) -o build/mux_rx.elf + +$(BUILD_DIR)/mux_tx.elf: $(BUILD_DIR)/mux_tx.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o + $(LD) $(NETWORK_COMPONENTS_LDFLAGS) build/sddf_network_sharedringbuffer.o build/mux_tx.o $(NETWORK_COMPONENTS_LIBS) -o build/mux_tx.elf + +$(BUILD_DIR)/arp.elf: $(BUILD_DIR)/arp.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/nfs/nfs.a + $(LD) $(NETWORK_COMPONENTS_LDFLAGS) build/sddf_network_sharedringbuffer.o build/arp.o $(BUILD_DIR)/nfs/nfs.a $(NETWORK_COMPONENTS_LIBS) -o build/arp.elf + directories: $(info $(shell mkdir -p $(BUILD_DIR)/lwip/src)) \ $(info $(shell mkdir -p $(BUILD_DIR)/lwip/src/core)) \ diff --git a/examples/kitty/kitty.system b/examples/kitty/kitty.system index 4c61be95..3974bfdf 100644 --- a/examples/kitty/kitty.system +++ b/examples/kitty/kitty.system @@ -32,11 +32,45 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -96,7 +130,7 @@ - + @@ -106,63 +140,199 @@ - - - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index bc3af45d..ee8269ce 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -49,9 +49,9 @@ INCLUDE := \ DEFINE := \ -DNFS_SERVER="\"$(NFS_SERVER)\"" \ -DNFS_DIRECTORY="\"$(NFS_DIRECTORY)\"" \ - -DETHERNET_INIT_CHANNEL=4 \ - -DETHERNET_TX_CHANNEL=2 \ + -DETHERNET_TX_CHANNEL=3 \ -DETHERNET_RX_CHANNEL=2 \ + -DETHERNET_ARP_CHANNEL=11 \ -DTIMER_CHANNEL=9 \ -DCLIENT_CHANNEL=7 diff --git a/fs/nfs/nfs.c b/fs/nfs/nfs.c index afe3c056..d03a3507 100644 --- a/fs/nfs/nfs.c +++ b/fs/nfs/nfs.c @@ -20,7 +20,7 @@ #include "tcp.h" #include "posix.h" -#define TIMEOUT (30 * NS_IN_MS) +#define TIMEOUT (10 * NS_IN_MS) struct nfs_context *nfs; @@ -44,6 +44,7 @@ void notified(microkit_channel ch) { sddf_timer_set_timeout(TIMEOUT); switch (ch) { case TIMER_CHANNEL: { + tcp_process_rx(); tcp_update(); if (tcp_ready() && nfs == NULL) { dlog("network ready, initing nfs"); @@ -67,9 +68,6 @@ void notified(microkit_channel ch) { } break; } - case ETHERNET_INIT_CHANNEL: - tcp_init_1(); - break; case ETHERNET_RX_CHANNEL: tcp_process_rx(); break; @@ -81,6 +79,8 @@ void notified(microkit_channel ch) { dlog("got notification from unknown channel"); break; } + + tcp_maybe_notify(); } void init(void) { diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index 765980bd..70041244 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -3,7 +3,13 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#define ARP_CHANNEL 7 + + extern struct nfs_context *nfs; void continuation_pool_init(void); void nfs_notified(void); + +int must_notify_rx(void); +int must_notify_tx(void); diff --git a/fs/nfs/tcp.c b/fs/nfs/tcp.c index 0db7d0d2..b899f7a0 100644 --- a/fs/nfs/tcp.c +++ b/fs/nfs/tcp.c @@ -30,26 +30,6 @@ #define NUM_BUFFERS 512 #define BUF_SIZE 2048 -typedef enum -{ - ORIGIN_RX_QUEUE, - ORIGIN_TX_QUEUE, -} ethernet_buffer_origin_t; - -typedef struct ethernet_buffer -{ - /* The actual underlying memory of the buffer */ - uintptr_t buffer; - /* The physical size of the buffer */ - size_t size; - /* Queue from which the buffer was allocated */ - char origin; - /* Index into buffer_metadata array */ - unsigned int index; - /* in use */ - bool in_use; -} ethernet_buffer_t; - typedef struct state { struct netif netif; @@ -59,12 +39,14 @@ typedef struct state /* Pointers to shared buffers */ ring_handle_t rx_ring; ring_handle_t tx_ring; - /* - * Metadata associated with buffers - */ - ethernet_buffer_t buffer_metadata[NUM_BUFFERS * 2]; } state_t; +typedef struct lwip_custom_pbuf +{ + struct pbuf_custom custom; + uintptr_t buffer; +} lwip_custom_pbuf_t; + typedef struct { struct tcp_pcb *sock_tpcb; int port; @@ -76,13 +58,6 @@ typedef struct { int rx_len; } socket_t; -typedef struct lwip_custom_pbuf -{ - struct pbuf_custom custom; - ethernet_buffer_t *buffer; - state_t *state; -} lwip_custom_pbuf_t; - state_t state; LWIP_MEMPOOL_DECLARE( @@ -91,71 +66,132 @@ LWIP_MEMPOOL_DECLARE( sizeof(lwip_custom_pbuf_t), "Zero-copy RX pool"); -ring_buffer_t *rx_free; -ring_buffer_t *rx_used; +uintptr_t rx_free; +uintptr_t rx_used; uintptr_t tx_free; uintptr_t tx_used; -uintptr_t copy_rx; -uintptr_t shared_dma_vaddr; +uintptr_t shared_dma_vaddr_rx; +uintptr_t shared_dma_vaddr_tx; // Should only need 1 at any one time, accounts for any reconnecting that might happen socket_t sockets[MAX_SOCKETS] = {0}; -bool network_ready; +static bool network_ready; +static bool notify_tx = false; +static bool notify_rx = false; int tcp_ready(void) { return network_ready; } +void tcp_maybe_notify(void) { + if (notify_rx && state.rx_ring.free_ring->notify_reader) { + state.rx_ring.free_ring->notify_reader = false; + notify_rx = false; + if (!have_signal) { + microkit_notify_delayed(ETHERNET_RX_CHANNEL); + } else if (signal != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_RX_CHANNEL) { + microkit_notify(ETHERNET_RX_CHANNEL); + } + } + + if (notify_tx && state.tx_ring.used_ring->notify_reader) { + state.tx_ring.used_ring->notify_reader = false; + notify_tx = false; + if (!have_signal) { + microkit_notify_delayed(ETHERNET_TX_CHANNEL); + } else if (signal != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_TX_CHANNEL) { + microkit_notify(ETHERNET_TX_CHANNEL); + } + } +} + +#define ROUND_DOWN(n, b) (((n) >> (b)) << (b)) +#define LINE_START(a) ROUND_DOWN(a, CONFIG_L1_CACHE_LINE_SIZE_BITS) +#define LINE_INDEX(a) (LINE_START(a)>>CONFIG_L1_CACHE_LINE_SIZE_BITS) + +static inline void +dsb(void) +{ + asm volatile("dsb sy" ::: "memory"); +} + +static inline void +dmb(void) +{ + asm volatile("dmb sy" ::: "memory"); +} + +static inline void +cleanInvalByVA(unsigned long vaddr) +{ + asm volatile("dc civac, %0" : : "r"(vaddr)); + dsb(); +} + +static inline void +cleanByVA(unsigned long vaddr) +{ + asm volatile("dc cvac, %0" : : "r"(vaddr)); + dmb(); +} + +void +cleanInvalidateCache(unsigned long start, unsigned long end) +{ + unsigned long line; + unsigned long index; + /* Clean the L1 range */ + + /* Finally clean and invalidate the L1 range. The extra clean is only strictly neccessary + * in a multiprocessor environment to prevent a write being lost if another core is + * attempting a store at the same time. As the range should already be clean asking + * it to clean again should not affect performance */ + for (index = LINE_INDEX(start); index < LINE_INDEX(end) + 1; index++) { + line = index << CONFIG_L1_CACHE_LINE_SIZE_BITS; + cleanInvalByVA(line); + } +} + +void +cleanCache(unsigned long start, unsigned long end) +{ + unsigned long line; + unsigned long index; + + for (index = LINE_INDEX(start); index < LINE_INDEX(end) + 1; index++) { + line = index << CONFIG_L1_CACHE_LINE_SIZE_BITS; + cleanByVA(line); + } +} + + uint32_t sys_now(void) { return sddf_timer_time_now() * US_IN_MS; } static void get_mac(void) { - microkit_ppcall(ETHERNET_INIT_CHANNEL, microkit_msginfo_new(0, 0)); - uint32_t palr = microkit_mr_get(0); - uint32_t paur = microkit_mr_get(1); - state.mac[3] = palr >> 24; - state.mac[2] = palr >> 16 & 0xff; - state.mac[1] = palr >> 8 & 0xff; - state.mac[0] = palr & 0xff; - state.mac[5] = paur >> 8 & 0xff; - state.mac[4] = paur & 0xff; + state.mac[0] = 0x52; + state.mac[1] = 0x54; + state.mac[2] = 0x1; + state.mac[3] = 0; + state.mac[4] = 0; + state.mac[5] = 10; } static void netif_status_callback(struct netif *netif) { if (dhcp_supplied_address(netif)) { dlog("DHCP request finished, IP address for netif %s is: %s", netif->name, ip4addr_ntoa(netif_ip4_addr(netif))); - network_ready = true; - } -} -/** - * Allocate an empty TX buffer from the empty pool - * - * @param state client state data. - * @param length length of buffer required - * - */ -static inline ethernet_buffer_t *alloc_tx_buffer(state_t *state, size_t length) { - if (BUF_SIZE < length) { - dlog("Requested buffer size too large."); - return NULL; - } - - uintptr_t addr; - unsigned int len; - ethernet_buffer_t *buffer; + microkit_mr_set(0, ip4_addr_get_u32(netif_ip4_addr(netif))); + microkit_mr_set(1, (state.mac[0] << 24) | (state.mac[1] << 16) | (state.mac[2] << 8) | (state.mac[3])); + microkit_mr_set(2, (state.mac[4] << 24) | (state.mac[5] << 16)); + microkit_ppcall(ETHERNET_ARP_CHANNEL, microkit_msginfo_new(0, 3)); - dequeue_free(&state->tx_ring, &addr, &len, (void **)&buffer); - if (!buffer) { - dlog("lwip: dequeued a null ethernet buffer"); + network_ready = true; } - - return buffer; } - static err_t lwip_eth_send(struct netif *netif, struct pbuf *p) { /* Grab an available TX buffer, copy pbuf data over, add to used tx ring, notify server */ @@ -164,14 +200,15 @@ static err_t lwip_eth_send(struct netif *netif, struct pbuf *p) { if (p->tot_len > BUF_SIZE) { return ERR_MEM; } - - state_t *state = (state_t *)netif->state; - - ethernet_buffer_t *buffer = alloc_tx_buffer(state, p->tot_len); - if (buffer == NULL) { + uintptr_t addr; + unsigned int len; + void *cookie; + int err = dequeue_free(&state.tx_ring, &addr, &len, &cookie); + if (err) { return ERR_MEM; } - unsigned char *frame = (unsigned char *)buffer->buffer; + uintptr_t buffer = addr; + unsigned char *frame = (unsigned char *)buffer; /* Copy all buffers that need to be copied */ unsigned int copied = 0; @@ -184,34 +221,21 @@ static err_t lwip_eth_send(struct netif *netif, struct pbuf *p) { copied += curr->len; } - int err = seL4_ARM_VSpace_Clean_Data(3, (uintptr_t)frame, (uintptr_t)frame + copied); - if (err) { - dlog("ARM Vspace clean failed: %d\n", err); - } + cleanCache((unsigned long) frame, (unsigned long) frame + copied); /* insert into the used tx queue */ - int error = enqueue_used(&state->tx_ring, (uintptr_t)frame, copied, buffer); - if (error) { - dlog("TX used ring full\n"); - enqueue_free(&(state->tx_ring), (uintptr_t)frame, BUF_SIZE, buffer); + err = enqueue_used(&state.tx_ring, (uintptr_t)frame, copied, NULL); + if (err) { + dlog("TX used ring full"); + enqueue_free(&(state.tx_ring), (uintptr_t)frame, BUF_SIZE, NULL); return ERR_MEM; } - /* Notify the server for next time we recv() */ - have_signal = true; - signal_msg = seL4_MessageInfo_new(0, 0, 0, 0); - signal = (BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_TX_CHANNEL); - /* NOTE: If driver is passive, we want to Call instead. */ + notify_tx = true; return ret; } -static inline void return_buffer(state_t *state, ethernet_buffer_t *buffer) { - /* As the rx_freeable ring is the size of the number of buffers we have, - the ring should never be full. */ - enqueue_free(&(state->rx_ring), buffer->buffer, BUF_SIZE, buffer); -} - /** * Free a pbuf. This also returns the underlying buffer to * the appropriate place. @@ -221,40 +245,14 @@ static inline void return_buffer(state_t *state, ethernet_buffer_t *buffer) { */ static void interface_free_buffer(struct pbuf *buf) { SYS_ARCH_DECL_PROTECT(old_level); - lwip_custom_pbuf_t *custom_pbuf = (lwip_custom_pbuf_t *)buf; - SYS_ARCH_PROTECT(old_level); - return_buffer(custom_pbuf->state, custom_pbuf->buffer); + enqueue_free(&state.rx_ring, custom_pbuf->buffer, BUF_SIZE, NULL); + notify_rx = true; LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf); SYS_ARCH_UNPROTECT(old_level); } -/** - * Create a pbuf structure to pass to the network interface. - * - * @param state client state data. - * @param buffer ethernet buffer containing metadata for the actual buffer - * @param length length of data - * - * @return the newly created pbuf. - */ -static struct pbuf *create_interface_buffer(state_t *state, ethernet_buffer_t *buffer, size_t length) { - lwip_custom_pbuf_t *custom_pbuf = (lwip_custom_pbuf_t *)LWIP_MEMPOOL_ALLOC(RX_POOL); - - custom_pbuf->state = state; - custom_pbuf->buffer = buffer; - custom_pbuf->custom.custom_free_function = interface_free_buffer; - - return pbuf_alloced_custom( - PBUF_RAW, - length, - PBUF_REF, - &custom_pbuf->custom, - (void *)buffer->buffer, - buffer->size); -} - /** * Initialise the network interface data structure. * @@ -289,21 +287,22 @@ void tcp_process_rx(void) { while (!ring_empty(state.rx_ring.used_ring)) { uintptr_t addr; unsigned int len; - ethernet_buffer_t *buffer; - - dequeue_used(&state.rx_ring, &addr, &len, (void **)&buffer); + void *cookie; - if (addr != buffer->buffer) { - dlog("sanity check failed"); - } + dequeue_used(&state.rx_ring, &addr, &len, &cookie); - /* Invalidate the memory */ - int err = seL4_ARM_VSpace_Invalidate_Data(3, buffer->buffer, buffer->buffer + ETHER_MTU); - if (err) { - dlog("ARM Vspace invalidate failed: %d", err); - } + lwip_custom_pbuf_t *custom_pbuf = (lwip_custom_pbuf_t *)LWIP_MEMPOOL_ALLOC(RX_POOL); + custom_pbuf->buffer = addr; + custom_pbuf->custom.custom_free_function = interface_free_buffer; - struct pbuf *p = create_interface_buffer(&state, (void *)buffer, len); + struct pbuf *p = pbuf_alloced_custom( + PBUF_RAW, + len, + PBUF_REF, + &custom_pbuf->custom, + (void *)addr, + BUF_SIZE + ); if (state.netif.input(p, &state.netif) != ERR_OK) { // If it is successfully received, the receiver controls whether or not it gets freed. @@ -321,36 +320,17 @@ void tcp_update(void) void tcp_init_0(void) { /* Set up shared memory regions */ - ring_init(&state.rx_ring, rx_free, (ring_buffer_t *)rx_used, 1, SIZE, SIZE); - ring_init(&state.tx_ring, (ring_buffer_t *)tx_free, (ring_buffer_t *)tx_used, 1, SIZE, SIZE); - - for (int i = 0; i < NUM_BUFFERS - 1; i++) { - ethernet_buffer_t *buffer = &state.buffer_metadata[i]; - *buffer = (ethernet_buffer_t){ - .buffer = shared_dma_vaddr + (BUF_SIZE * i), - .size = BUF_SIZE, - .origin = ORIGIN_RX_QUEUE, - .index = i, - .in_use = false, - }; - enqueue_free(&state.rx_ring, buffer->buffer, BUF_SIZE, buffer); - } + ring_init(&state.rx_ring, rx_free, rx_used, 1, NUM_BUFFERS, NUM_BUFFERS); + ring_init(&state.tx_ring, tx_free, tx_used, 0, NUM_BUFFERS, NUM_BUFFERS); for (int i = 0; i < NUM_BUFFERS - 1; i++) { - ethernet_buffer_t *buffer = &state.buffer_metadata[i + NUM_BUFFERS]; - *buffer = (ethernet_buffer_t){ - .buffer = shared_dma_vaddr + (BUF_SIZE * (i + NUM_BUFFERS)), - .size = BUF_SIZE, - .origin = ORIGIN_TX_QUEUE, - .index = i + NUM_BUFFERS, - .in_use = false, - }; - enqueue_free(&state.tx_ring, buffer->buffer, BUF_SIZE, buffer); + uintptr_t addr = shared_dma_vaddr_rx + (BUF_SIZE * i); + enqueue_free(&state.rx_ring, addr, BUF_SIZE, NULL); } + get_mac(); lwip_init(); LWIP_MEMPOOL_INIT(RX_POOL); - get_mac(); /* Set some dummy IP configuration values to get lwIP bootstrapped */ struct ip4_addr netmask, ipaddr, gw, multicast; @@ -364,21 +344,37 @@ void tcp_init_0(void) if (!netif_add(&(state.netif), &ipaddr, &netmask, &gw, &state, ethernet_init, ethernet_input)) { - dlog("Netif add returned NULL\n"); + dlog("Netif add returned NULL"); } - netif_set_default(&(state.netif)); - - microkit_notify(ETHERNET_INIT_CHANNEL); -} - -void tcp_init_1(void) -{ netif_set_status_callback(&(state.netif), netif_status_callback); netif_set_up(&(state.netif)); int err = dhcp_start(&(state.netif)); dlogp(err, "failed to start DHCP negotiation"); + + state.rx_ring.free_ring->notify_reader = true; + state.rx_ring.used_ring->notify_reader = true; + state.tx_ring.free_ring->notify_reader = true; + state.tx_ring.used_ring->notify_reader = true; + + if (notify_rx && state.rx_ring.free_ring->notify_reader) { + notify_rx = false; + if (!have_signal) { + microkit_notify_delayed(ETHERNET_RX_CHANNEL); + } else if (signal != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_RX_CHANNEL) { + microkit_notify(ETHERNET_RX_CHANNEL); + } + } + + if (notify_tx && state.tx_ring.used_ring->notify_reader) { + notify_tx = false; + if (!have_signal) { + microkit_notify_delayed(ETHERNET_TX_CHANNEL); + } else if (signal != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_TX_CHANNEL) { + microkit_notify(ETHERNET_TX_CHANNEL); + } + } } void socket_err_func(void *arg, err_t err) diff --git a/fs/nfs/tcp.h b/fs/nfs/tcp.h index a14f558d..38b049f6 100644 --- a/fs/nfs/tcp.h +++ b/fs/nfs/tcp.h @@ -7,10 +7,10 @@ #define SOCKET_BUF_SIZE 0x200000 void tcp_init_0(void); -void tcp_init_1(void); int tcp_ready(void); void tcp_update(void); void tcp_process_rx(void); +void tcp_maybe_notify(void); int tcp_socket_create(void); int tcp_socket_connect(int index, int port); diff --git a/sddf b/sddf index b4a9a795..962c5589 160000 --- a/sddf +++ b/sddf @@ -1 +1 @@ -Subproject commit b4a9a795e61b48cdd6f56637aef89564c53db23b +Subproject commit 962c558982a3437686754237fd158c5e7f8cfa73 From 8cea4c5aa7e7ae8e4ca1b3ce1e6fe90080e7e31f Mon Sep 17 00:00:00 2001 From: James Archer Date: Wed, 13 Dec 2023 18:53:27 +1100 Subject: [PATCH 16/23] Update README instructions for NFS client --- README.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ead93961..018891ad 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,9 @@ On Nix/NixOS: nix-shell --pure ``` +You will also need an aarch64 GCC toolchain. The system has been tested with this toolchain: (https://developer.arm.com/-/media/Files/downloads/gnu-a/10.2-2020.11/binrel/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf.tar.xz?revision=79f65c42-1a1b-43f2-acb7-a795c8427085&hash=61BBFB526E785D234C5D8718D9BA8E61). Put the bin directory of the GCC toolchain in your PATH. + + ### Getting the Microkit SDK There are a lot of changes to Microkit that have been made over the past year which means @@ -68,6 +71,11 @@ cd LionsOS git submodule update --init # Enter the Kitty demo directory cd examples/kitty +# Define NFS server to be used by the NFS client +export NFS_SERVER=0.0.0.0 # IP adddress of NFS server +export NFS_DIRECTORY=/path/to/dir +# Define path to libgcc, where $GCC is the GCC toolchain downloaded above +export LIBGCC=$GCC/lib/gcc/aarch64-none-elf/11.3.1 # Now compile the demo make MICROKIT_SDK=/path/to/microkit-sdk-1.2.6 ``` @@ -92,6 +100,31 @@ MQ with the `-a` flag to automatically get a connection where you can also input mq.sh run -c "MicroPython" -a -l mqlog -s odroidc4_pool -f build/kitty.img ``` +### Testing MicroPython's NFS support + +The Kitty system includes an NFS client which MicroPython uses as its filesystem. Most (but not all) of MicroPython's standard file IO operations are supported (importing modules, the file object's methods and functions from the `os` module). + +```python +>>> os.listdir() +[] +>>> with open('hello.py') as f: +... f.write('print("hello world")\n') +... +21 +>>> os.listdir() +['hello.py'] +>>> with open('hello.py') as f: +... print(f.read()) +... +print("hello world") + +>>> import hello +hello world +>>> os.remove('hello.py') +>>> os.listdir() +[] +``` + ## Working on Kitty components For now, all experimentation is to be done in the respective repository. @@ -129,4 +162,3 @@ mdbook serve --open * [Microkit development source code](https://github.com/Ivan-Velickovic/microkit) * [Odroid-C4 wiki](https://wiki.odroid.com/odroid-c4/odroid-c4) * [Odroid-C4 SoC Techincal Reference Manual](https://dn.odroid.com/S905X3/ODROID-C4/Docs/S905X3_Public_Datasheet_Hardkernel.pdf) - From 70d42c30cecf51cb18070ec94ffe4216a8af1ecd Mon Sep 17 00:00:00 2001 From: James Archer Date: Thu, 14 Dec 2023 13:39:15 +1100 Subject: [PATCH 17/23] Update ARP component build --- examples/kitty/Makefile | 38 +++++++++++++++++++------------------- sddf | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/kitty/Makefile b/examples/kitty/Makefile index c86c73b1..f791fc37 100644 --- a/examples/kitty/Makefile +++ b/examples/kitty/Makefile @@ -186,30 +186,30 @@ $(BUILD_DIR)/ethernet.elf: $(BUILD_DIR)/meson_ethernet.o $(BUILD_DIR)/sddf_netwo $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ NETWORK_COMPONENTS := $(SDDF)/network/components -NETWORK_COMPONENT_CFLAGS := \ +NETWORK_COMPONENTS_INCLUDE := \ -I$(SDDF)/include \ -I$(SDDF)/util/include \ -I$(BOARD_DIR)/include \ -I$(LWIP)/include \ - -I$(LWIP)/include/ipv4 \ - -mtune=$(CPU) \ + -I$(LWIP)/include/ipv4 +NETWORK_COMPONENT_CFLAGS := \ + $(NETWORK_COMPONENTS_INCLUDE) \ -mstrict-align \ -ffreestanding \ -g \ -O0 \ -Wall \ -Wno-unused-function \ - -I$(LIBVMM)/src/arch/aarch64 \ - -I$(LIBVMM)/src \ - -I$(LIBVMM)/src/util \ - -DBOARD_$(MICROKIT_BOARD) -NETWORK_COMPONENTS_LDFLAGS := \ - -L$(BOARD_DIR)/lib \ - -L$(SDDF)/lib -NETWORK_COMPONENTS_LIBS := \ - -lmicrokit \ - -Tmicrokit.ld \ - -lc + -DNO_ASSERT \ + -DBOARD_$(MICROKIT_BOARD) \ + -MD \ + -MP + +NETWORK_COMPONENTS_LDFLAGS := -L$(BOARD_DIR)/lib -L$(SDDF)/lib -L$(LIBGCC) +NETWORK_COMPONENTS_LIBS := -lmicrokit -Tmicrokit.ld -lc -lgcc + +$(BUILD_DIR)/cache.o: $(SDDF)/util/cache.c + aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ $(BUILD_DIR)/copy.o: $(NETWORK_COMPONENTS)/copy.c aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ @@ -224,16 +224,16 @@ $(BUILD_DIR)/arp.o: $(NETWORK_COMPONENTS)/arp.c aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ $(BUILD_DIR)/copy.elf: $(BUILD_DIR)/copy.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o - $(LD) $(NETWORK_COMPONENTS_LDFLAGS) build/sddf_network_sharedringbuffer.o build/copy.o $(NETWORK_COMPONENTS_LIBS) -o build/copy.elf + aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/copy.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/copy.elf $(BUILD_DIR)/mux_rx.elf: $(BUILD_DIR)/mux_rx.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o - $(LD) $(NETWORK_COMPONENTS_LDFLAGS) build/sddf_network_sharedringbuffer.o build/mux_rx.o $(NETWORK_COMPONENTS_LIBS) -o build/mux_rx.elf + aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/mux_rx.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/mux_rx.elf $(BUILD_DIR)/mux_tx.elf: $(BUILD_DIR)/mux_tx.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o - $(LD) $(NETWORK_COMPONENTS_LDFLAGS) build/sddf_network_sharedringbuffer.o build/mux_tx.o $(NETWORK_COMPONENTS_LIBS) -o build/mux_tx.elf + aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/mux_tx.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/mux_tx.elf -$(BUILD_DIR)/arp.elf: $(BUILD_DIR)/arp.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/nfs/nfs.a - $(LD) $(NETWORK_COMPONENTS_LDFLAGS) build/sddf_network_sharedringbuffer.o build/arp.o $(BUILD_DIR)/nfs/nfs.a $(NETWORK_COMPONENTS_LIBS) -o build/arp.elf +$(BUILD_DIR)/arp.elf: $(BUILD_DIR)/arp.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/cache.o $(BUILD_DIR)/nfs/nfs.a + aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/arp.o $(BUILD_DIR)/cache.o $(BUILD_DIR)/nfs/lwip/core/inet_chksum.o $(BUILD_DIR)/nfs/lwip/core/def.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/arp.elf directories: $(info $(shell mkdir -p $(BUILD_DIR)/lwip/src)) \ diff --git a/sddf b/sddf index 962c5589..e0fddd40 160000 --- a/sddf +++ b/sddf @@ -1 +1 @@ -Subproject commit 962c558982a3437686754237fd158c5e7f8cfa73 +Subproject commit e0fddd4063fca75520086af26575759ec32a0b81 From b6ef21cde5d128636eafb45f757b5fadeacc8e1a Mon Sep 17 00:00:00 2001 From: James Archer Date: Thu, 14 Dec 2023 14:07:02 +1100 Subject: [PATCH 18/23] Update sDDF commit --- sddf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sddf b/sddf index e0fddd40..9e6f7a01 160000 --- a/sddf +++ b/sddf @@ -1 +1 @@ -Subproject commit e0fddd4063fca75520086af26575759ec32a0b81 +Subproject commit 9e6f7a0188f1bac522c46cad5a5aac5b40c15e9b From e692c45170adff4dde1a7f19c1f0887a2f2e1bfe Mon Sep 17 00:00:00 2001 From: James Archer Date: Thu, 14 Dec 2023 14:06:06 +1100 Subject: [PATCH 19/23] Remove cache.o build rule from Kitty makefile --- examples/kitty/Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/kitty/Makefile b/examples/kitty/Makefile index f791fc37..64e78a69 100644 --- a/examples/kitty/Makefile +++ b/examples/kitty/Makefile @@ -208,9 +208,6 @@ NETWORK_COMPONENT_CFLAGS := \ NETWORK_COMPONENTS_LDFLAGS := -L$(BOARD_DIR)/lib -L$(SDDF)/lib -L$(LIBGCC) NETWORK_COMPONENTS_LIBS := -lmicrokit -Tmicrokit.ld -lc -lgcc -$(BUILD_DIR)/cache.o: $(SDDF)/util/cache.c - aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ - $(BUILD_DIR)/copy.o: $(NETWORK_COMPONENTS)/copy.c aarch64-none-elf-gcc -c $(NETWORK_COMPONENT_CFLAGS) $< -o $@ @@ -233,7 +230,7 @@ $(BUILD_DIR)/mux_tx.elf: $(BUILD_DIR)/mux_tx.o $(BUILD_DIR)/sddf_network_sharedr aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/mux_tx.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/mux_tx.elf $(BUILD_DIR)/arp.elf: $(BUILD_DIR)/arp.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/cache.o $(BUILD_DIR)/nfs/nfs.a - aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/arp.o $(BUILD_DIR)/cache.o $(BUILD_DIR)/nfs/lwip/core/inet_chksum.o $(BUILD_DIR)/nfs/lwip/core/def.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/arp.elf + aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/arp.o $(BUILD_DIR)/nfs/lwip/core/inet_chksum.o $(BUILD_DIR)/nfs/lwip/core/def.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/arp.elf directories: $(info $(shell mkdir -p $(BUILD_DIR)/lwip/src)) \ From 94fbb6c3ac588e5059624e9518d6198361426f5d Mon Sep 17 00:00:00 2001 From: James Archer Date: Thu, 14 Dec 2023 13:45:55 +1100 Subject: [PATCH 20/23] Update microkit signal variable names --- fs/nfs/tcp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/nfs/tcp.c b/fs/nfs/tcp.c index b899f7a0..517cf07e 100644 --- a/fs/nfs/tcp.c +++ b/fs/nfs/tcp.c @@ -90,7 +90,7 @@ void tcp_maybe_notify(void) { notify_rx = false; if (!have_signal) { microkit_notify_delayed(ETHERNET_RX_CHANNEL); - } else if (signal != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_RX_CHANNEL) { + } else if (signal_cap != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_RX_CHANNEL) { microkit_notify(ETHERNET_RX_CHANNEL); } } @@ -100,7 +100,7 @@ void tcp_maybe_notify(void) { notify_tx = false; if (!have_signal) { microkit_notify_delayed(ETHERNET_TX_CHANNEL); - } else if (signal != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_TX_CHANNEL) { + } else if (signal_cap != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_TX_CHANNEL) { microkit_notify(ETHERNET_TX_CHANNEL); } } @@ -362,7 +362,7 @@ void tcp_init_0(void) notify_rx = false; if (!have_signal) { microkit_notify_delayed(ETHERNET_RX_CHANNEL); - } else if (signal != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_RX_CHANNEL) { + } else if (signal_cap != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_RX_CHANNEL) { microkit_notify(ETHERNET_RX_CHANNEL); } } @@ -371,7 +371,7 @@ void tcp_init_0(void) notify_tx = false; if (!have_signal) { microkit_notify_delayed(ETHERNET_TX_CHANNEL); - } else if (signal != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_TX_CHANNEL) { + } else if (signal_cap != BASE_OUTPUT_NOTIFICATION_CAP + ETHERNET_TX_CHANNEL) { microkit_notify(ETHERNET_TX_CHANNEL); } } From b39a855bbef4e366d31e273062bbb7bd71e99e8d Mon Sep 17 00:00:00 2001 From: James Archer Date: Thu, 14 Dec 2023 14:11:14 +1100 Subject: [PATCH 21/23] Remove bad make dependency --- examples/kitty/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/kitty/Makefile b/examples/kitty/Makefile index 64e78a69..febb79c3 100644 --- a/examples/kitty/Makefile +++ b/examples/kitty/Makefile @@ -229,7 +229,7 @@ $(BUILD_DIR)/mux_rx.elf: $(BUILD_DIR)/mux_rx.o $(BUILD_DIR)/sddf_network_sharedr $(BUILD_DIR)/mux_tx.elf: $(BUILD_DIR)/mux_tx.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/mux_tx.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/mux_tx.elf -$(BUILD_DIR)/arp.elf: $(BUILD_DIR)/arp.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/cache.o $(BUILD_DIR)/nfs/nfs.a +$(BUILD_DIR)/arp.elf: $(BUILD_DIR)/arp.o $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/nfs/nfs.a aarch64-none-elf-ld $(NETWORK_COMPONENTS_LDFLAGS) $(BUILD_DIR)/sddf_network_sharedringbuffer.o $(BUILD_DIR)/arp.o $(BUILD_DIR)/nfs/lwip/core/inet_chksum.o $(BUILD_DIR)/nfs/lwip/core/def.o $(NETWORK_COMPONENTS_LIBS) -o $(BUILD_DIR)/arp.elf directories: From f213d5298af85c71421145d7a2da7a6bc4dda553 Mon Sep 17 00:00:00 2001 From: James Archer Date: Thu, 14 Dec 2023 14:25:44 +1100 Subject: [PATCH 22/23] Restore VMM-Micropython channel --- examples/kitty/kitty.system | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/kitty/kitty.system b/examples/kitty/kitty.system index 3974bfdf..b5e2294e 100644 --- a/examples/kitty/kitty.system +++ b/examples/kitty/kitty.system @@ -335,4 +335,13 @@ + + + + + + From 329a9966d08aa6c0b22c26a61ee748db48e3a05d Mon Sep 17 00:00:00 2001 From: Ivan Velickovic Date: Fri, 15 Dec 2023 14:37:36 +1100 Subject: [PATCH 23/23] ci: fixes Unfortunately libnfs does not seem to work with Clang and also needs libgcc for some reason. This patch puts the CI in a state where it can build the current work-in-progress Kitty system until we can sort it out and have it all build with Clang. --- .github/workflows/ci.yaml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 97ae1b76..ae2d56bf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,6 +20,13 @@ jobs: shell: bash - name: Extract Microkit SDK run: unzip microkit-sdk.zip && tar -xf microkit-sdk-1.2.6.tar.gz + - name: Download and install AArch64 GCC toolchain + run: | + wget -O aarch64-toolchain.tar.gz https://trustworthy.systems/Downloads/microkit/arm-gnu-toolchain-11.3.rel1-x86_64-aarch64-none-elf.tar.xz%3Frev%3D73ff9780c12348b1b6772a1f54ab4bb3 + tar xf aarch64-toolchain.tar.gz + echo "$(pwd)/arm-gnu-toolchain-11.3.rel1-x86_64-aarch64-none-elf/bin" >> $GITHUB_PATH - name: Build Kitty example - run: nix-shell --pure --run "make -C examples/kitty MICROKIT_SDK=$(pwd)/microkit-sdk-1.2.6" - + run: export LIBGCC=$(pwd)/arm-gnu-toolchain-11.3.rel1-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/11.3.1 && make -C examples/kitty MICROKIT_SDK=$(pwd)/microkit-sdk-1.2.6 + env: + NFS_SERVER: 0.0.0.0 + NFS_DIRECTORY: test/