diff --git a/projects/tutorial-commons/utils.h b/projects/tutorial-commons/utils.h new file mode 100644 index 0000000..058a2b5 --- /dev/null +++ b/projects/tutorial-commons/utils.h @@ -0,0 +1,291 @@ +#define APP0_PID 0 +#define APP1_PID 1 + +// See plat_conf.h +#define BOOT_PMP 0 +#define RAM_MEM 1 +#define UART_MEM 2 +#define TIME_MEM 3 +#define HART0_TIME 4 +#define HART1_TIME 5 +#define HART2_TIME 6 +#define HART3_TIME 7 +#define MONITOR 8 +#define CHANNEL 9 + +// normal caps +#define UART_CAP 10 +#define UART_PMP 1 +#define BUFFER_PMP 2 + +// CAPS for second process +#define APP_1_CAP_PMP_MEM 0 +#define APP_1_CAP_PMP_UART 10 +#define APP_1_TIME 1 +#define APP_1_CAP_SOCKET 3 + +#define APP_1_PMP_SLOT_MEM 0 +#define APP_1_PMP_SLOT_UART 1 +#define APP_1_PMP_SLOT_BUFFER 2 + +// CAPS for second process +#define FREE_CAP_BEGIN 12 +#define FREE_CAP_END 20 + +// Other constants +#define APP_1_BASE_ADDR 0x80020000 +#define APP_1_SIZE 0x10000 +#define SHARED_BUFFER_BASE (APP_1_BASE_ADDR+APP_1_SIZE) +#define SHARED_BUFFER_SIZE 0x10000 + +void setup_uart() +{ + uint64_t uart_addr = s3k_napot_encode(UART0_BASE_ADDR, 0x8); + // Derive a PMP capability for accessing UART + s3k_cap_derive(UART_MEM, UART_CAP, s3k_mk_pmp(uart_addr, S3K_MEM_RW)); + // Load the derive PMP capability to PMP configuration + s3k_pmp_load(UART_CAP, UART_PMP); + // Synchronize PMP unit (hardware) with PMP configuration + // false => not full synchronization. + s3k_sync_mem(); +} + +void default_trap_handler(void) __attribute__((interrupt("machine"))); +void default_trap_handler(void) { + // We enter here on illegal instructions, for example writing to + // protected area (UART). + + // On an exception we do + // - tf.epc = tf.pc (save program counter) + // - tf.pc = tf.tpc (load trap handler address) + // - tf.esp = tf.sp (save stack pointer) + // - tf.sp = tf.tsp (load trap stack pointer) + // - tf.ecause = mcause (see RISC-V privileged spec) + // - tf.eval = mval (see RISC-V privileged spec) + // tf is the trap frame, all registers of our process + uint64_t epc = s3k_reg_read(S3K_REG_EPC); + uint64_t esp = s3k_reg_read(S3K_REG_ESP); + uint64_t ecause = s3k_reg_read(S3K_REG_ECAUSE); + uint64_t eval = s3k_reg_read(S3K_REG_EVAL); + + alt_printf( + "error info:\n- epc: 0x%x\n- esp: 0x%x\n- ecause: 0x%x\n- eval: 0x%x\n", + epc, esp, ecause, eval); + alt_printf("restoring pc and sp\n\n"); + // __attribute__((interrupt("machine"))) replaces `ret` with an `mret`. + // When mret is executed in user-mode, the kernel catches it setting the + // following: + // - tf.pc = tf.epc + // - tf.sp = tf.esp + // Restoring pc and sp to the previous values, unless epc and esp was + // overwritten. +} + + +void setup_trap(void (*trap_handler)(void), void * trap_stack_base, uint64_t trap_stack_size) +{ + // Sets the trap handler + s3k_reg_write(S3K_REG_TPC, (uint64_t)trap_handler); + // Set the trap stack + s3k_reg_write(S3K_REG_TSP, ((uint64_t)trap_stack_base) + trap_stack_size); +} + + +#define TAG_BLOCK_TO_ADDR(tag, block) ( \ + (((uint64_t) tag) << S3K_MAX_BLOCK_SIZE) + \ + (((uint64_t) block) << S3K_MIN_BLOCK_SIZE) \ + ) + +void s3k_print_cap(s3k_cap_t *cap) { + if (!cap) + alt_printf("Capability is NULL\n"); + switch ((*cap).type) { + case S3K_CAPTY_NONE: + alt_printf("No Capability\n"); + break; + case S3K_CAPTY_TIME: + alt_printf("Time hart:%X bgn:%X mrk:%X end:%Z\n", + (*cap).time.hart, (*cap).time.bgn, (*cap).time.mrk, (*cap).time.end); + break; + case S3K_CAPTY_MEMORY: + alt_printf("Memory rwx:%X lock:%X bgn:%X mrk:%X end:%X\n", + (*cap).mem.rwx, (*cap).mem.lck, + TAG_BLOCK_TO_ADDR((*cap).mem.tag, (*cap).mem.bgn), + TAG_BLOCK_TO_ADDR((*cap).mem.tag, (*cap).mem.mrk), + TAG_BLOCK_TO_ADDR((*cap).mem.tag, (*cap).mem.end) + ); + break; + case S3K_CAPTY_PMP: + alt_printf("PMP rwx:%X used:%X index:%X address:%Z\n", + (*cap).pmp.rwx, (*cap).pmp.used, (*cap).pmp.slot, (*cap).pmp.addr); + break; + case S3K_CAPTY_MONITOR: + alt_printf("Monitor bgn:%X mrk:%X end:%X\n", + (*cap).mon.bgn, (*cap).mon.mrk, (*cap).mon.end); + break; + case S3K_CAPTY_CHANNEL: + alt_printf("Channel bgn:%X mrk:%X end:%X\n", + (*cap).chan.bgn, (*cap).chan.mrk, (*cap).chan.end); + break; + case S3K_CAPTY_SOCKET: + alt_printf("Socket mode:%X perm:%X channel:%X tag:%X\n", + (*cap).sock.mode, (*cap).sock.perm, (*cap).sock.chan, (*cap).sock.tag); + break; + } +} + +void debug_capability_from_idx(uint32_t cap_idx) { + s3k_cap_t cap; + while (s3k_cap_read(cap_idx, &cap)); + s3k_print_cap(&cap); +} + +uint32_t log_sys(char * msg, uint32_t res) { + alt_printf("%s %X\n", msg, res); +} + +uint32_t find_free_cap() { + s3k_cap_t cap; + for (uint32_t i = FREE_CAP_BEGIN; i <= FREE_CAP_END; i++) { + if (s3k_cap_read(i, &cap)) + return i; + } + return 0; +} + + +void setup_app_1() +{ + uint64_t uart_addr = s3k_napot_encode(UART0_BASE_ADDR, 0x8); + uint64_t app1_addr = s3k_napot_encode(APP_1_BASE_ADDR, APP_1_SIZE); + + // Derive a PMP capability for app1 main memory + uint32_t free_cap_mem_idx = find_free_cap(); + log_sys("1", + s3k_cap_derive(RAM_MEM, free_cap_mem_idx, s3k_mk_memory(APP_1_BASE_ADDR, APP_1_BASE_ADDR + APP_1_SIZE, S3K_MEM_RWX))); + uint32_t free_cap_idx = find_free_cap(); + log_sys("1", + s3k_cap_derive(free_cap_mem_idx, free_cap_idx, s3k_mk_pmp(app1_addr, S3K_MEM_RWX))); + log_sys("2", + s3k_mon_cap_move(MONITOR, APP0_PID, free_cap_idx, APP1_PID, APP_1_CAP_PMP_MEM)); + log_sys("3", + s3k_mon_pmp_load(MONITOR, APP1_PID, APP_1_CAP_PMP_MEM, APP_1_PMP_SLOT_MEM)); + + // Derive a PMP capability for uart + log_sys("4", + s3k_cap_derive(UART_MEM, free_cap_idx, s3k_mk_pmp(uart_addr, S3K_MEM_RW))); + log_sys("5", + s3k_mon_cap_move(MONITOR, APP0_PID, free_cap_idx, APP1_PID, APP_1_CAP_PMP_UART)); + log_sys("6", + s3k_mon_pmp_load(MONITOR, APP1_PID, APP_1_CAP_PMP_UART, APP_1_PMP_SLOT_UART)); + + // Write start PC of app1 to PC + log_sys("7", + s3k_mon_reg_write(MONITOR, APP1_PID, S3K_REG_PC, APP_1_BASE_ADDR)); + + s3k_sync_mem(); +} + +#define NO_APP_1 0 +#define NO_APP_0 1 +#define ROUND_ROBIN 2 +#define PARALLEL 3 + +void setup_scheduling(uint32_t scheduling_type) { + // Disable the other two cores + s3k_cap_delete(HART2_TIME); + s3k_cap_delete(HART3_TIME); + + if (scheduling_type == NO_APP_1) { + s3k_cap_delete(HART1_TIME); + } + else if (scheduling_type == NO_APP_0) { + // Notice that we must be able to finish our job to setup APP 1 + s3k_cap_delete(HART1_TIME); + uint32_t cap_idx = find_free_cap(); + s3k_cap_derive(HART0_TIME, cap_idx, s3k_mk_time(S3K_MIN_HART, 0, S3K_SLOT_CNT / 2)); + s3k_mon_cap_move(MONITOR, APP0_PID, HART0_TIME, APP1_PID, APP_1_TIME); + } + else if (scheduling_type == ROUND_ROBIN) { + s3k_cap_delete(HART1_TIME); + uint32_t cap_idx = find_free_cap(); + log_sys("Time derivation", + s3k_cap_derive(HART0_TIME, cap_idx, + s3k_mk_time(S3K_MIN_HART, 0, S3K_SLOT_CNT / 2))); + log_sys("Time delegation", + s3k_mon_cap_move(MONITOR, APP0_PID, cap_idx, APP1_PID, APP_1_TIME)); + } + else if (scheduling_type == PARALLEL) { + s3k_mon_cap_move(MONITOR, APP0_PID, HART1_TIME, APP1_PID, APP_1_TIME); + } + s3k_sync(); +} + + +uint32_t setup_socket(bool server, bool yield, bool capability) +{ + uint64_t socket_server = find_free_cap(); + uint64_t yield_mode = (yield)?S3K_IPC_YIELD:S3K_IPC_NOYIELD; + + s3k_ipc_perm_t permission = S3K_IPC_SDATA | S3K_IPC_CDATA; + if (capability) + permission |= S3K_IPC_CCAP | S3K_IPC_SCAP; + + s3k_cap_derive(CHANNEL, socket_server, + s3k_mk_socket(0, yield_mode, permission, 0)); + uint64_t socket_client = find_free_cap(); + s3k_cap_derive(socket_server, socket_client, + s3k_mk_socket(0, yield_mode, permission, 1)); + if (server) { + s3k_mon_cap_move(MONITOR, APP0_PID, socket_client, APP1_PID, APP_1_CAP_SOCKET); + return socket_server; + } + s3k_mon_cap_move(MONITOR, APP0_PID, socket_server, APP1_PID, APP_1_CAP_SOCKET); + return socket_client; +} + + +void server_main_loop(s3k_msg_t (* handler) (s3k_reply_t, uint32_t), bool capability) { + s3k_msg_t msg; + s3k_reply_t reply; + while (true) + { + do { + if (capability) { + msg.cap_idx = find_free_cap(); + msg.send_cap = 1; + } + alt_puts("APP1: ready to receive\n"); + reply = s3k_sock_sendrecv(APP_1_CAP_SOCKET, &msg); + if (reply.err == S3K_ERR_TIMEOUT) + alt_puts("APP1: timeout\n"); + } while (reply.err); + msg = (*handler)(reply, msg.cap_idx); + } +} + +void wait_for_app1_blocked() { + s3k_state_t state; + while (true) { + alt_puts("APP0: waiting loop\n"); + if (s3k_mon_state_get(MONITOR, APP1_PID, &state)) + continue; + if (state & S3K_PSF_BLOCKED) + break; + alt_puts("APP0: waiting 1\n"); + s3k_mon_yield(MONITOR, APP1_PID); + alt_puts("APP0: waiting 2\n"); + } +} + +s3k_reply_t send_receive_forever(uint64_t socket, s3k_msg_t msg) { + s3k_reply_t reply; + do { + reply = s3k_sock_sendrecv(socket, &msg); + while (reply.err == S3K_ERR_TIMEOUT) { + alt_puts("APP0: timeout"); + reply = s3k_sock_recv(socket, msg.cap_idx); + } + } while (reply.err); + return reply; +} diff --git a/projects/tutorial.01.hello-world/app0/main.c b/projects/tutorial.01.hello-world/app0/main.c index 97d1b41..a4095cc 100644 --- a/projects/tutorial.01.hello-world/app0/main.c +++ b/projects/tutorial.01.hello-world/app0/main.c @@ -1,39 +1,13 @@ #include "altc/altio.h" #include "s3k/s3k.h" -#define APP0_PID 0 -#define APP1_PID 1 - -// See plat_conf.h -#define BOOT_PMP 0 -#define RAM_MEM 1 -#define UART_MEM 2 -#define TIME_MEM 3 -#define HART0_TIME 4 -#define HART1_TIME 5 -#define HART2_TIME 6 -#define HART3_TIME 7 -#define MONITOR 8 -#define CHANNEL 9 - -void setup_uart(uint64_t uart_idx) -{ - uint64_t uart_addr = s3k_napot_encode(UART0_BASE_ADDR, 0x8); - // Derive a PMP capability for accessing UART - s3k_cap_derive(UART_MEM, uart_idx, s3k_mk_pmp(uart_addr, S3K_MEM_RW)); - // Load the derive PMP capability to PMP configuration - s3k_pmp_load(uart_idx, 1); - // Synchronize PMP unit (hardware) with PMP configuration - // false => not full synchronization. - s3k_sync_mem(); -} +#include "../../tutorial-commons/utils.h" int main(void) { // Setup UART access - setup_uart(10); + setup_uart(); // Write hello world. - alt_puts("Hello, world"); - + alt_printf("Hello, world\n"); } diff --git a/projects/tutorial.02.trap-handler/app0/main.c b/projects/tutorial.02.trap-handler/app0/main.c index ab7ee6f..86918a7 100644 --- a/projects/tutorial.02.trap-handler/app0/main.c +++ b/projects/tutorial.02.trap-handler/app0/main.c @@ -1,85 +1,24 @@ #include "altc/altio.h" #include "s3k/s3k.h" -#define APP0_PID 0 -#define APP1_PID 1 +#include "../../tutorial-commons/utils.h" -// See plat_conf.h -#define BOOT_PMP 0 -#define RAM_MEM 1 -#define UART_MEM 2 -#define TIME_MEM 3 -#define HART0_TIME 4 -#define HART1_TIME 5 -#define HART2_TIME 6 -#define HART3_TIME 7 -#define MONITOR 8 -#define CHANNEL 9 - -void setup_uart(s3k_cidx_t uart_idx); char trap_stack[1024]; void trap_handler(void) __attribute__((interrupt("machine"))); -void setup_trap(void) -{ - // Sets the trap handler - s3k_reg_write(S3K_REG_TPC, (uint64_t)trap_handler); - // Set the trap stack - s3k_reg_write(S3K_REG_TSP, (uint64_t)trap_stack + 1024); -} - void trap_handler(void) { - // We enter here on illegal instructions, for example writing to - // protected area (UART). - - // On an exception we do - // - tf.epc = tf.pc (save program counter) - // - tf.pc = tf.tpc (load trap handler address) - // - tf.esp = tf.sp (save stack pointer) - // - tf.sp = tf.tsp (load trap stack pointer) - // - tf.ecause = mcause (see RISC-V privileged spec) - // - tf.eval = mval (see RISC-V privileged spec) - // tf is the trap frame, all registers of our process - uint64_t epc = s3k_reg_read(S3K_REG_EPC); - uint64_t esp = s3k_reg_read(S3K_REG_ESP); - uint64_t ecause = s3k_reg_read(S3K_REG_ECAUSE); - uint64_t eval = s3k_reg_read(S3K_REG_EVAL); - - setup_uart(16); + setup_uart(); alt_puts("uart is now setup!"); - alt_printf( - "error info:\n- epc: 0x%x\n- esp: 0x%x\n- ecause: 0x%x\n- eval: 0x%x\n", - epc, esp, ecause, eval); - alt_printf("restoring pc and sp\n\n"); - // __attribute__((interrupt("machine"))) replaces `ret` with an `mret`. - // When mret is executed in user-mode, the kernel catches it setting the - // following: - // - tf.pc = tf.epc - // - tf.sp = tf.esp - // Restoring pc and sp to the previous values, unless epc and esp was - // overwritten. -} - -void setup_uart(s3k_cidx_t uart_idx) -{ - uint64_t uart_addr = s3k_napot_encode(UART0_BASE_ADDR, 0x8); - // Derive a PMP capability for accessing UART - s3k_cap_derive(UART_MEM, uart_idx, s3k_mk_pmp(uart_addr, S3K_MEM_RW)); - // Load the derive PMP capability to PMP configuration - s3k_pmp_load(uart_idx, 1); - // Synchronize PMP unit (hardware) with PMP configuration - // false => not full synchronization. - s3k_sync_mem(); + default_trap_handler(); } int main(void) { // Setup trap handler - setup_trap(); + setup_trap(trap_handler, trap_stack, 1024); // Write hello world. - alt_puts("Hello, world"); - + alt_printf("Hello, world\n"); } diff --git a/projects/tutorial.03.mem-cap/app0/main.c b/projects/tutorial.03.mem-cap/app0/main.c index 58088cd..c9c6193 100644 --- a/projects/tutorial.03.mem-cap/app0/main.c +++ b/projects/tutorial.03.mem-cap/app0/main.c @@ -1,112 +1,48 @@ #include "altc/altio.h" #include "s3k/s3k.h" -#define APP0_PID 0 -#define APP1_PID 1 +#include "../../tutorial-commons/utils.h" -// See plat_conf.h -#define BOOT_PMP 0 -#define RAM_MEM 1 -#define UART_MEM 2 -#define TIME_MEM 3 -#define HART0_TIME 4 -#define HART1_TIME 5 -#define HART2_TIME 6 -#define HART3_TIME 7 -#define MONITOR 8 -#define CHANNEL 9 +char trap_stack[1024]; -/* initial configuration for memory is in */ -/* /plat/virt/config.h */ +int main(void) +{ + // Setup UART access + setup_uart(); + // Setup trap handler + setup_trap(default_trap_handler, trap_stack, 1024); -#define TAG_BLOCK_TO_ADDR(tag, block) ( \ - (((uint64_t) tag) << S3K_MAX_BLOCK_SIZE) + \ - (((uint64_t) block) << S3K_MIN_BLOCK_SIZE) \ - ) -void setup_uart(uint64_t uart_idx) -{ - uint64_t uart_addr = s3k_napot_encode(UART0_BASE_ADDR, 0x8); - // Derive a PMP capability for accessing UART - s3k_cap_derive(UART_MEM, uart_idx, s3k_mk_pmp(uart_addr, S3K_MEM_RW)); - // Load the derive PMP capability to PMP configuration - s3k_pmp_load(uart_idx, 1); - // Synchronize PMP unit (hardware) with PMP configuration - // false => not full synchronization. - s3k_sync_mem(); -} + alt_printf("Hello, world\n"); + debug_capability_from_idx(RAM_MEM); -void s3k_print_cap(s3k_cap_t *cap) { - if (!cap) - alt_printf("Capability is NULL\n"); - switch ((*cap).type) { - case S3K_CAPTY_NONE: - alt_printf("No Capability\n"); - break; - case S3K_CAPTY_TIME: - alt_printf("Time hart:%X bgn:%X mrk:%X end:%Z\n", - (*cap).time.hart, (*cap).time.bgn, (*cap).time.mrk, (*cap).time.end); - break; - case S3K_CAPTY_MEMORY: - alt_printf("Memory rwx:%X lock:%X bgn:%X mrk:%X end:%X\n", - (*cap).mem.rwx, (*cap).mem.lck, - TAG_BLOCK_TO_ADDR((*cap).mem.tag, (*cap).mem.bgn), - TAG_BLOCK_TO_ADDR((*cap).mem.tag, (*cap).mem.mrk), - TAG_BLOCK_TO_ADDR((*cap).mem.tag, (*cap).mem.end) - ); - break; - case S3K_CAPTY_PMP: - alt_printf("PMP rwx:%X used:%X index:%X address:%Z\n", - (*cap).pmp.rwx, (*cap).pmp.used, (*cap).pmp.slot, (*cap).pmp.addr); - break; - case S3K_CAPTY_MONITOR: - alt_printf("Monitor bgn:%X mrk:%X end:%X\n", - (*cap).mon.bgn, (*cap).mon.mrk, (*cap).mon.end); - break; - case S3K_CAPTY_CHANNEL: - alt_printf("Channel bgn:%X mrk:%X end:%X\n", - (*cap).chan.bgn, (*cap).chan.mrk, (*cap).chan.end); - break; - case S3K_CAPTY_SOCKET: - alt_printf("Socket mode:%X perm:%X channel:%X tag:%X\n", - (*cap).sock.mode, (*cap).sock.perm, (*cap).sock.chan, (*cap).sock.tag); - break; - } -} + uint32_t free_cap = find_free_cap(); + alt_printf("Using free cap %d\n", free_cap); -int main(void) -{ - // Setup UART access - setup_uart(10); + log_sys("cap derivation result", s3k_cap_derive(RAM_MEM, free_cap, + s3k_mk_memory(APP_1_BASE_ADDR, APP_1_BASE_ADDR + APP_1_SIZE, S3K_MEM_RWX))); + log_sys("cap derivation result", s3k_cap_derive(RAM_MEM, find_free_cap(), + s3k_mk_memory(APP_1_BASE_ADDR, APP_1_BASE_ADDR + APP_1_SIZE, S3K_MEM_RWX))); - // Write hello world. - alt_puts("Hello, world"); + debug_capability_from_idx(RAM_MEM); + debug_capability_from_idx(free_cap); s3k_cap_t cap; - while (s3k_cap_read(RAM_MEM, &cap)); - s3k_print_cap(&cap); - alt_printf("cap derivation result %X\n", - s3k_cap_derive(1, 17, s3k_mk_memory(0x80020000, 0x80030000, S3K_MEM_RWX))); - alt_printf("cap derivation result %X\n", - s3k_cap_derive(1, 18, s3k_mk_memory(0x80020000, 0x80030000, S3K_MEM_RWX))); - while (s3k_cap_read(RAM_MEM, &cap)); - s3k_print_cap(&cap); - while (s3k_cap_read(17, &cap)); - s3k_print_cap(&cap); + uint32_t free_cap_pmp = find_free_cap(); + uint64_t pmp_addr = s3k_napot_encode(APP_1_BASE_ADDR, APP_1_SIZE); + log_sys("cap derivation result", + s3k_cap_derive(free_cap, free_cap_pmp, s3k_mk_pmp(pmp_addr, S3K_MEM_RW))); + + debug_capability_from_idx(free_cap); + debug_capability_from_idx(free_cap_pmp); - uint64_t pmp_addr = s3k_napot_encode(0x80020000, 0x10000); - alt_printf("cap derivation result %X\n", - s3k_cap_derive(17, 18, s3k_mk_pmp(pmp_addr, S3K_MEM_RW))); - while (s3k_cap_read(17, &cap)); - s3k_print_cap(&cap); + log_sys("Loading the PMP", s3k_pmp_load(free_cap_pmp, 2)); - alt_printf("Loading the PMP\n"); - while (s3k_pmp_load(18, 2)); alt_printf("Sync status\n"); s3k_sync_mem(); alt_printf("Accessing the new memory\n"); - *((uint64_t *)(0x80020000)) = 10; - alt_printf("Successfully wrote in random memory 0x%X\n", *((uint64_t *)(0x80020000))); + *((uint64_t *)(APP_1_BASE_ADDR)) = 10; + alt_printf("Successfully wrote in random memory 0x%X\n", *((uint64_t *)(APP_1_BASE_ADDR))); } diff --git a/projects/tutorial.04.timing-cap/app0/main.c b/projects/tutorial.04.timing-cap/app0/main.c index 823a5c9..5a83621 100644 --- a/projects/tutorial.04.timing-cap/app0/main.c +++ b/projects/tutorial.04.timing-cap/app0/main.c @@ -1,132 +1,26 @@ #include "altc/altio.h" #include "s3k/s3k.h" -#define APP0_PID 0 -#define APP1_PID 1 +#include "../../tutorial-commons/utils.h" -// See plat_conf.h -#define BOOT_PMP 0 -#define RAM_MEM 1 -#define UART_MEM 2 -#define TIME_MEM 3 -#define HART0_TIME 4 -#define HART1_TIME 5 -#define HART2_TIME 6 -#define HART3_TIME 7 -#define MONITOR 8 -#define CHANNEL 9 -#define CAP_UART 10 -#define CAP_TMP 11 - -#define APP_1_BASE_ADDR 0x80020000 -#define APP_1_SIZE 0x10000 -#define APP_1_PMP_MEM 0 -#define APP_1_PMP_UART 1 -#define APP_1_TIME 2 - -#define NO_APP_1 0 -#define NO_APP_0 1 -#define ROUND_ROBIN 2 -#define PARALLEL 3 - -#define SCHEDULING NO_APP_0 - -void setup_uart(uint64_t uart_idx) -{ - uint64_t uart_addr = s3k_napot_encode(UART0_BASE_ADDR, 0x8); - // Derive a PMP capability for accessing UART - s3k_cap_derive(UART_MEM, uart_idx, s3k_mk_pmp(uart_addr, S3K_MEM_RW)); - // Load the derive PMP capability to PMP configuration - s3k_pmp_load(uart_idx, 1); - // Synchronize PMP unit (hardware) with PMP configuration - // false => not full synchronization. - s3k_sync_mem(); -} - -void setup_app_1(uint64_t tmp) -{ - uint64_t uart_addr = s3k_napot_encode(UART0_BASE_ADDR, 0x8); - uint64_t app1_addr = s3k_napot_encode(APP_1_BASE_ADDR, APP_1_SIZE); - - // Derive a PMP capability for app1 main memory - alt_printf("1 %X\n", - s3k_cap_derive(RAM_MEM, tmp, s3k_mk_pmp(app1_addr, S3K_MEM_RWX)) - ); - alt_printf("2 %X\n", - s3k_mon_cap_move(MONITOR, APP0_PID, tmp, APP1_PID, APP_1_PMP_MEM) - ); - alt_printf("3 %X\n", - s3k_mon_pmp_load(MONITOR, APP1_PID, APP_1_PMP_MEM, 0) - ); - - // Derive a PMP capability for uart - alt_printf("4 %X\n", - s3k_cap_derive(UART_MEM, tmp, s3k_mk_pmp(uart_addr, S3K_MEM_RW)) - ); - - alt_printf("5 %X\n", - s3k_mon_cap_move(MONITOR, APP0_PID, tmp, APP1_PID, APP_1_PMP_UART) - ); - alt_printf("6 %X\n", - s3k_mon_pmp_load(MONITOR, APP1_PID, APP_1_PMP_UART, 1) - ); - - // Write start PC of app1 to PC - alt_printf("9 %X\n", - s3k_mon_reg_write(MONITOR, APP1_PID, S3K_REG_PC, APP_1_BASE_ADDR) - ); - - s3k_sync_mem(); -} - -void setup_scheduling(uint64_t tmp_cap_idx) { - // Disable the other two cores - s3k_cap_delete(HART2_TIME); - s3k_cap_delete(HART3_TIME); - - if (SCHEDULING == NO_APP_1) { - s3k_cap_delete(HART1_TIME); - } - else if (SCHEDULING == NO_APP_0) { - // Notice that we must be able to finish our job to setup APP 1 - s3k_cap_delete(HART1_TIME); - s3k_cap_derive(HART0_TIME, tmp_cap_idx, s3k_mk_time(S3K_MIN_HART, 0, S3K_SLOT_CNT / 2)); - s3k_mon_cap_move(MONITOR, APP0_PID, HART0_TIME, APP1_PID, APP_1_TIME); - } - else if (SCHEDULING == ROUND_ROBIN) { - s3k_cap_delete(HART1_TIME); - alt_printf("Time derivation %d \n", - s3k_cap_derive(HART0_TIME, tmp_cap_idx, s3k_mk_time(S3K_MIN_HART, 0, - S3K_SLOT_CNT / 2))); - alt_printf("Time delegation %d \n", - s3k_mon_cap_move(MONITOR, APP0_PID, tmp_cap_idx, APP1_PID, APP_1_TIME)); - } - else if (SCHEDULING == PARALLEL) { - s3k_mon_cap_move(MONITOR, APP0_PID, HART1_TIME, APP1_PID, APP_1_TIME); - } -} int main(void) { // Setup UART access - setup_uart(CAP_UART); + setup_uart(); // Setup app1 capabilities and PC - setup_app_1(CAP_TMP); + setup_app_1(); // Write hello world. - alt_puts("hello, world from app0"); + alt_printf("hello, world from app0\n"); // Setup scehduling - setup_scheduling(CAP_TMP); + setup_scheduling(PARALLEL); // Start app1 - alt_printf("10 %X\n", - s3k_mon_resume(MONITOR, APP1_PID) - ); - - s3k_sync(); + log_sys("10", s3k_mon_resume(MONITOR, APP1_PID)); while (1) alt_puts("0"); diff --git a/projects/tutorial.04.timing-cap/app1/main.c b/projects/tutorial.04.timing-cap/app1/main.c index 2fc5aed..b2df38d 100644 --- a/projects/tutorial.04.timing-cap/app1/main.c +++ b/projects/tutorial.04.timing-cap/app1/main.c @@ -1,7 +1,7 @@ #include "altc/altio.h" #include "s3k/s3k.h" -#define APP_1_TIME 2 +#include "../../tutorial-commons/utils.h" int main(void) { diff --git a/projects/tutorial.05.rpc/Makefile b/projects/tutorial.05.rpc/Makefile new file mode 100644 index 0000000..a2997c1 --- /dev/null +++ b/projects/tutorial.05.rpc/Makefile @@ -0,0 +1,43 @@ +.POSIX: + +export PLATFORM ?=qemu_virt4 +export ROOT :=${abspath ../..} +export BUILD :=${abspath build/${PLATFORM}} +export S3K_CONF_H :=${abspath s3k_conf.h} + +include ${ROOT}/tools.mk + +APPS=app0 app1 + +ELFS:=${patsubst %, ${BUILD}/%.elf, kernel ${APPS}} + +all: kernel ${APPS} + +clean: + rm -rf ${BUILD} + +common: + @${MAKE} -C ${ROOT}/common + +kernel: common + @${MAKE} -C ${ROOT}/kernel + +${APPS}: common + @${MAKE} -f ../build.mk PROGRAM=$@ + +qemu: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/qemu.sh + +qemu-gdb: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/qemu.sh -gdb tcp::3333 -S + +gdb: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/gdb.sh + +gdb-openocd: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/gdb-openocd.sh + +size: ${ELFS} + ${SIZE} ${ELFS} + +.PHONY: all clean size qemu qemu-gdb gdb kernel common ${APPS} diff --git a/projects/tutorial.05.rpc/app0.ld b/projects/tutorial.05.rpc/app0.ld new file mode 100644 index 0000000..3a47536 --- /dev/null +++ b/projects/tutorial.05.rpc/app0.ld @@ -0,0 +1,5 @@ +MEMORY { + RAM (rwx) : ORIGIN = 0x80010000, LENGTH = 0x10000 +} + +__stack_size = 1024; diff --git a/projects/tutorial.05.rpc/app0/main.c b/projects/tutorial.05.rpc/app0/main.c new file mode 100644 index 0000000..8f4e573 --- /dev/null +++ b/projects/tutorial.05.rpc/app0/main.c @@ -0,0 +1,44 @@ +#include "altc/altio.h" +#include "altc/string.h" +#include "s3k/s3k.h" + +#include "../../tutorial-commons/utils.h" + + +int main(void) +{ + // Setup UART access + setup_uart(); + + alt_puts("starting app0"); + + // Setup app1 capabilities and PC + setup_app_1(); + + // setup_scheduling(PARALLEL); // with parallel no tim-out + setup_scheduling(ROUND_ROBIN); + + // Setup socket capabilities. + uint32_t socket = setup_socket(true, true, false); + + // Resume app1 + s3k_mon_resume(MONITOR, APP1_PID); + + s3k_msg_t msg; + s3k_reply_t reply; + memcpy(msg.data, "pong", 5); + + s3k_reg_write(S3K_REG_SERVTIME, 4500); + volatile int x; + while (1) { + do { + reply = s3k_sock_sendrecv(socket, &msg); + if (reply.err == S3K_ERR_TIMEOUT) + alt_puts("0> timeout"); + } while (reply.err); + for (int i=0; i<100; i++) { + x += 1; + } + alt_puts((char *)reply.data); + } +} diff --git a/projects/tutorial.05.rpc/app1.ld b/projects/tutorial.05.rpc/app1.ld new file mode 100644 index 0000000..7e525b5 --- /dev/null +++ b/projects/tutorial.05.rpc/app1.ld @@ -0,0 +1,5 @@ +MEMORY { + RAM (rwx) : ORIGIN = 0x80020000, LENGTH = 0x10000 +} + +__stack_size = 1024; diff --git a/projects/tutorial.05.rpc/app1/main.c b/projects/tutorial.05.rpc/app1/main.c new file mode 100644 index 0000000..bb894bb --- /dev/null +++ b/projects/tutorial.05.rpc/app1/main.c @@ -0,0 +1,29 @@ +#include "altc/altio.h" +#include "altc/string.h" +#include "s3k/s3k.h" + +#include + +#include "../../tutorial-commons/utils.h" + +int main(void) +{ + alt_puts("starting app1"); + s3k_msg_t msg; + s3k_reply_t reply; + int count = 0; + volatile int x; + while (1) { + do { + alt_snprintf((char *)&(msg.data), 32, "ping %d", count); + reply = s3k_sock_sendrecv(APP_1_CAP_SOCKET, &msg); + if (reply.err == S3K_ERR_TIMEOUT) + alt_puts("1> timeout"); + } while (reply.err); + alt_puts((char *)reply.data); + count++; + for (int i=0; i<1000000; i++) { + x += 1; + } + } +} diff --git a/projects/tutorial.05.rpc/build.mk b/projects/tutorial.05.rpc/build.mk new file mode 100644 index 0000000..7cb8d24 --- /dev/null +++ b/projects/tutorial.05.rpc/build.mk @@ -0,0 +1,62 @@ +.POSIX: + +BUILD ?=build +PROGRAM ?=a + +include ${ROOT}/tools.mk +include ${ROOT}/common/plat/${PLATFORM}.mk + +C_SRCS:=${wildcard ${PROGRAM}/*.c} +S_SRCS:=${wildcard ${PROGRAM}/*.S} +OBJS :=${patsubst %.c,${BUILD}/%.o,${C_SRCS}} \ + ${patsubst %.S,${BUILD}/%.o,${S_SRCS}} \ + ${STARTFILES}/start.o +DEPS :=${OBJS:.o=.d} + +CFLAGS:=-march=${ARCH} -mabi=${ABI} -mcmodel=${CMODEL} \ + -DPLATFORM_${PLATFORM} \ + -nostdlib \ + -Os -g3 -flto \ + -I${COMMON_INC} -include ${S3K_CONF_H} + +LDFLAGS:=-march=${ARCH} -mabi=${ABI} -mcmodel=${CMODEL} \ + -nostdlib \ + -flto \ + -T${PROGRAM}.ld -Tdefault.ld \ + -Wl,--no-warn-rwx-segments \ + -L${COMMON_LIB} -ls3k -laltc -lplat \ + +ELF:=${BUILD}/${PROGRAM}.elf +BIN:=${ELF:.elf=.bin} +HEX:=${ELF:.elf=.hex} +DA :=${ELF:.elf=.da} + +all: ${ELF} ${BIN} ${HEX} ${DA} + +clean: + rm -f ${ELF} ${OBJS} ${DEPS} + +${BUILD}/${PROGRAM}/%.o: ${PROGRAM}/%.S + @mkdir -p ${@D} + ${CC} -o $@ $< ${CFLAGS} ${INC} -MMD -c + +${BUILD}/${PROGRAM}/%.o: ${PROGRAM}/%.c + @mkdir -p ${@D} + ${CC} -o $@ $< ${CFLAGS} ${INC} -MMD -c + +%.elf: ${OBJS} + @mkdir -p ${@D} + ${CC} -o $@ ${OBJS} ${LDFLAGS} ${INC} + +%.bin: %.elf + ${OBJCOPY} -O binary $< $@ + +%.hex: %.elf + ${OBJCOPY} -O ihex $< $@ + +%.da: %.elf + ${OBJDUMP} -D $< > $@ + +.PHONY: all clean + +-include ${DEPS} diff --git a/projects/tutorial.05.rpc/default.ld b/projects/tutorial.05.rpc/default.ld new file mode 100644 index 0000000..e32de60 --- /dev/null +++ b/projects/tutorial.05.rpc/default.ld @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +OUTPUT_ARCH(riscv) +ENTRY(_start) + +__global_pointer$ = MIN(_sdata + 0x800, MAX(_data + 0x800, _end - 0x800)); + +SECTIONS { + .text : { + *( .init ) + *( .text .text.* ) + } > RAM + + .data : { + _data = . ; + *( .data ) + *( .data.* ) + _sdata = . ; + *( .sdata ) + *( .sdata.* ) + } > RAM + + .bss : { + _bss = .; + _sbss = .; + *(.sbss .sbss.*) + *(.bss .bss.*) + _end = .; + } > RAM + + .stack : ALIGN(8) { + . += __stack_size; + __stack_pointer = .; + _end = .; + } +} diff --git a/projects/tutorial.05.rpc/s3k_conf.h b/projects/tutorial.05.rpc/s3k_conf.h new file mode 100644 index 0000000..5cb7696 --- /dev/null +++ b/projects/tutorial.05.rpc/s3k_conf.h @@ -0,0 +1,25 @@ +#pragma once + +#define PLATFORM_VIRT +#include "plat/config.h" + +// Number of user processes +#define S3K_PROC_CNT 2 + +// Number of capabilities per process. +#define S3K_CAP_CNT 32 + +// Number of IPC channels. +#define S3K_CHAN_CNT 2 + +// Number of slots per period +#define S3K_SLOT_CNT 32ull + +// Length of slots in ticks. +#define S3K_SLOT_LEN (S3K_RTC_HZ / S3K_SLOT_CNT / 100ull) + +// Scheduler time +#define S3K_SCHED_TIME (S3K_SLOT_LEN / 10) + +// If debugging, comment +#define NDEBUG diff --git a/projects/tutorial.06.rpc-resume/Makefile b/projects/tutorial.06.rpc-resume/Makefile new file mode 100644 index 0000000..a2997c1 --- /dev/null +++ b/projects/tutorial.06.rpc-resume/Makefile @@ -0,0 +1,43 @@ +.POSIX: + +export PLATFORM ?=qemu_virt4 +export ROOT :=${abspath ../..} +export BUILD :=${abspath build/${PLATFORM}} +export S3K_CONF_H :=${abspath s3k_conf.h} + +include ${ROOT}/tools.mk + +APPS=app0 app1 + +ELFS:=${patsubst %, ${BUILD}/%.elf, kernel ${APPS}} + +all: kernel ${APPS} + +clean: + rm -rf ${BUILD} + +common: + @${MAKE} -C ${ROOT}/common + +kernel: common + @${MAKE} -C ${ROOT}/kernel + +${APPS}: common + @${MAKE} -f ../build.mk PROGRAM=$@ + +qemu: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/qemu.sh + +qemu-gdb: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/qemu.sh -gdb tcp::3333 -S + +gdb: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/gdb.sh + +gdb-openocd: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/gdb-openocd.sh + +size: ${ELFS} + ${SIZE} ${ELFS} + +.PHONY: all clean size qemu qemu-gdb gdb kernel common ${APPS} diff --git a/projects/tutorial.06.rpc-resume/app0.ld b/projects/tutorial.06.rpc-resume/app0.ld new file mode 100644 index 0000000..3a47536 --- /dev/null +++ b/projects/tutorial.06.rpc-resume/app0.ld @@ -0,0 +1,5 @@ +MEMORY { + RAM (rwx) : ORIGIN = 0x80010000, LENGTH = 0x10000 +} + +__stack_size = 1024; diff --git a/projects/tutorial.06.rpc-resume/app0/main.c b/projects/tutorial.06.rpc-resume/app0/main.c new file mode 100644 index 0000000..0033b1f --- /dev/null +++ b/projects/tutorial.06.rpc-resume/app0/main.c @@ -0,0 +1,35 @@ +#include "altc/altio.h" +#include "altc/string.h" +#include "s3k/s3k.h" + +#include "../../tutorial-commons/utils.h" + + +int main(void) +{ + // Setup UART access + setup_uart(); + + alt_puts("starting app0"); + + // Setup app1 capabilities and PC + setup_app_1(); + + // Setup socket capabilities. + uint64_t socket = setup_socket(false, true, false); + + // Resume app1 + s3k_mon_resume(MONITOR, APP1_PID); + + wait_for_app1_blocked(); + + s3k_msg_t msg; + s3k_reply_t reply; + memcpy(msg.data, "ping", 5); + + s3k_reg_write(S3K_REG_SERVTIME, 4500); + while (1) { + reply = send_receive_forever(socket, msg); + alt_printf("APP0: %s\n", (char *)reply.data); + } +} diff --git a/projects/tutorial.06.rpc-resume/app1.ld b/projects/tutorial.06.rpc-resume/app1.ld new file mode 100644 index 0000000..7e525b5 --- /dev/null +++ b/projects/tutorial.06.rpc-resume/app1.ld @@ -0,0 +1,5 @@ +MEMORY { + RAM (rwx) : ORIGIN = 0x80020000, LENGTH = 0x10000 +} + +__stack_size = 1024; diff --git a/projects/tutorial.06.rpc-resume/app1/main.c b/projects/tutorial.06.rpc-resume/app1/main.c new file mode 100644 index 0000000..aba659c --- /dev/null +++ b/projects/tutorial.06.rpc-resume/app1/main.c @@ -0,0 +1,28 @@ +#include "altc/altio.h" +#include "altc/string.h" +#include "s3k/s3k.h" + +#include "../../tutorial-commons/utils.h" + + +#include + +int count = 0; + +s3k_msg_t on_msg(s3k_reply_t input, uint32_t cap_idx) { + alt_printf("APP1: %s\n", (char *)input.data); + s3k_msg_t output; + + volatile int x; + for (int i=0; i<1000; i++) { + x += 1; + } + alt_snprintf((char*)(& output.data[0]), 10, "pong %d", count++); + return output; +} + +int main(void) +{ + alt_puts("starting app1"); + server_main_loop(on_msg, false); +} diff --git a/projects/tutorial.06.rpc-resume/build.mk b/projects/tutorial.06.rpc-resume/build.mk new file mode 100644 index 0000000..7cb8d24 --- /dev/null +++ b/projects/tutorial.06.rpc-resume/build.mk @@ -0,0 +1,62 @@ +.POSIX: + +BUILD ?=build +PROGRAM ?=a + +include ${ROOT}/tools.mk +include ${ROOT}/common/plat/${PLATFORM}.mk + +C_SRCS:=${wildcard ${PROGRAM}/*.c} +S_SRCS:=${wildcard ${PROGRAM}/*.S} +OBJS :=${patsubst %.c,${BUILD}/%.o,${C_SRCS}} \ + ${patsubst %.S,${BUILD}/%.o,${S_SRCS}} \ + ${STARTFILES}/start.o +DEPS :=${OBJS:.o=.d} + +CFLAGS:=-march=${ARCH} -mabi=${ABI} -mcmodel=${CMODEL} \ + -DPLATFORM_${PLATFORM} \ + -nostdlib \ + -Os -g3 -flto \ + -I${COMMON_INC} -include ${S3K_CONF_H} + +LDFLAGS:=-march=${ARCH} -mabi=${ABI} -mcmodel=${CMODEL} \ + -nostdlib \ + -flto \ + -T${PROGRAM}.ld -Tdefault.ld \ + -Wl,--no-warn-rwx-segments \ + -L${COMMON_LIB} -ls3k -laltc -lplat \ + +ELF:=${BUILD}/${PROGRAM}.elf +BIN:=${ELF:.elf=.bin} +HEX:=${ELF:.elf=.hex} +DA :=${ELF:.elf=.da} + +all: ${ELF} ${BIN} ${HEX} ${DA} + +clean: + rm -f ${ELF} ${OBJS} ${DEPS} + +${BUILD}/${PROGRAM}/%.o: ${PROGRAM}/%.S + @mkdir -p ${@D} + ${CC} -o $@ $< ${CFLAGS} ${INC} -MMD -c + +${BUILD}/${PROGRAM}/%.o: ${PROGRAM}/%.c + @mkdir -p ${@D} + ${CC} -o $@ $< ${CFLAGS} ${INC} -MMD -c + +%.elf: ${OBJS} + @mkdir -p ${@D} + ${CC} -o $@ ${OBJS} ${LDFLAGS} ${INC} + +%.bin: %.elf + ${OBJCOPY} -O binary $< $@ + +%.hex: %.elf + ${OBJCOPY} -O ihex $< $@ + +%.da: %.elf + ${OBJDUMP} -D $< > $@ + +.PHONY: all clean + +-include ${DEPS} diff --git a/projects/tutorial.06.rpc-resume/default.ld b/projects/tutorial.06.rpc-resume/default.ld new file mode 100644 index 0000000..e32de60 --- /dev/null +++ b/projects/tutorial.06.rpc-resume/default.ld @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +OUTPUT_ARCH(riscv) +ENTRY(_start) + +__global_pointer$ = MIN(_sdata + 0x800, MAX(_data + 0x800, _end - 0x800)); + +SECTIONS { + .text : { + *( .init ) + *( .text .text.* ) + } > RAM + + .data : { + _data = . ; + *( .data ) + *( .data.* ) + _sdata = . ; + *( .sdata ) + *( .sdata.* ) + } > RAM + + .bss : { + _bss = .; + _sbss = .; + *(.sbss .sbss.*) + *(.bss .bss.*) + _end = .; + } > RAM + + .stack : ALIGN(8) { + . += __stack_size; + __stack_pointer = .; + _end = .; + } +} diff --git a/projects/tutorial.06.rpc-resume/s3k_conf.h b/projects/tutorial.06.rpc-resume/s3k_conf.h new file mode 100644 index 0000000..5cb7696 --- /dev/null +++ b/projects/tutorial.06.rpc-resume/s3k_conf.h @@ -0,0 +1,25 @@ +#pragma once + +#define PLATFORM_VIRT +#include "plat/config.h" + +// Number of user processes +#define S3K_PROC_CNT 2 + +// Number of capabilities per process. +#define S3K_CAP_CNT 32 + +// Number of IPC channels. +#define S3K_CHAN_CNT 2 + +// Number of slots per period +#define S3K_SLOT_CNT 32ull + +// Length of slots in ticks. +#define S3K_SLOT_LEN (S3K_RTC_HZ / S3K_SLOT_CNT / 100ull) + +// Scheduler time +#define S3K_SCHED_TIME (S3K_SLOT_LEN / 10) + +// If debugging, comment +#define NDEBUG diff --git a/projects/tutorial.07.msg-noyield/Makefile b/projects/tutorial.07.msg-noyield/Makefile new file mode 100644 index 0000000..a2997c1 --- /dev/null +++ b/projects/tutorial.07.msg-noyield/Makefile @@ -0,0 +1,43 @@ +.POSIX: + +export PLATFORM ?=qemu_virt4 +export ROOT :=${abspath ../..} +export BUILD :=${abspath build/${PLATFORM}} +export S3K_CONF_H :=${abspath s3k_conf.h} + +include ${ROOT}/tools.mk + +APPS=app0 app1 + +ELFS:=${patsubst %, ${BUILD}/%.elf, kernel ${APPS}} + +all: kernel ${APPS} + +clean: + rm -rf ${BUILD} + +common: + @${MAKE} -C ${ROOT}/common + +kernel: common + @${MAKE} -C ${ROOT}/kernel + +${APPS}: common + @${MAKE} -f ../build.mk PROGRAM=$@ + +qemu: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/qemu.sh + +qemu-gdb: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/qemu.sh -gdb tcp::3333 -S + +gdb: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/gdb.sh + +gdb-openocd: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/gdb-openocd.sh + +size: ${ELFS} + ${SIZE} ${ELFS} + +.PHONY: all clean size qemu qemu-gdb gdb kernel common ${APPS} diff --git a/projects/tutorial.07.msg-noyield/app0.ld b/projects/tutorial.07.msg-noyield/app0.ld new file mode 100644 index 0000000..3a47536 --- /dev/null +++ b/projects/tutorial.07.msg-noyield/app0.ld @@ -0,0 +1,5 @@ +MEMORY { + RAM (rwx) : ORIGIN = 0x80010000, LENGTH = 0x10000 +} + +__stack_size = 1024; diff --git a/projects/tutorial.07.msg-noyield/app0/main.c b/projects/tutorial.07.msg-noyield/app0/main.c new file mode 100644 index 0000000..7d7a962 --- /dev/null +++ b/projects/tutorial.07.msg-noyield/app0/main.c @@ -0,0 +1,44 @@ +#include "altc/altio.h" +#include "altc/string.h" +#include "s3k/s3k.h" + +#include "../../tutorial-commons/utils.h" + + +int main(void) +{ + // Setup UART access + setup_uart(); + + alt_puts("starting app0"); + + // Setup app1 capabilities and PC + setup_app_1(); + + // setup_scheduling(PARALLEL); // with parallel no tim-out + setup_scheduling(ROUND_ROBIN); + + // Setup socket capabilities. + uint32_t socket = setup_socket(true, false, false); + + // Resume app1 + s3k_mon_resume(MONITOR, APP1_PID); + + s3k_msg_t msg; + s3k_reply_t reply; + memcpy(msg.data, "pong", 5); + + s3k_reg_write(S3K_REG_SERVTIME, 4500); + volatile int x; + while (1) { + do { + reply = s3k_sock_sendrecv(socket, &msg); + if (reply.err == S3K_ERR_TIMEOUT) + alt_puts("0> timeout"); + } while (reply.err); + for (int i=0; i<1000; i++) { + x += 1; + } + alt_puts((char *)reply.data); + } +} diff --git a/projects/tutorial.07.msg-noyield/app1.ld b/projects/tutorial.07.msg-noyield/app1.ld new file mode 100644 index 0000000..7e525b5 --- /dev/null +++ b/projects/tutorial.07.msg-noyield/app1.ld @@ -0,0 +1,5 @@ +MEMORY { + RAM (rwx) : ORIGIN = 0x80020000, LENGTH = 0x10000 +} + +__stack_size = 1024; diff --git a/projects/tutorial.07.msg-noyield/app1/main.c b/projects/tutorial.07.msg-noyield/app1/main.c new file mode 100644 index 0000000..354ad25 --- /dev/null +++ b/projects/tutorial.07.msg-noyield/app1/main.c @@ -0,0 +1,29 @@ +#include "altc/altio.h" +#include "altc/string.h" +#include "s3k/s3k.h" + +#include + +#include "../../tutorial-commons/utils.h" + +int main(void) +{ + alt_puts("starting app1"); + s3k_msg_t msg; + s3k_reply_t reply; + int count = 0; + volatile int x; + while (1) { + do { + alt_snprintf((char*)&(msg.data), 32, "ping %d", count); + reply = s3k_sock_sendrecv(APP_1_CAP_SOCKET, &msg); + if (reply.err == S3K_ERR_TIMEOUT) + alt_puts("1> timeout"); + } while (reply.err); + alt_puts((char *)reply.data); + count++; + for (int i=0; i<1000000; i++) { + x += 1; + } + } +} diff --git a/projects/tutorial.07.msg-noyield/build.mk b/projects/tutorial.07.msg-noyield/build.mk new file mode 100644 index 0000000..7cb8d24 --- /dev/null +++ b/projects/tutorial.07.msg-noyield/build.mk @@ -0,0 +1,62 @@ +.POSIX: + +BUILD ?=build +PROGRAM ?=a + +include ${ROOT}/tools.mk +include ${ROOT}/common/plat/${PLATFORM}.mk + +C_SRCS:=${wildcard ${PROGRAM}/*.c} +S_SRCS:=${wildcard ${PROGRAM}/*.S} +OBJS :=${patsubst %.c,${BUILD}/%.o,${C_SRCS}} \ + ${patsubst %.S,${BUILD}/%.o,${S_SRCS}} \ + ${STARTFILES}/start.o +DEPS :=${OBJS:.o=.d} + +CFLAGS:=-march=${ARCH} -mabi=${ABI} -mcmodel=${CMODEL} \ + -DPLATFORM_${PLATFORM} \ + -nostdlib \ + -Os -g3 -flto \ + -I${COMMON_INC} -include ${S3K_CONF_H} + +LDFLAGS:=-march=${ARCH} -mabi=${ABI} -mcmodel=${CMODEL} \ + -nostdlib \ + -flto \ + -T${PROGRAM}.ld -Tdefault.ld \ + -Wl,--no-warn-rwx-segments \ + -L${COMMON_LIB} -ls3k -laltc -lplat \ + +ELF:=${BUILD}/${PROGRAM}.elf +BIN:=${ELF:.elf=.bin} +HEX:=${ELF:.elf=.hex} +DA :=${ELF:.elf=.da} + +all: ${ELF} ${BIN} ${HEX} ${DA} + +clean: + rm -f ${ELF} ${OBJS} ${DEPS} + +${BUILD}/${PROGRAM}/%.o: ${PROGRAM}/%.S + @mkdir -p ${@D} + ${CC} -o $@ $< ${CFLAGS} ${INC} -MMD -c + +${BUILD}/${PROGRAM}/%.o: ${PROGRAM}/%.c + @mkdir -p ${@D} + ${CC} -o $@ $< ${CFLAGS} ${INC} -MMD -c + +%.elf: ${OBJS} + @mkdir -p ${@D} + ${CC} -o $@ ${OBJS} ${LDFLAGS} ${INC} + +%.bin: %.elf + ${OBJCOPY} -O binary $< $@ + +%.hex: %.elf + ${OBJCOPY} -O ihex $< $@ + +%.da: %.elf + ${OBJDUMP} -D $< > $@ + +.PHONY: all clean + +-include ${DEPS} diff --git a/projects/tutorial.07.msg-noyield/default.ld b/projects/tutorial.07.msg-noyield/default.ld new file mode 100644 index 0000000..e32de60 --- /dev/null +++ b/projects/tutorial.07.msg-noyield/default.ld @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +OUTPUT_ARCH(riscv) +ENTRY(_start) + +__global_pointer$ = MIN(_sdata + 0x800, MAX(_data + 0x800, _end - 0x800)); + +SECTIONS { + .text : { + *( .init ) + *( .text .text.* ) + } > RAM + + .data : { + _data = . ; + *( .data ) + *( .data.* ) + _sdata = . ; + *( .sdata ) + *( .sdata.* ) + } > RAM + + .bss : { + _bss = .; + _sbss = .; + *(.sbss .sbss.*) + *(.bss .bss.*) + _end = .; + } > RAM + + .stack : ALIGN(8) { + . += __stack_size; + __stack_pointer = .; + _end = .; + } +} diff --git a/projects/tutorial.07.msg-noyield/s3k_conf.h b/projects/tutorial.07.msg-noyield/s3k_conf.h new file mode 100644 index 0000000..5cb7696 --- /dev/null +++ b/projects/tutorial.07.msg-noyield/s3k_conf.h @@ -0,0 +1,25 @@ +#pragma once + +#define PLATFORM_VIRT +#include "plat/config.h" + +// Number of user processes +#define S3K_PROC_CNT 2 + +// Number of capabilities per process. +#define S3K_CAP_CNT 32 + +// Number of IPC channels. +#define S3K_CHAN_CNT 2 + +// Number of slots per period +#define S3K_SLOT_CNT 32ull + +// Length of slots in ticks. +#define S3K_SLOT_LEN (S3K_RTC_HZ / S3K_SLOT_CNT / 100ull) + +// Scheduler time +#define S3K_SCHED_TIME (S3K_SLOT_LEN / 10) + +// If debugging, comment +#define NDEBUG diff --git a/projects/tutorial.08.rpc-mem-cap/Makefile b/projects/tutorial.08.rpc-mem-cap/Makefile new file mode 100644 index 0000000..a2997c1 --- /dev/null +++ b/projects/tutorial.08.rpc-mem-cap/Makefile @@ -0,0 +1,43 @@ +.POSIX: + +export PLATFORM ?=qemu_virt4 +export ROOT :=${abspath ../..} +export BUILD :=${abspath build/${PLATFORM}} +export S3K_CONF_H :=${abspath s3k_conf.h} + +include ${ROOT}/tools.mk + +APPS=app0 app1 + +ELFS:=${patsubst %, ${BUILD}/%.elf, kernel ${APPS}} + +all: kernel ${APPS} + +clean: + rm -rf ${BUILD} + +common: + @${MAKE} -C ${ROOT}/common + +kernel: common + @${MAKE} -C ${ROOT}/kernel + +${APPS}: common + @${MAKE} -f ../build.mk PROGRAM=$@ + +qemu: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/qemu.sh + +qemu-gdb: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/qemu.sh -gdb tcp::3333 -S + +gdb: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/gdb.sh + +gdb-openocd: kernel ${APPS} + @ELFS="${ELFS}" ${ROOT}/scripts/gdb-openocd.sh + +size: ${ELFS} + ${SIZE} ${ELFS} + +.PHONY: all clean size qemu qemu-gdb gdb kernel common ${APPS} diff --git a/projects/tutorial.08.rpc-mem-cap/app0.ld b/projects/tutorial.08.rpc-mem-cap/app0.ld new file mode 100644 index 0000000..3a47536 --- /dev/null +++ b/projects/tutorial.08.rpc-mem-cap/app0.ld @@ -0,0 +1,5 @@ +MEMORY { + RAM (rwx) : ORIGIN = 0x80010000, LENGTH = 0x10000 +} + +__stack_size = 1024; diff --git a/projects/tutorial.08.rpc-mem-cap/app0/main.c b/projects/tutorial.08.rpc-mem-cap/app0/main.c new file mode 100644 index 0000000..5357621 --- /dev/null +++ b/projects/tutorial.08.rpc-mem-cap/app0/main.c @@ -0,0 +1,63 @@ +#include "altc/altio.h" +#include "altc/string.h" +#include "s3k/s3k.h" + +#include "../../tutorial-commons/utils.h" + +uint32_t setup_buffer_cap() { + uint32_t new_cap = find_free_cap(); + debug_capability_from_idx(RAM_MEM); + log_sys("app 0: derive cap for shared buffer", + s3k_cap_derive(RAM_MEM, new_cap, + s3k_mk_memory(SHARED_BUFFER_BASE, SHARED_BUFFER_BASE + SHARED_BUFFER_SIZE, S3K_MEM_RW))); + return new_cap; +} + +uint32_t setup_buffer_pmp(uint32_t parent_cap_idx) { + uint32_t pmp_cap_idx = find_free_cap(); + log_sys("app 0: revoke parent cap", s3k_cap_revoke(parent_cap_idx)); + log_sys("app 0: derive new mem cap", + s3k_cap_derive(parent_cap_idx, pmp_cap_idx, + s3k_mk_pmp( s3k_napot_encode(SHARED_BUFFER_BASE, SHARED_BUFFER_SIZE), S3K_MEM_RW))); + log_sys("app 0: load pmp for new buffer", s3k_pmp_load(pmp_cap_idx, BUFFER_PMP)); + s3k_sync_mem(); + return pmp_cap_idx; +} + +int main(void) +{ + // Setup UART access + setup_uart(); + + alt_puts("starting app0"); + + // Setup app1 capabilities and PC + setup_app_1(); + + // Setup socket capabilities. + uint64_t socket = setup_socket(false, true, true); + + // Resume app1 + s3k_mon_resume(MONITOR, APP1_PID); + + wait_for_app1_blocked(); + alt_printf("APP0: other app booted\n"); + + uint32_t parent_cap = setup_buffer_cap(); + + s3k_msg_t msg; + s3k_reply_t reply; + s3k_reg_write(S3K_REG_SERVTIME, 4500); + + uint32_t counter = 0; + while (1) { + uint32_t child_cap = setup_buffer_pmp(parent_cap); + alt_printf("APP0: writing counter in shared memory %d\n", counter); + *((uint32_t *) SHARED_BUFFER_BASE) = ++counter; + msg.send_cap = true; + msg.cap_idx = child_cap; + alt_printf("APP0: sending %d\n", counter); + reply = send_receive_forever(socket, msg); + alt_printf("APP0: received %s\n", (char *)reply.data); + } +} diff --git a/projects/tutorial.08.rpc-mem-cap/app1.ld b/projects/tutorial.08.rpc-mem-cap/app1.ld new file mode 100644 index 0000000..7e525b5 --- /dev/null +++ b/projects/tutorial.08.rpc-mem-cap/app1.ld @@ -0,0 +1,5 @@ +MEMORY { + RAM (rwx) : ORIGIN = 0x80020000, LENGTH = 0x10000 +} + +__stack_size = 1024; diff --git a/projects/tutorial.08.rpc-mem-cap/app1/main.c b/projects/tutorial.08.rpc-mem-cap/app1/main.c new file mode 100644 index 0000000..061468f --- /dev/null +++ b/projects/tutorial.08.rpc-mem-cap/app1/main.c @@ -0,0 +1,32 @@ +#include "altc/altio.h" +#include "altc/string.h" +#include "s3k/s3k.h" + +#include "../../tutorial-commons/utils.h" + + +#include + +int count = 0; + +s3k_msg_t on_msg(s3k_reply_t input, uint32_t cap_idx) { + alt_printf("1> handling request\n"); + s3k_msg_t output; + if (input.cap.type == 0) { + alt_printf("1> missing capability in message\n"); + alt_snprintf((char*)&(output.data), 10, ""); + return output; + } + + s3k_pmp_load(cap_idx, APP_1_PMP_SLOT_BUFFER); + s3k_sync_mem(); + uint32_t counter = *((uint32_t *)SHARED_BUFFER_BASE); + alt_snprintf((char*)&(output.data), 10, "%d", counter); + return output; +} + +int main(void) +{ + alt_puts("starting app1"); + server_main_loop(on_msg, true); +} diff --git a/projects/tutorial.08.rpc-mem-cap/build.mk b/projects/tutorial.08.rpc-mem-cap/build.mk new file mode 100644 index 0000000..7cb8d24 --- /dev/null +++ b/projects/tutorial.08.rpc-mem-cap/build.mk @@ -0,0 +1,62 @@ +.POSIX: + +BUILD ?=build +PROGRAM ?=a + +include ${ROOT}/tools.mk +include ${ROOT}/common/plat/${PLATFORM}.mk + +C_SRCS:=${wildcard ${PROGRAM}/*.c} +S_SRCS:=${wildcard ${PROGRAM}/*.S} +OBJS :=${patsubst %.c,${BUILD}/%.o,${C_SRCS}} \ + ${patsubst %.S,${BUILD}/%.o,${S_SRCS}} \ + ${STARTFILES}/start.o +DEPS :=${OBJS:.o=.d} + +CFLAGS:=-march=${ARCH} -mabi=${ABI} -mcmodel=${CMODEL} \ + -DPLATFORM_${PLATFORM} \ + -nostdlib \ + -Os -g3 -flto \ + -I${COMMON_INC} -include ${S3K_CONF_H} + +LDFLAGS:=-march=${ARCH} -mabi=${ABI} -mcmodel=${CMODEL} \ + -nostdlib \ + -flto \ + -T${PROGRAM}.ld -Tdefault.ld \ + -Wl,--no-warn-rwx-segments \ + -L${COMMON_LIB} -ls3k -laltc -lplat \ + +ELF:=${BUILD}/${PROGRAM}.elf +BIN:=${ELF:.elf=.bin} +HEX:=${ELF:.elf=.hex} +DA :=${ELF:.elf=.da} + +all: ${ELF} ${BIN} ${HEX} ${DA} + +clean: + rm -f ${ELF} ${OBJS} ${DEPS} + +${BUILD}/${PROGRAM}/%.o: ${PROGRAM}/%.S + @mkdir -p ${@D} + ${CC} -o $@ $< ${CFLAGS} ${INC} -MMD -c + +${BUILD}/${PROGRAM}/%.o: ${PROGRAM}/%.c + @mkdir -p ${@D} + ${CC} -o $@ $< ${CFLAGS} ${INC} -MMD -c + +%.elf: ${OBJS} + @mkdir -p ${@D} + ${CC} -o $@ ${OBJS} ${LDFLAGS} ${INC} + +%.bin: %.elf + ${OBJCOPY} -O binary $< $@ + +%.hex: %.elf + ${OBJCOPY} -O ihex $< $@ + +%.da: %.elf + ${OBJDUMP} -D $< > $@ + +.PHONY: all clean + +-include ${DEPS} diff --git a/projects/tutorial.08.rpc-mem-cap/default.ld b/projects/tutorial.08.rpc-mem-cap/default.ld new file mode 100644 index 0000000..e32de60 --- /dev/null +++ b/projects/tutorial.08.rpc-mem-cap/default.ld @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +OUTPUT_ARCH(riscv) +ENTRY(_start) + +__global_pointer$ = MIN(_sdata + 0x800, MAX(_data + 0x800, _end - 0x800)); + +SECTIONS { + .text : { + *( .init ) + *( .text .text.* ) + } > RAM + + .data : { + _data = . ; + *( .data ) + *( .data.* ) + _sdata = . ; + *( .sdata ) + *( .sdata.* ) + } > RAM + + .bss : { + _bss = .; + _sbss = .; + *(.sbss .sbss.*) + *(.bss .bss.*) + _end = .; + } > RAM + + .stack : ALIGN(8) { + . += __stack_size; + __stack_pointer = .; + _end = .; + } +} diff --git a/projects/tutorial.08.rpc-mem-cap/s3k_conf.h b/projects/tutorial.08.rpc-mem-cap/s3k_conf.h new file mode 100644 index 0000000..5cb7696 --- /dev/null +++ b/projects/tutorial.08.rpc-mem-cap/s3k_conf.h @@ -0,0 +1,25 @@ +#pragma once + +#define PLATFORM_VIRT +#include "plat/config.h" + +// Number of user processes +#define S3K_PROC_CNT 2 + +// Number of capabilities per process. +#define S3K_CAP_CNT 32 + +// Number of IPC channels. +#define S3K_CHAN_CNT 2 + +// Number of slots per period +#define S3K_SLOT_CNT 32ull + +// Length of slots in ticks. +#define S3K_SLOT_LEN (S3K_RTC_HZ / S3K_SLOT_CNT / 100ull) + +// Scheduler time +#define S3K_SCHED_TIME (S3K_SLOT_LEN / 10) + +// If debugging, comment +#define NDEBUG