From a7a01f8ea193d2767467857fe8ebd736184decd5 Mon Sep 17 00:00:00 2001 From: Daniel Schwyn Date: Mon, 4 Apr 2022 15:16:17 +0200 Subject: [PATCH] Bug fixes Signed-off-by: Daniel Schwyn --- .gitignore | 1 + include/arch/aarch64/aos/invocations_arch.h | 12 ++ include/barrelfish_kpi/platform.h | 1 + include/barrelfish_kpi/sys_debug.h | 1 + include/drivers/pl011.h | 34 +++++ include/maps/qemu_map.h | 37 ++++++ include/stdlib.h | 6 +- kernel/arch/arm/gic.c | 3 +- kernel/arch/arm/gic_v2.c | 3 +- kernel/arch/arm/gic_v3.c | 3 +- kernel/arch/armv8/paging.c | 81 ++++++++++-- kernel/arch/armv8/plat_qemu.c | 9 +- kernel/arch/armv8/syscall.c | 7 +- kernel/include/arch/armv8/startup_arch.h | 6 +- kernel/include/capabilities.h | 2 +- lib/aos/aos_rpc.c | 6 +- lib/aos/include/threads_priv.h | 3 + lib/aos/paging.c | 14 +-- lib/aos/slab.c | 33 +++-- lib/aos/slot_alloc/slot_alloc.c | 2 + lib/aos/slot_alloc/twolevel_slot_alloc.c | 4 +- lib/libc/sys/barrelfish/syscalls.c | 8 +- lib/spawn/spawn.c | 1 + tools/bfdocker.sh | 15 ++- tools/docker/Makefile | 4 +- tools/docker/entrypoint.sh | 9 +- tools/docker/install.sh | 8 +- usr/drivers/pl011/Hakefile | 19 +++ usr/drivers/pl011/main.c | 132 ++++++++++++++++++++ usr/init/main.c | 34 ++++- 30 files changed, 432 insertions(+), 66 deletions(-) create mode 100644 include/drivers/pl011.h create mode 100644 include/maps/qemu_map.h create mode 100644 usr/drivers/pl011/Hakefile create mode 100644 usr/drivers/pl011/main.c diff --git a/.gitignore b/.gitignore index 73e505f..56777ec 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ bin/ # clang .clang_complete compile_commands.json +test-logs diff --git a/include/arch/aarch64/aos/invocations_arch.h b/include/arch/aarch64/aos/invocations_arch.h index c041e37..2b5436b 100644 --- a/include/arch/aarch64/aos/invocations_arch.h +++ b/include/arch/aarch64/aos/invocations_arch.h @@ -21,6 +21,7 @@ #include // for distcap_state_t #include // invoking lmp endpoint requires flags #include +#include // for struct platform info #include #include @@ -241,4 +242,15 @@ static inline errval_t invoke_vnode_inherit(struct capref dest, capaddr_t src, newflags, src_mcn, dst_mcn).error; } +static inline errval_t invoke_kernel_get_platform_info(struct capref kernel_cap, struct platform_info* pi) +{ + struct sysret sr = cap_invoke2(kernel_cap, KernelCmd_Get_platform, (lvaddr_t)pi); + if (err_is_fail(sr.error)) { + pi->arch = PI_ARCH_UNKNOWN; + pi->platform = PI_PLATFORM_UNKNOWN; + } + + return sr.error; +} + #endif diff --git a/include/barrelfish_kpi/platform.h b/include/barrelfish_kpi/platform.h index 48cb74d..1597d13 100644 --- a/include/barrelfish_kpi/platform.h +++ b/include/barrelfish_kpi/platform.h @@ -19,6 +19,7 @@ #include enum pi_arch { + PI_ARCH_UNKNOWN, PI_ARCH_X86, PI_ARCH_ARMV7A, PI_ARCH_ARMV8A, diff --git a/include/barrelfish_kpi/sys_debug.h b/include/barrelfish_kpi/sys_debug.h index 5a2354f..1135197 100644 --- a/include/barrelfish_kpi/sys_debug.h +++ b/include/barrelfish_kpi/sys_debug.h @@ -38,6 +38,7 @@ enum debug_message { DEBUG_CREATE_IRQ_SRC_CAP, DEBUG_GET_MDB_SIZE, DEBUG_PRINT_MDB_COUNTERS, + DEBUG_GET_PLATFORM_INFO, }; #endif //BARRELFISH_KPI_SYS_DEBUG_H diff --git a/include/drivers/pl011.h b/include/drivers/pl011.h new file mode 100644 index 0000000..25c4dec --- /dev/null +++ b/include/drivers/pl011.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, ETH Zurich. + * Copyright (c) 2022, The University of British Columbia. + * All rights reserved. + * + * This file is distributed under the terms in the attached LICENSE file. + * If you do not find this file, copies can be found by writing to: + * ETH Zurich D-INFK, CAB F.78, Universitaetstr 6, CH-8092 Zurich. + */ + +#ifndef PL011_H_ +#define PL011_H_ + +#include +#include + +//#define PL011_DEBUG_ON +#if defined(PL011_DEBUG_ON) +#define PL011_DEBUG(x...) debug_printf("pl011:" x) +#else +#define PL011_DEBUG(x...) ((void)0) +#endif + +#define PL011_UART0_INT 1 + +struct pl011_s; + +errval_t pl011_init(struct pl011_s** s, void *base); +errval_t pl011_enable_interrupt(struct pl011_s * s); +errval_t pl011_putchar(struct pl011_s* s, char c); +errval_t pl011_getchar(struct pl011_s* s, char *c); + + +#endif diff --git a/include/maps/qemu_map.h b/include/maps/qemu_map.h new file mode 100644 index 0000000..44adb8f --- /dev/null +++ b/include/maps/qemu_map.h @@ -0,0 +1,37 @@ +/** + * \file + * \brief Physical memory map for the QEMU Virt Platform + */ + +/* + * Copyright (c) 2022, The University of British Columbia. + * All rights reserved. + * + * This file is distributed under the terms in the attached LICENSE file. + * If you do not find this file, copies can be found by writing to: + * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich. + * Attn: Systems Group. + */ + +#ifndef QEMU_MAP_H +#define QEMU_MAP_H + + +#define QEMU_SPI_INTERRUPTS_START 32 + +/* + * UART + */ + +#define QEMU_UART_BASE 0x09000000 +#define QEMU_UART_SIZE 0x1000 +#define QEMU_UART_INT (QEMU_SPI_INTERRUPTS_START + PL011_UART0_INT) +/* + * GIC Distributor + */ +#define QEMU_GIC_DIST_BASE 0x08000000 +#define QEMU_GIC_DIST_SIZE 0x1000 + + + +#endif // QEMU_MAP_H diff --git a/include/stdlib.h b/include/stdlib.h index 73bc6ee..30e9091 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -88,7 +88,7 @@ long atol(const char *); void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); void *calloc(size_t, size_t) __malloc_like __result_use_check - __alloc_size(1) __alloc_size(2); + __attribute__((__alloc_size__(1, 2))); div_t div(int, int) __pure2; _Noreturn void exit(int); void free(void *); @@ -303,8 +303,8 @@ void qsort_r(void *, size_t, size_t, void *, int (*)(void *, const void *, const void *)); int radixsort(const unsigned char **, int, const unsigned char *, unsigned); -void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size(2) - __alloc_size(3); +void *reallocarray(void *, size_t, size_t) __result_use_check + __attribute__((__alloc_size__(2, 3))); void *reallocf(void *, size_t) __alloc_size(2); int rpmatch(const char *); void setprogname(const char *); diff --git a/kernel/arch/arm/gic.c b/kernel/arch/arm/gic.c index 9120047..6587ef7 100644 --- a/kernel/arch/arm/gic.c +++ b/kernel/arch/arm/gic.c @@ -28,7 +28,8 @@ extern lpaddr_t platform_gic_distributor_base; // Command line arguments static struct cmdarg cmdargs[] = { {"gic", ArgType_UInt, { .uinteger = &platform_gic_cpu_interface_base }}, - {"gicdist", ArgType_UInt, { .uinteger = &platform_gic_distributor_base }} + {"gicdist", ArgType_UInt, { .uinteger = &platform_gic_distributor_base }}, + {NULL, 0, {NULL}} }; enum IrqType { diff --git a/kernel/arch/arm/gic_v2.c b/kernel/arch/arm/gic_v2.c index ba3c34d..6b1bd22 100644 --- a/kernel/arch/arm/gic_v2.c +++ b/kernel/arch/arm/gic_v2.c @@ -26,7 +26,8 @@ extern lpaddr_t platform_gic_distributor_base; // Command line arguments static struct cmdarg cmdargs[] = { {"gic", ArgType_ULong, { .ulonginteger = &platform_gic_cpu_interface_base }}, - {"gicdist", ArgType_ULong, { .ulonginteger = &platform_gic_distributor_base }} + {"gicdist", ArgType_ULong, { .ulonginteger = &platform_gic_distributor_base }}, + {NULL, 0, {NULL}} }; /* diff --git a/kernel/arch/arm/gic_v3.c b/kernel/arch/arm/gic_v3.c index 4b87dbb..c67cc80 100644 --- a/kernel/arch/arm/gic_v3.c +++ b/kernel/arch/arm/gic_v3.c @@ -27,7 +27,8 @@ extern lpaddr_t platform_gic_redistributor_base; // Command line arguments static struct cmdarg cmdargs[] = { {"gicdist", ArgType_ULong, { .ulonginteger = &platform_gic_distributor_base }}, - {"gicredist", ArgType_ULong, { .ulonginteger = &platform_gic_redistributor_base }} + {"gicredist", ArgType_ULong, { .ulonginteger = &platform_gic_redistributor_base }}, + {NULL, 0, {NULL}} }; /* diff --git a/kernel/arch/armv8/paging.c b/kernel/arch/armv8/paging.c index 44433ce..7d77df9 100644 --- a/kernel/arch/armv8/paging.c +++ b/kernel/arch/armv8/paging.c @@ -525,8 +525,14 @@ caps_map_l3(struct capability* dest, { assert(0 == (kpi_paging_flags & ~KPI_PAGING_FLAGS_MASK)); - if (slot + pte_count >= VMSAv8_64_PTABLE_NUM_ENTRIES) { - return SYS_ERR_VNODE_SLOT_INVALID; + // Check slot is valid and mapping does not overlap leaf page table + if (slot + pte_count > VMSAv8_64_PTABLE_NUM_ENTRIES) { + if (slot >= VMSAv8_64_PTABLE_NUM_ENTRIES) { + return SYS_ERR_VNODE_SLOT_INVALID; + } + else { + return SYS_ERR_VM_MAP_SIZE; + } } if (src->type != ObjType_Frame && src->type != ObjType_DevFrame) { @@ -534,16 +540,11 @@ caps_map_l3(struct capability* dest, } // check offset within frame - if ((offset + BASE_PAGE_SIZE > get_size(src)) || + if ((offset + pte_count * BASE_PAGE_SIZE > get_size(src)) || ((offset % BASE_PAGE_SIZE) != 0)) { return SYS_ERR_FRAME_OFFSET_INVALID; } - // check mapping does not overlap leaf page table - if (slot + pte_count > VMSAv8_64_PTABLE_NUM_ENTRIES ) { - return SYS_ERR_VM_MAP_SIZE; - } - // Destination lpaddr_t dest_lpaddr = gen_phys_to_local_phys(get_address(dest)); lvaddr_t dest_lvaddr = local_phys_to_mem(dest_lpaddr); @@ -770,7 +771,7 @@ bool paging_is_region_valid(lvaddr_t buffer, size_t size, uint8_t type) return true; } -void paging_dump_tables(struct dcb *dispatcher) +void paging_dump_tables(struct dcb *dispatcher, lvaddr_t addr) { if (!local_phys_is_valid(dispatcher->vspace)) { printk(LOG_ERR, "dispatcher->vspace = 0x%"PRIxLPADDR": too high!\n" , @@ -779,6 +780,68 @@ void paging_dump_tables(struct dcb *dispatcher) } lvaddr_t l0 = local_phys_to_mem(dispatcher->vspace); + if (addr < (VMSAv8_64_PTABLE_NUM_ENTRIES * VMSAv8_64_PTABLE_NUM_ENTRIES * HUGE_PAGE_SIZE)) { + uint32_t l0_index = VMSAv8_64_L0_INDEX(addr); + uint32_t l1_index = VMSAv8_64_L1_INDEX(addr); + uint32_t l2_index = VMSAv8_64_L2_INDEX(addr); + uint32_t l3_index = VMSAv8_64_L3_INDEX(addr); + + printf("dumping table: %lx -> %u.%u.%u.%u\n", addr, l0_index, l1_index, l2_index, l3_index); + + union armv8_ttable_entry *l0_e = (union armv8_ttable_entry *) l0 + l0_index; + if (!l0_e->d.valid) { + printf("l0[% 3d] -> INVALID\n", l0_index); + return; + } + + genpaddr_t l1_gp = (genpaddr_t)(l0_e->d.base) << BASE_PAGE_BITS; + lvaddr_t l1 = local_phys_to_mem(gen_phys_to_local_phys(l1_gp)); + printf("l0[% 3d] -> l1 @ %p\n", l0_index, l1); + + union armv8_ttable_entry *l1_e = (union armv8_ttable_entry *)l1 + l1_index; + if (!l1_e->d.valid) { + printf(" l1[% 3d] -> INVALID\n", l1_index); + return; + } + + // super page mapping + if (l1_e->block_l1.mb0 == 0) { + genpaddr_t l2_gp = (genpaddr_t)(l1_e->block_l1.base) << HUGE_PAGE_BITS; + printf(" l1[% 3d] -> HUGE_PAGE @ 0x%lx\n", l1_index, l2_gp); + return; + } + + genpaddr_t l2_gp = (genpaddr_t)(l1_e->d.base) << BASE_PAGE_BITS; + lvaddr_t l2 = local_phys_to_mem(gen_phys_to_local_phys(l2_gp)); + printf(" l1[% 3d] -> l2 @ %p\n", l1_index, l2); + + union armv8_ttable_entry *l2_e = (union armv8_ttable_entry *)l2 + l2_index; + if (!l2_e->d.valid) { + printf(" l2[% 3d] -> INVALID\n", l2_index); + return; + } + + if (l2_e->block_l2.mb0 == 0) { + genpaddr_t l3_gp = (genpaddr_t)(l1_e->block_l2.base) << LARGE_PAGE_BITS; + printf(" l2[% 3d] -> LARGE_PAGE @ 0x%lx\n", l1_index, l3_gp); + return; + } + + genpaddr_t l3_gp = (genpaddr_t)(l2_e->d.base) << BASE_PAGE_BITS; + lvaddr_t l3 = local_phys_to_mem(gen_phys_to_local_phys(l3_gp)); + printf(" l2 [% 3d] -> l3 @ %p\n", l2_index, l3); + + union armv8_ttable_entry *l3_e = (union armv8_ttable_entry *)l3 + l3_index; + if (!l3_e->d.valid) { + printf(" l3[% 3d] -> INVALID\n", l3_index); + return; + } + genpaddr_t paddr = (genpaddr_t)(l3_e->page.base) << BASE_PAGE_BITS; + printf(" l3[% 3d] -> BASE_PAGE @ 0x%lx \n", l3_index, paddr); + + return; + } + for (int l0_index = 0; l0_index < VMSAv8_64_PTABLE_NUM_ENTRIES; l0_index++) { // get level0 table union armv8_ttable_entry *l0_e = (union armv8_ttable_entry *) l0 + l0_index; diff --git a/kernel/arch/armv8/plat_qemu.c b/kernel/arch/armv8/plat_qemu.c index af373d6..f97a891 100644 --- a/kernel/arch/armv8/plat_qemu.c +++ b/kernel/arch/armv8/plat_qemu.c @@ -153,6 +153,11 @@ uint32_t platform_get_timer_interrupt(void){ // TODO get this right void platform_get_dev_range(lpaddr_t* start, size_t* size){ - *start = 0; - *size = 0; + // the whole platform_get_dev_range is rather a hack. + // to make the Qemu work with the approach of imx8x. + + // see: https://github.com/qemu/qemu/blob/master/hw/arm/virt.c + *start = 0x08000000; + + *size = 0x01010000; // just include up to the uart } diff --git a/kernel/arch/armv8/syscall.c b/kernel/arch/armv8/syscall.c index 6bed912..e4495ba 100644 --- a/kernel/arch/armv8/syscall.c +++ b/kernel/arch/armv8/syscall.c @@ -851,7 +851,9 @@ static struct sysret dispatcher_dump_ptables( assert(3 == argc); struct dcb *dispatcher = to->u.dispatcher.dcb; - paging_dump_tables(dispatcher); + + struct registers_aarch64_syscall_args* sa = &context->syscall_args; + paging_dump_tables(dispatcher, sa->arg2); return SYSRET(SYS_ERR_OK); } @@ -1312,6 +1314,9 @@ void sys_syscall(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, case SYSCALL_NOP: r.error = SYS_ERR_OK; break; + case SYSCALL_REBOOT: + psci_system_reset(); + break; case SYSCALL_PRINT: if (argc == 3) { diff --git a/kernel/include/arch/armv8/startup_arch.h b/kernel/include/arch/armv8/startup_arch.h index f9c9e51..22ef6f2 100644 --- a/kernel/include/arch/armv8/startup_arch.h +++ b/kernel/include/arch/armv8/startup_arch.h @@ -28,9 +28,9 @@ VMSAv8_64_L3_BUFFERABLE | \ VMSAv8_64_L3_USR_RW) -#define INIT_L0_SIZE ARMv8_L0_ENTRIES(ARMV8_INIT_SPACE_LIMIT) -#define INIT_L1_SIZE ARMv8_L1_ENTRIES(ARMV8_INIT_SPACE_LIMIT) -#define INIT_L2_SIZE ARMv8_L2_ENTRIES(ARMV8_INIT_SPACE_LIMIT) +#define INIT_L0_SIZE (1) +#define INIT_L1_SIZE ARMv8_L0_ENTRIES(ARMV8_INIT_SPACE_LIMIT) +#define INIT_L2_SIZE ARMv8_L1_ENTRIES(ARMV8_INIT_SPACE_LIMIT) #define INIT_L3_SIZE ARMv8_L2_ENTRIES(ARMV8_INIT_SPACE_LIMIT) void create_module_caps(struct spawn_state *st); diff --git a/kernel/include/capabilities.h b/kernel/include/capabilities.h index 5326e7e..f35ae57 100644 --- a/kernel/include/capabilities.h +++ b/kernel/include/capabilities.h @@ -145,7 +145,7 @@ errval_t ptable_modify_flags(struct capability *leaf_pt, size_t offset, errval_t paging_modify_flags(struct capability *frame, uintptr_t offset, uintptr_t pages, uintptr_t kpi_paging_flags); void paging_dump_tables_around(struct dcb *dispatcher, lvaddr_t vaddr); -void paging_dump_tables(struct dcb *dispatcher); +void paging_dump_tables(struct dcb *dispatcher, lvaddr_t va); errval_t caps_retype(enum objtype type, gensize_t objsize, size_t count, struct capability *dest_cnode, cslot_t dest_slot, diff --git a/lib/aos/aos_rpc.c b/lib/aos/aos_rpc.c index 0667e0d..d5f68a6 100644 --- a/lib/aos/aos_rpc.c +++ b/lib/aos/aos_rpc.c @@ -61,7 +61,7 @@ aos_rpc_serial_putchar(struct aos_rpc *rpc, char c) { errval_t aos_rpc_process_spawn(struct aos_rpc *rpc, char *cmdline, coreid_t core, domainid_t *newpid) { - // TODO (M5): implement spawn new process rpc + // TODO: implement spawn new process rpc return SYS_ERR_OK; } @@ -69,7 +69,7 @@ aos_rpc_process_spawn(struct aos_rpc *rpc, char *cmdline, errval_t aos_rpc_process_get_name(struct aos_rpc *rpc, domainid_t pid, char **name) { - // TODO (M5): implement name lookup for process given a process id + // TODO: implement name lookup for process given a process id return SYS_ERR_OK; } @@ -77,7 +77,7 @@ aos_rpc_process_get_name(struct aos_rpc *rpc, domainid_t pid, char **name) { errval_t aos_rpc_process_get_all_pids(struct aos_rpc *rpc, domainid_t **pids, size_t *pid_count) { - // TODO (M5): implement process id discovery + // TODO: implement process id discovery return SYS_ERR_OK; } diff --git a/lib/aos/include/threads_priv.h b/lib/aos/include/threads_priv.h index eb199bf..29335fa 100644 --- a/lib/aos/include/threads_priv.h +++ b/lib/aos/include/threads_priv.h @@ -95,6 +95,9 @@ static inline bool havework_disabled(dispatcher_handle_t handle) { struct dispatcher_generic *disp = get_dispatcher_generic(handle); return disp->runq != NULL +#ifdef CONFIG_INTERCONNECT_DRIVER_LMP + || disp->lmp_send_events_list != NULL +#endif || disp->polled_channels != NULL || disp->notificators != NULL ; diff --git a/lib/aos/paging.c b/lib/aos/paging.c index 3c6831c..2985065 100644 --- a/lib/aos/paging.c +++ b/lib/aos/paging.c @@ -29,8 +29,8 @@ static struct paging_state current; * \brief Helper function that allocates a slot and * creates a aarch64 page table capability for a certain level */ -static errval_t pt_alloc(struct paging_state * st, enum objtype type, - struct capref *ret) +static errval_t pt_alloc(struct paging_state * st, enum objtype type, + struct capref *ret) { errval_t err; err = st->slot_alloc->alloc(st->slot_alloc, ret); @@ -56,7 +56,7 @@ __attribute__((unused)) static errval_t pt_alloc_l2(struct paging_state * st, st return pt_alloc(st, ObjType_VNode_AARCH64_l2, ret); } -__attribute__((unused)) static errval_t pt_alloc_l3(struct paging_state * st, struct capref *ret) +__attribute__((unused)) static errval_t pt_alloc_l3(struct paging_state * st, struct capref *ret) { return pt_alloc(st, ObjType_VNode_AARCH64_l3, ret); } @@ -67,7 +67,7 @@ __attribute__((unused)) static errval_t pt_alloc_l3(struct paging_state * st, st * TODO(M4): Improve this function. * \brief Initialize the paging_state struct for the paging * state of the calling process. - * + * * \param st The struct to be initialized, must not be NULL. * \param start_vaddr Virtual address allocation should start at * this address. @@ -90,7 +90,7 @@ errval_t paging_init_state(struct paging_state *st, lvaddr_t start_vaddr, * TODO(M4): Improve this function. * \brief Initialize the paging_state struct for the paging state * of a child process. - * + * * \param st The struct to be initialized, must not be NULL. * \param start_vaddr Virtual address allocation should start at * this address. @@ -115,7 +115,6 @@ errval_t paging_init_state_foreign(struct paging_state *st, lvaddr_t start_vaddr */ errval_t paging_init(void) { - debug_printf("paging_init\n"); // TODO (M2): Call paging_init_state for ¤t // TODO (M4): initialize self-paging handler // TIP: use thread_set_exception_handler() to setup a page fault handler @@ -194,7 +193,6 @@ errval_t paging_map_frame_attr(struct paging_state *st, void **buf, size_t bytes return LIB_ERR_NOT_IMPLEMENTED; } - /** * @brief mapps the provided frame at the supplied address in the paging state * @@ -233,8 +231,6 @@ errval_t paging_map_fixed_attr(struct paging_state *st, lvaddr_t vaddr, * @return SYS_ERR_OK on success, or error code indicating the kind of failure * * The supplied `region` must be the start of a previously mapped frame. - * - * @NOTE: Implementing this function is optional. */ errval_t paging_unmap(struct paging_state *st, const void *region) { diff --git a/lib/aos/slab.c b/lib/aos/slab.c index 7c373f3..2a2e14e 100644 --- a/lib/aos/slab.c +++ b/lib/aos/slab.c @@ -179,29 +179,36 @@ size_t slab_freecount(struct slab_allocator *slabs) */ static errval_t slab_refill_pages(struct slab_allocator *slabs, size_t bytes) { - // Hint: you can't just use malloc here... - // Hint: For M1, just use the fixed mapping funcionality, however you may want to replace - // the fixed mapping later to avoid conflicts. - return LIB_ERR_NOT_IMPLEMENTED; + errval_t err; + struct capref cap; + + err = slot_alloc(&cap); + if (err_is_fail(err)) { + return err_push(err, LIB_ERR_SLOT_ALLOC); + } + + err = slab_refill_no_pagefault(slabs, cap, bytes); + if (err_is_fail(err)) { + slot_free(cap); + } + + return err; } /** * @brief refills the slab allocator without causing a page fault * - * @param slabs the slab allocator to be refilled - * @param frame an empty slot to hold the frame capability - * @param minbytes the minimum about of bytes to refill + * @param slabs the slab allocator to be refilled + * @param frame_slot an empty capability slot for the frames + * @param minbytes the minimum number of bytes to allocate * - * @return SYS_ERR_OK on success, errval on failure - * - * Note, the frame here is an empty slot that can be used as storage for a frame. + * @return SYS_ERR_OK on success, error code on failure */ -errval_t slab_refill_no_pagefault(struct slab_allocator *slabs, struct capref frame, +errval_t slab_refill_no_pagefault(struct slab_allocator *slabs, struct capref frame_slot, size_t minbytes) { - // Refill the slot allocator without causing a page fault - // Hint: you can't just use malloc here... + // Refill the slot allocator without causing a page-fault return LIB_ERR_NOT_IMPLEMENTED; } diff --git a/lib/aos/slot_alloc/slot_alloc.c b/lib/aos/slot_alloc/slot_alloc.c index bf408f5..e0905f6 100644 --- a/lib/aos/slot_alloc/slot_alloc.c +++ b/lib/aos/slot_alloc/slot_alloc.c @@ -70,6 +70,8 @@ errval_t slot_alloc_root(struct capref *ret) } state->rootca.refilling = false; } + // If we got below two here somehow it's game over + assert(rootcn_free > 2); struct slot_allocator *ca = (struct slot_allocator*)(&state->rootca); return ca->alloc(ca, ret); } diff --git a/lib/aos/slot_alloc/twolevel_slot_alloc.c b/lib/aos/slot_alloc/twolevel_slot_alloc.c index 6f87e5d..4ac5b96 100644 --- a/lib/aos/slot_alloc/twolevel_slot_alloc.c +++ b/lib/aos/slot_alloc/twolevel_slot_alloc.c @@ -64,8 +64,10 @@ errval_t two_level_alloc(struct slot_allocator *ca, struct capref *ret) struct slot_alloc_state *state = get_slot_alloc_state(); struct slot_allocator *rca = (struct slot_allocator *)(&state->rootca); // Need to refill when one slot left, otherwise it's too late + // We can't leave it at one though either as the code in slot_alloc_root() + // assumes there are always at least 2 slots left, so refill at 2 or less size_t rootcn_free = single_slot_alloc_freecount(&state->rootca); - if (rootcn_free == 1) { + if (rootcn_free <= 2) { // resize root slot allocator (and rootcn) err = root_slot_allocator_refill(NULL, NULL); if (err_is_fail(err)) { diff --git a/lib/libc/sys/barrelfish/syscalls.c b/lib/libc/sys/barrelfish/syscalls.c index 36e0027..43a719d 100644 --- a/lib/libc/sys/barrelfish/syscalls.c +++ b/lib/libc/sys/barrelfish/syscalls.c @@ -6,16 +6,16 @@ #include #include -size_t (*_libc_terminal_read_func)(char *, size_t); -size_t (*_libc_terminal_write_func)(const char *, size_t); +extern size_t (*_libc_terminal_read_func)(char *, size_t); +extern size_t (*_libc_terminal_write_func)(const char *, size_t); void (*_libc_assert_func)(const char *, const char *, const char *, int); typedef void *(*morecore_alloc_func_t)(size_t bytes, size_t *retbytes); -morecore_alloc_func_t sys_morecore_alloc; +extern morecore_alloc_func_t sys_morecore_alloc; typedef void (*morecore_free_func_t)(void *base, size_t bytes); -morecore_free_func_t sys_morecore_free; +extern morecore_free_func_t sys_morecore_free; int system(const char *cmd) { diff --git a/lib/spawn/spawn.c b/lib/spawn/spawn.c index ad2a363..0031496 100644 --- a/lib/spawn/spawn.c +++ b/lib/spawn/spawn.c @@ -53,6 +53,7 @@ static void armv8_set_registers(void *arch_load_info, + /** * TODO(M2): Implement this function. * \brief Spawn a new dispatcher called 'argv[0]' with 'argc' arguments. diff --git a/tools/bfdocker.sh b/tools/bfdocker.sh index 4bb13e5..3f2bcfb 100755 --- a/tools/bfdocker.sh +++ b/tools/bfdocker.sh @@ -28,6 +28,15 @@ mkdir -p $BF_BUILD # run the command in the docker image with the same userid to avoid # permission problems later. -docker run -u $(id -u) -i -t \ - --mount type=bind,source=$BF_SOURCE,target=/source \ - $BF_DOCKER + +if [[ "$@" == "" ]]; then + docker run -u $(id -u) -i -t \ + --mount type=bind,source=$BF_SOURCE,target=/source \ + $BF_DOCKER "$@" +else + docker run -u $(id -u) \ + --mount type=bind,source=$BF_SOURCE,target=/source \ + $BF_DOCKER "$@" +fi + + diff --git a/tools/docker/Makefile b/tools/docker/Makefile index a3458f6..e9a83a6 100644 --- a/tools/docker/Makefile +++ b/tools/docker/Makefile @@ -18,8 +18,8 @@ build: Dockerfile install.sh entrypoint.sh docker build -t $(IMAGE_NAME):$(IMAGE_TAG) . publish: build - docker tag $(IMAGE_NAME):20.04-lts-aos $(DOCKER_HUB_USER)/$(IMAGE_NAME):$(IMAGE_TAG) - docker tag $(IMAGE_NAME):20.04-lts-aos $(DOCKER_HUB_USER)/$(IMAGE_NAME):latest + docker tag $(IMAGE_NAME):$(IMAGE_TAG) $(DOCKER_HUB_USER)/$(IMAGE_NAME):$(IMAGE_TAG) + docker tag $(IMAGE_NAME):$(IMAGE_TAG) $(DOCKER_HUB_USER)/$(IMAGE_NAME):latest docker push $(DOCKER_HUB_USER)/$(IMAGE_NAME):$(IMAGE_TAG) test: diff --git a/tools/docker/entrypoint.sh b/tools/docker/entrypoint.sh index 55d2329..950034f 100755 --- a/tools/docker/entrypoint.sh +++ b/tools/docker/entrypoint.sh @@ -1,11 +1,16 @@ #!/bin/bash -# Copyright (c) 2021 The University of British Columbia. +# Copyright (c) 2021,2022 The University of British Columbia. # All rights reserved. # # This file is distributed under the terms in the attached LICENSE file. -cd /source +# create the build directory if it doesn't exist +mkdir -p /source/build + +# cd into the build directory +cd /source/build + if [ "$1" == "" ]; then exec "/bin/bash" diff --git a/tools/docker/install.sh b/tools/docker/install.sh index 38ff77e..4a62417 100755 --- a/tools/docker/install.sh +++ b/tools/docker/install.sh @@ -14,7 +14,7 @@ DEBIAN_FRONTEND=noninteractive apt-get install -y \ python3 parted wget mtools # install barrelfish dependencies -apt-get update +apt-get update && apt-get upgrade DEBIAN_FRONTEND=noninteractive apt-get install -y \ build-essential bison flex ghc libghc-src-exts-dev \ libghc-ghc-paths-dev libghc-parsec3-dev libghc-random-dev\ @@ -27,6 +27,10 @@ DEBIAN_FRONTEND=noninteractive apt-get install -y \ cabal v1-update cabal v1-install --global bytestring-trie +# install the autograder dependencies +DEBIAN_FRONTEND=noninteractive apt-get install -y \ + python3 python3-pexpect python3-plumbum + # get the uuu tool wget -P /bin https://github.com/NXPmicro/mfgtools/releases/download/uuu_1.4.165/uuu chmod 755 /bin/uuu @@ -39,4 +43,4 @@ chmod 755 /source apt-get clean && apt-get autoclean && apt-get autoremove -y # make sure it's executable -chmod 755 /entrypoint.sh \ No newline at end of file +chmod 755 /entrypoint.sh diff --git a/usr/drivers/pl011/Hakefile b/usr/drivers/pl011/Hakefile new file mode 100644 index 0000000..d892caa --- /dev/null +++ b/usr/drivers/pl011/Hakefile @@ -0,0 +1,19 @@ +-------------------------------------------------------------------------- +-- Copyright (c) 2020, ETH Zurich. +-- All rights reserved. +-- +-- This file is distributed under the terms in the attached LICENSE file. +-- If you do not find this file, copies can be found by writing to: +-- ETH Zurich D-INFK, CAB F.78, Universitaetstr 6, CH-8092 Zurich. +-- +-- Hakefile for lpuart +-- +-------------------------------------------------------------------------- + +[ + build library { target = "pl011", + cFiles = ["main.c"], + mackerelDevices = [ "pl011_uart" ], + architectures = ["armv8"] + } +] diff --git a/usr/drivers/pl011/main.c b/usr/drivers/pl011/main.c new file mode 100644 index 0000000..6e90353 --- /dev/null +++ b/usr/drivers/pl011/main.c @@ -0,0 +1,132 @@ +/** + * \file + * \brief Serial port driver. + */ + +/* + * Copyright (c) 2020, ETH Zurich. + * Copyright (c) 2022, The University of British Columbia. + * All rights reserved. + * + * This file is distributed under the terms in the attached LICENSE file. + * If you do not find this file, copies can be found by writing to: + * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich, + * Attn: Systems Group. + */ + +#include +#include + +struct pl011_s { + struct event_closure int_handler; + struct pl011_uart_t dev; +}; + + +static void hw_init(struct pl011_s *s) +{ + pl011_uart_t *u = &s->dev; + + /* Mask all interrupts: set all bits to zero. */ + pl011_uart_IMSC_rawwr(u, 0); + + /* Disable the UART before reconfiguring it. */ + pl011_uart_CR_uarten_wrf(u, 0); + + // Configure port to 38400 baud, 8 data, no parity, 1 stop (8-N-1) + // + // (This is a mild scam as system is running in QEMU) + // + // Note baud rate changes not committed in h/w until lcr_h + // written. + pl011_uart_IBRD_divint_wrf(u, 0xc); // Assuming UARTCLK is 7.3728MHz + pl011_uart_FBRD_divfrac_wrf(u, 0); + + /* Configure the line control register. */ + pl011_uart_LCR_H_t lcr = (pl011_uart_LCR_H_t)0; + /* Disable FIFOs. There's no way to get an interrupt when a single + * character arrives with FIFOs, so it's useless as a console. */ + lcr = pl011_uart_LCR_H_fen_insert(lcr, 0); + /* Eight data bits. */ + lcr = pl011_uart_LCR_H_wlen_insert(lcr, pl011_uart_bits8); + /* No parity. */ + lcr = pl011_uart_LCR_H_pen_insert(lcr, 0); + /* One stop bit. */ + lcr = pl011_uart_LCR_H_stp2_insert(lcr, 0); + pl011_uart_LCR_H_wr(u, lcr); + + /* Configure the main control register. */ + pl011_uart_CR_t cr = (pl011_uart_CR_t)0; + /* No flow control. */ + cr = pl011_uart_CR_ctsen_insert(cr, 0); + cr = pl011_uart_CR_rtsen_insert(cr, 0); + /* Enable transmit and receive. */ + cr = pl011_uart_CR_txe_insert(cr, 1); + cr = pl011_uart_CR_rxe_insert(cr, 1); + /* Enable UART. */ + cr = pl011_uart_CR_uarten_insert(cr, 1); + pl011_uart_CR_wr(u, cr); +} + +errval_t pl011_init(struct pl011_s **s_ret, void *base) +{ + PL011_DEBUG("Driver init\n"); + + assert(s_ret != NULL); + assert(base != NULL); + + struct pl011_s *s = calloc(1, sizeof(struct pl011_s)); + if (s == NULL) { + return LIB_ERR_MALLOC_FAIL; + } + + *s_ret = s; + + pl011_uart_initialize(&s->dev, base); + + PL011_DEBUG("Initializing hw..."); + hw_init(s); + return SYS_ERR_OK; +} + +errval_t pl011_getchar(struct pl011_s *s, char *c) +{ + pl011_uart_t *u = &s->dev; + assert(u->base != 0); + + /* Acknowledge any interrupt. */ + pl011_uart_ICR_rxic_wrf(u, 1); + + /* check if there is data */ + if (pl011_uart_FR_rxfe_rdf(u) == 1) { + return LPUART_ERR_NO_DATA; + } + + /* store the return character */ + *c = (char)pl011_uart_DR_data_rdf(u); + + return SYS_ERR_OK; +} + +errval_t pl011_enable_interrupt(struct pl011_s *s) +{ + pl011_uart_t *u = &s->dev; + assert(u->base != 0); + + // Receive interrupt enable + pl011_uart_ICR_rxic_wrf(u, 1); + pl011_uart_IMSC_rxim_wrf(u, 1); + return SYS_ERR_OK; +} + +errval_t pl011_putchar(struct pl011_s *s, char c) +{ + pl011_uart_t *u = &s->dev; + assert(u->base != 0); + + while (pl011_uart_FR_txff_rdf(u) == 1) + ; + pl011_uart_DR_rawwr(u, c); + + return SYS_ERR_OK; +} diff --git a/usr/init/main.c b/usr/init/main.c index 286bbc3..5957c32 100644 --- a/usr/init/main.c +++ b/usr/init/main.c @@ -31,6 +31,7 @@ struct bootinfo *bi; coreid_t my_core_id; +struct platform_info platform_info; @@ -56,6 +57,7 @@ bsp_main(int argc, char *argv[]) { // Grading grading_test_early(); + // TODO: Spawn system processes, boot second core etc. here // Grading @@ -85,23 +87,45 @@ app_main(int argc, char *argv[]) { return LIB_ERR_NOT_IMPLEMENTED; } - - int main(int argc, char *argv[]) { errval_t err; + /* obtain the core information from the kernel*/ + err = invoke_kernel_get_core_id(cap_kernel, &my_core_id); + if (err_is_fail(err)) { + USER_PANIC_ERR(err, "failed to obtain the core id from the kernel\n"); + } /* Set the core id in the disp_priv struct */ - err = invoke_kernel_get_core_id(cap_kernel, &my_core_id); - assert(err_is_ok(err)); disp_set_core_id(my_core_id); - debug_printf("init: on core %" PRIuCOREID ", invoked as:", my_core_id); + /* obtain the platform information */ + err = invoke_kernel_get_platform_info(cap_kernel, &platform_info); + if (err_is_fail(err)) { + USER_PANIC_ERR(err, "failed to obtain the platform info from the kernel\n"); + } + + char *platform; + switch (platform_info.platform) { + case PI_PLATFORM_QEMU: + platform = "QEMU"; + break; + case PI_PLATFORM_IMX8X: + platform = "IMX8X"; + break; + default: + platform = "UNKNOWN"; + } + + debug_printf("init domain starting on core %" PRIuCOREID " (%s), invoked as:", my_core_id, platform); for (int i = 0; i < argc; i++) { printf(" %s", argv[i]); } printf("\n"); + + + fflush(stdout);