From 40cc5affc056f48daa666a1b16d5c450b035feb5 Mon Sep 17 00:00:00 2001 From: Calascibetta Romain Date: Mon, 23 Dec 2024 01:46:17 +0100 Subject: [PATCH] . --- GNUmakefile | 5 +- clock.c | 44 ++- coherent_page.c | 13 + crt.c | 6 +- dtb.c | 48 +++ exception_handler.c | 25 ++ include/bcm.h | 18 +- include/board.h | 8 + include/clock.h | 4 +- include/coherent_page.h | 12 + include/cpu_aarch64.h | 13 + include/crt.h | 11 + include/dtb.h | 8 + include/exception_handler.h | 31 +- include/log.h | 11 +- include/mbox.h | 8 +- include/mem.h | 4 + include/memory.h | 6 + include/memory_map.h | 35 ++- include/pager.h | 12 + include/power.h | 7 + include/serial.h | 14 +- include/spinlock.h | 11 + include/synchronize.h | 14 + include/sysconfig.h | 2 +- include/tag.h | 10 +- include/translation_table.h | 112 +++++++ interrupt_handler.c | 4 + kernel.c | 79 ++++- log.c | 8 +- mbox.c | 13 +- memory.c | 97 ++++++ nolibc/assert.c | 2 +- nolibc/puts.c | 6 +- openlibm/src/e_lgamma_r.c | 4 + openlibm/src/e_lgammaf_r.c | 4 + pager.c | 64 ++++ power.c | 21 ++ printf.c | 17 +- serial.c | 71 ++++- spinlock.c | 45 +++ synchronize.c | 58 ++++ tag.c | 68 +++++ test03.map | 574 ++++++++++++++++++++++++++++++++++++ translation_table.c | 93 ++++++ 45 files changed, 1591 insertions(+), 129 deletions(-) create mode 100644 coherent_page.c create mode 100644 dtb.c create mode 100644 include/board.h create mode 100644 include/coherent_page.h create mode 100644 include/cpu_aarch64.h create mode 100644 include/crt.h create mode 100644 include/dtb.h create mode 100644 include/memory.h create mode 100644 include/pager.h create mode 100644 include/power.h create mode 100644 include/spinlock.h create mode 100644 include/synchronize.h create mode 100644 include/translation_table.h create mode 100644 memory.c create mode 100644 pager.c create mode 100644 power.c create mode 100644 spinlock.c create mode 100644 synchronize.c create mode 100644 tag.c create mode 100644 test03.map create mode 100644 translation_table.c diff --git a/GNUmakefile b/GNUmakefile index 7ee13be..70c1bc2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -50,7 +50,8 @@ LDFLAGS += -nostdlib -static -Wl,--no-warn-rwx-segments \ -Wl,--start-group -L . -lgilbraltar -L nolibc -lnolibc -L openlibm -lopenlibm -lgcc -Wl,--end-group SRCS= kernel.c timer.c led.c interrupt_handler.c exception_handler.c \ - mbox.c clock.c crt.c serial.c log.c + mbox.c clock.c crt.c serial.c log.c power.c tag.c coherent_page.c dtb.c \ + synchronize.c spinlock.c memory.c pager.c translation_table.c ASMS= startup.S exception_stub.S @@ -116,5 +117,5 @@ test02.img: libgilbraltar.a nolibc/libnolibc.a openlibm/libopenlibm.a test/test0 test03.img: libgilbraltar.a nolibc/libnolibc.a openlibm/libopenlibm.a test/test03.o @echo "LD ${@:img=elf}" - @$(LD) test/${@:img=o} -o ${@:img=elf} $(LDFLAGS) -Wl,-T gilbraltar.ld + @$(LD) test/${@:img=o} -o ${@:img=elf} $(LDFLAGS) -Wl,-Map ${@:img=map} -Wl,-T gilbraltar.ld @$(OBJCOPY) ${@:img=elf} -O binary $@ diff --git a/clock.c b/clock.c index 8ef2996..3349f40 100644 --- a/clock.c +++ b/clock.c @@ -1,41 +1,31 @@ -#include +#include +#include #include +#include #include -#define PROPTAG_GET_CLOCK_RATE 0x00030002 +#define PROPTAG_GET_CLOCK_RATE 0x00030002 #define PROPTAG_GET_CLOCK_RATE_MEASURED 0x00030047 -uint32_t gilbraltar_get_clock(uint32_t cid) { - uint32_t proptag0[] __attribute__ ((aligned(16))) = - { - 8.4, - CODE_REQUEST, - PROPTAG_GET_CLOCK_RATE, - 4*4, - 1*4, - cid, - 0, - PROPTAG_END - }; +uint32_t gilbraltar_get_rate_of_clock(uint32_t cid) { + uint32_t proptag0[] __attribute__((aligned(16))) = { + 8 * 4, CODE_REQUEST, PROPTAG_GET_CLOCK_RATE, 2 * 4, 1 * 4, cid, + 0, PROPTAG_END}; - gilbraltar_mbox_write_read((uintptr_t) &proptag0); + for (int i = 0; i < sizeof(proptag0) / 4; i++) + gilbraltar_log(DEBUG, "%08lx[%d]: %04x\r\n", (uintptr_t)proptag0, i, + proptag0[i]); + + assert(gilbraltar_mbox_write_read((uintptr_t)&proptag0)); if (proptag0[6] != 0) return proptag0[6]; - uint32_t proptag1[] __attribute__ ((aligned(16))) = - { - 8*4, - CODE_REQUEST, - PROPTAG_GET_CLOCK_RATE_MEASURED, - 4*4, - 1*4, - cid, - 0, - PROPTAG_END - }; + uint32_t proptag1[] __attribute__((aligned(16))) = { + 8 * 4, CODE_REQUEST, PROPTAG_GET_CLOCK_RATE_MEASURED, 2 * 4, 1 * 4, cid, + 0, PROPTAG_END}; - gilbraltar_mbox_write_read((uintptr_t) &proptag1); + assert(gilbraltar_mbox_write_read((uintptr_t)&proptag1)); return proptag1[6]; } diff --git a/coherent_page.c b/coherent_page.c new file mode 100644 index 0000000..aa5eae6 --- /dev/null +++ b/coherent_page.c @@ -0,0 +1,13 @@ +#include +#include + +uintptr_t get_coherent_page(enum coherent_page slot) { + switch (slot) { + case PROP_MAILBOX: + return (MEM_COHERENT_REGION); + case GPIO_VIRTBUF: + return (MEM_COHERENT_REGION + PAGE_SIZE); + } + + abort(); +} diff --git a/crt.c b/crt.c index 22eab7d..ddd1c3d 100644 --- a/crt.c +++ b/crt.c @@ -34,11 +34,13 @@ uintptr_t SSP_GUARD_SYMBOL = 0x00deadbeef0d0a00; * message and abort, taking care to make minimal use of the stack. */ static const char stack_chk_fail_message[] = - "ABORT: Stack corruption detected\n"; + "ABORT: Stack corruption detected\r\n"; -extern void uart_puts(const char *str); +extern void gilbraltar_serial_puts(const char *str); __attribute__((noreturn)) void SSP_FAIL_SYMBOL(void) { + gilbraltar_serial_puts(stack_chk_fail_message); + for (;;) ; } diff --git a/dtb.c b/dtb.c new file mode 100644 index 0000000..8d199fa --- /dev/null +++ b/dtb.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +#define ARM_DTB_PTR32 0x000000f8 + +struct __attribute__((packed)) header { + uint32_t magic; +#define DTB_MAGIC 0xd00dfeed + uint32_t total_size; +#define DTB_MAX_SIZE 0x100000 + uint32_t off_dt_strt; + uint32_t off_dt_strs; + uint32_t off_mem_rsvmap; + uint32_t version; +#define DTB_VERSION 17 + uint32_t last_comp_version; +#define DTB_LAST_COMP_VERSION 16 + uint32_t boot_cpuid_phys; + uint32_t size_dt_strs; + uint32_t size_dt_strt; +}; + +static const struct header *hdr = 0; + +bool gilbraltar_dtb_init(void) { + uint32_t *volatile ptr = (uint32_t *volatile)ARM_DTB_PTR32; + + const void *dtb = (const void *)(uintptr_t)*ptr; + hdr = (const struct header *)dtb; + + if (be32toh(hdr->magic) != DTB_MAGIC || + be32toh(hdr->last_comp_version) != DTB_LAST_COMP_VERSION) + return false; + + uint32_t total_size = be32toh(hdr->total_size); + + if (total_size < sizeof(struct header) || total_size > DTB_MAX_SIZE) + return false; + + gilbraltar_log(INFO, " dtb magic : %04x\r\n", be32toh(hdr->magic)); + gilbraltar_log(INFO, "dtb version : %d\r\n", be32toh(hdr->last_comp_version)); + gilbraltar_log(INFO, " dtb size : %d byte(s)\r\n", + be32toh(hdr->total_size)); + + return true; +} diff --git a/exception_handler.c b/exception_handler.c index ef8824d..7b03231 100644 --- a/exception_handler.c +++ b/exception_handler.c @@ -1,6 +1,31 @@ #include +#include +#include + +static const char *names[] = {"Unexpected exception", "Synchronous exception", + "System error"}; void gilbraltar_exception_handler(uint64_t exn, struct frame *frame) { + enable_fiqs(); + + uint64_t sp = frame->sp_el0; + + if ((frame->spsr_el1 & 0xf) == 0x05) + sp = frame->sp_el1; + + uint64_t ec = (frame->esr_el1 >> 26) & 0x3f; + uint64_t iss = frame->esr_el1 & 0x1ffffff; + uint64_t far = 0; + + if ((0x20 <= ec && ec <= 0x25) || (0x34 <= ec && ec <= 0x35)) + far = frame->far_el1; + + gilbraltar_log(ERROR, + "%s (pc: 0x%lx, ec: 0x%lx, iss: 0x%lx, far: 0x%lx, sp: 0x%lx, " + "lr: 0x%lx, spsr: 0x%lx)\r\n", + names[exn], frame->elr_el1, ec, iss, far, sp, frame->x30, + frame->spsr_el1); + while (1) __asm__ __volatile("wfi"); } diff --git a/include/bcm.h b/include/bcm.h index d2121a5..c79f0c0 100644 --- a/include/bcm.h +++ b/include/bcm.h @@ -10,14 +10,26 @@ #define ARM_SYSTIMER_CHI (ARM_SYSTIMER_BASE + 0x08) // Interrupt Controller -#define ARM_IC_BASE (ARM_IO_BASE + 0xb000) +#define ARM_IC_BASE (ARM_IO_BASE + 0xb000) #define ARM_IC_FIQ_CONTROL (ARM_IO_BASE + 0x20c) // General Purpose I/O #2 -#define ARM_GPIO2_BASE (ARM_IO_BASE + 0x1517c00) +#define ARM_GPIO2_BASE (ARM_IO_BASE + 0x1517c00) -#define ARM_GPIO2_DATA0 (ARM_GPIO2_BASE + 0x04) +#define ARM_GPIO2_DATA0 (ARM_GPIO2_BASE + 0x04) #define ARM_GPIO2_IODIR0 (ARM_GPIO2_BASE + 0x08) +// Power Manager +#define ARM_PM_BASE (ARM_IO_BASE + 0x1200000) + +#define ARM_PM_RSTC (ARM_PM_BASE + 0x1c) +#define ARM_PM_RSTS (ARM_PM_BASE + 0x20) +#define ARM_PM_WDOG (ARM_PM_BASE + 0x24) +#define ARM_PM_PADS0 (ARM_PM_BASE + 0x2c) +#define ARM_PM_PADS1 (ARM_PM_BASE + 0x30) +#define ARM_PM_PADS2 (ARM_PM_BASE + 0x34) + +#define ARM_PM_PASSWD (0x5a << 24) + #endif diff --git a/include/board.h b/include/board.h new file mode 100644 index 0000000..db8df69 --- /dev/null +++ b/include/board.h @@ -0,0 +1,8 @@ +#ifndef __GILBRALTAR_BOARD__ +#define __GILBRALTAR_BOARD__ + +#include + +uint32_t gilbraltar_get_board(void); + +#endif diff --git a/include/clock.h b/include/clock.h index b1c570a..17d5e96 100644 --- a/include/clock.h +++ b/include/clock.h @@ -1,6 +1,8 @@ #ifndef __GILBRALTAR_CLOCK__ #define __GILBRALTAR_CLOCK__ -uint32_t gilbraltar_get_clock(uint32_t); +#include + +uint32_t gilbraltar_get_rate_of_clock(uint32_t); #endif diff --git a/include/coherent_page.h b/include/coherent_page.h new file mode 100644 index 0000000..d8d4a60 --- /dev/null +++ b/include/coherent_page.h @@ -0,0 +1,12 @@ +#ifndef __GILBRALTAR_COHERENT_PAGE__ +#define __GILBRALTAR_COHERENT_PAGE__ + +#include +#include +#include + +enum coherent_page { PROP_MAILBOX = 0, GPIO_VIRTBUF }; + +uintptr_t get_coherent_page(enum coherent_page); + +#endif diff --git a/include/cpu_aarch64.h b/include/cpu_aarch64.h new file mode 100644 index 0000000..95479a5 --- /dev/null +++ b/include/cpu_aarch64.h @@ -0,0 +1,13 @@ +#ifndef __GILBRALTAR_CPU_AARCH64__ +#define __GILBRALTAR_CPU_AARCH64__ + +#include + +static inline uint64_t cpu_cntpct(void) { + uint64_t val; + + __asm__ __volatile("mrs %0, cntpct_el0" : "=r"(val)::); + return (val); +} + +#endif diff --git a/include/crt.h b/include/crt.h new file mode 100644 index 0000000..62c1da5 --- /dev/null +++ b/include/crt.h @@ -0,0 +1,11 @@ +#include + +extern uintptr_t SSP_GUARD_SYMBOL; + +#include +#define READ_CPU_TICKS cpu_cntpct + +__attribute__((always_inline)) static inline void crt_init_ssp(void) { + SSP_GUARD_SYMBOL = READ_CPU_TICKS() + (READ_CPU_TICKS() << 32UL); + SSP_GUARD_SYMBOL &= ~(uintptr_t)0xff00; +} diff --git a/include/dtb.h b/include/dtb.h new file mode 100644 index 0000000..d0a92c2 --- /dev/null +++ b/include/dtb.h @@ -0,0 +1,8 @@ +#ifndef __GILBRALTAR_DTB__ +#define __GILBRALTAR_DTB__ + +#include + +bool gilbraltar_dtb_init(void); + +#endif diff --git a/include/exception_handler.h b/include/exception_handler.h index 7fb4968..eeaca35 100644 --- a/include/exception_handler.h +++ b/include/exception_handler.h @@ -3,28 +3,15 @@ #include -struct frame { - uint32_t sp_irq; - uint32_t lr_irq; - uint32_t sp_fiq; - uint32_t lr_fiq; - uint32_t r0; - uint32_t r1; - uint32_t r2; - uint32_t r3; - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t r7; - uint32_t r8; - uint32_t r9; - uint32_t r10; - uint32_t r11; - uint32_t r12; - uint32_t sp; - uint32_t lr; - uint32_t spsr; - uint32_t pc; +struct __attribute__((packed)) frame { + uint64_t esr_el1; + uint64_t spsr_el1; + uint64_t x30; + uint64_t elr_el1; + uint64_t sp_el0; + uint64_t sp_el1; + uint64_t far_el1; + uint64_t unused; }; void gilbraltar_exception_handler(uint64_t, struct frame *); diff --git a/include/log.h b/include/log.h index 6829ac3..507362a 100644 --- a/include/log.h +++ b/include/log.h @@ -1,19 +1,14 @@ #ifndef __GILBRALTAR_LOG__ #define __GILBRALTAR_LOG__ -#include #include #include +#include -enum log_level { - ERROR= 0, - WARN, - INFO, - DEBUG -}; +enum log_level { ERROR = 0, WARN, INFO, DEBUG }; size_t gilbraltar_log(enum log_level, const char *fmt, ...) - __attribute__((format (printf, 2, 3))); + __attribute__((format(printf, 2, 3))); void gilbraltar_log_set(enum log_level); #endif diff --git a/include/mbox.h b/include/mbox.h index a984b88..89ee1af 100644 --- a/include/mbox.h +++ b/include/mbox.h @@ -4,15 +4,15 @@ #include #include -#define MAILBOX_BASE (ARM_IO_BASE + 0x13880) +#define MAILBOX_BASE (ARM_IO_BASE + 0x13880) -#define MAILBOX0_READ (MAILBOX_BASE + 0x00) +#define MAILBOX0_READ (MAILBOX_BASE + 0x00) #define MAILBOX0_STATUS (MAILBOX_BASE + 0x18) -#define MAILBOX1_WRITE (MAILBOX_BASE + 0x20) +#define MAILBOX1_WRITE (MAILBOX_BASE + 0x20) #define MAILBOX1_STATUS (MAILBOX_BASE + 0x38) #define MAILBOX_STATUS_EMPTY 0x40000000 -#define MAILBOX_STATUS_FULL 0x80000000 +#define MAILBOX_STATUS_FULL 0x80000000 #define BCM_MAILBOX_PROP_OUT 8 diff --git a/include/mem.h b/include/mem.h index 6f4d133..385445e 100644 --- a/include/mem.h +++ b/include/mem.h @@ -20,4 +20,8 @@ static inline void write32(uintptr_t addr, uint32_t v) { *(uint32_t volatile *)addr = v; } +#define data_sync_barrier() __asm__ __volatile("dsb sy" ::: "memory") +#define data_mem_barrier() __asm__ __volatile("dmb sy" ::: "memory") +#define instruction_sync_barrier() __asm__ __volatile("isb" ::: "memory") + #endif diff --git a/include/memory.h b/include/memory.h new file mode 100644 index 0000000..1aa4de4 --- /dev/null +++ b/include/memory.h @@ -0,0 +1,6 @@ +#ifndef __GILBRALTAR_MEMORY__ +#define __GILBRALTAR_MEMORY__ + +void gilbraltar_memory_init(void); + +#endif diff --git a/include/memory_map.h b/include/memory_map.h index 42770fc..4a7f858 100644 --- a/include/memory_map.h +++ b/include/memory_map.h @@ -13,19 +13,18 @@ #define GIGABYTE 0x40000000UL #endif -#define CORES 4 // must be a power of 2 -#define MEM_SIZE (512 * MEGABYTE) // default size -#define GPU_MEM_SIZE (64 * MEGABYTE) // set in config.txt -#define ARM_MEM_SIZE (MEM_SIZE - GPU_MEM_SIZE) // normally overwritten -#define PAGE_SIZE 0x10000 // page size used by us -#define PAGE_SHIFT 16 -#define PAGE_MASK ~(0xffff) +#define CORES 4 // must be a power of 2 +#define MEM_SIZE (512 * MEGABYTE) // default size +#define GPU_MEM_SIZE (64 * MEGABYTE) // set in config.txt +#define ARM_MEM_SIZE (MEM_SIZE - GPU_MEM_SIZE) // normally overwritten +#define PAGE_SIZE 0x10000LL // page size used by us +#define PAGE_SHIFT 16 #define EXCEPTION_STACK_SIZE 0x8000 -#define PAGE_RESERVE (16 * MEGABYTE) +#define PAGE_RESERVE (16 * MEGABYTE) // Kernel #define MEM_KERNEL_START 0x80000 // main code starts here -#define MEM_KERNEL_END (MEM_KERNEL_START + KERNEL_MAX_SIZE) +#define MEM_KERNEL_END (MEM_KERNEL_START + KERNEL_MAX_SIZE) #define MEM_KERNEL_STACK (MEM_KERNEL_END + KERNEL_STACK_SIZE) // expands down #define MEM_EXCEPTION_STACK \ @@ -38,20 +37,26 @@ ((MEM_EXCEPTION_STACK_END + 2 * MEGABYTE) & ~(MEGABYTE - 1)) // Heap -#define MEM_HEAP_START GIGABYTE -#define MEM_HEAP_END (8 * GIGABYTE - 1) +#define MEM_HEAP_START (MEM_COHERENT_REGION + 4 * MEGABYTE) // IRQ & FIC stacks #define MEM_ABORT_STACK (MEM_KERNEL_STACK + KERNEL_STACK_SIZE * (CORES - 1)) -#define MEM_IRQ_STACK (MEM_EXCEPTION_STACK_END + EXCEPTION_STACK_SIZE) +#define MEM_IRQ_STACK (MEM_EXCEPTION_STACK_END + EXCEPTION_STACK_SIZE) #define MEM_FIQ_STACK \ (MEM_IRQ_STACK + EXCEPTION_STACK_SIZE * (CORES - 1) + EXCEPTION_STACK_SIZE) // Page table -#define MEM_PAGE_TABLE1 \ - (MEM_FIQ_STACK + EXCEPTION_STACK_SIZE * (CORES - 1)) +#define MEM_PAGE_TABLE1 (MEM_FIQ_STACK + EXCEPTION_STACK_SIZE * (CORES - 1)) #define PAGE_TABLE1_SIZE 0x4000 -#define MEM_PAGE_TABLE1_END (MEM_PAGE_TABLE1 + PAGE_TABLE1_SIZE) +#define MEM_PAGE_TABLE1_END (MEM_PAGE_TABLE1 + PAGE_TABLE1_SIZE) + +// I/O memory regions of RaspBerry Pi 5 +#define MEM_IOMEM_AXI_START 0x1000000000UL // AXI peripherals +#define MEM_IOMEM_AXI_END 0x101fffffffUL +#define MEM_IOMEM_SOC_START 0x1060000000UL // SoC peripherals +#define MEM_IOMEM_SOC_END 0x107fffffffUL +#define MEM_IOMEM_PCIE_START 0x1f00000000UL // PCI Bus 0000:01 +#define MEM_IOMEM_PCIE_END 0x1f1fffffffUL #endif diff --git a/include/pager.h b/include/pager.h new file mode 100644 index 0000000..b0c3db3 --- /dev/null +++ b/include/pager.h @@ -0,0 +1,12 @@ +#ifndef __GILBRALTAR_PAGER__ +#define __GILBRALTAR_PAGER__ + +#include +#include + +void gilbraltar_pager_init(uintptr_t, size_t); +size_t gilbraltar_pager_free_space(void); +void *gilbraltar_palloc(void); +void gilbraltar_pager_free(void *); + +#endif diff --git a/include/power.h b/include/power.h new file mode 100644 index 0000000..008f95d --- /dev/null +++ b/include/power.h @@ -0,0 +1,7 @@ +#ifndef __GILBRALTAR_POWER__ +#define __GILBRALTAR_POWER__ + +void reboot(void); +void poweroff(void); + +#endif diff --git a/include/serial.h b/include/serial.h index 1292bfb..a44b1d3 100644 --- a/include/serial.h +++ b/include/serial.h @@ -2,22 +2,22 @@ #define __GILBRALTAR_SERIAL__ #include -#include #include +#include #define ARM_UART0_BASE (ARM_IO_BASE + 0x1001000) -#define ARM_UART0_DR (ARM_UART0_BASE + 0x00) -#define ARM_UART0_FR (ARM_UART0_BASE + 0x18) +#define ARM_UART0_DR (ARM_UART0_BASE + 0x00) +#define ARM_UART0_FR (ARM_UART0_BASE + 0x18) #define ARM_UART0_IBRD (ARM_UART0_BASE + 0x24) #define ARM_UART0_FBRD (ARM_UART0_BASE + 0x28) #define ARM_UART0_LCRH (ARM_UART0_BASE + 0x2c) -#define ARM_UART0_CR (ARM_UART0_BASE + 0x30) +#define ARM_UART0_CR (ARM_UART0_BASE + 0x30) #define ARM_UART0_IFLS (ARM_UART0_BASE + 0x34) #define ARM_UART0_IMSC (ARM_UART0_BASE + 0x38) -#define ARM_UART0_RIS (ARM_UART0_BASE + 0x3c) -#define ARM_UART0_MIS (ARM_UART0_BASE + 0x40) -#define ARM_UART0_ICR (ARM_UART0_BASE + 0x44) +#define ARM_UART0_RIS (ARM_UART0_BASE + 0x3c) +#define ARM_UART0_MIS (ARM_UART0_BASE + 0x40) +#define ARM_UART0_ICR (ARM_UART0_BASE + 0x44) void gilbraltar_serial_init(void); void gilbraltar_serial_send(uint8_t); diff --git a/include/spinlock.h b/include/spinlock.h new file mode 100644 index 0000000..c03e496 --- /dev/null +++ b/include/spinlock.h @@ -0,0 +1,11 @@ +#ifndef __GILBRALTAR_SPINLOCK__ +#define __GILBRALTAR_SPINLOCK__ + +#include +#include + +void gilbraltar_spinlock_init(void); +void gilbraltar_spinlock_acquire(enum level, uint32_t *); +void gilbraltar_spinlock_release(enum level, uint32_t *); + +#endif diff --git a/include/synchronize.h b/include/synchronize.h new file mode 100644 index 0000000..cc4cc2f --- /dev/null +++ b/include/synchronize.h @@ -0,0 +1,14 @@ +#ifndef __GILBRALTAR_SYNCHRONIZE__ +#define __GILBRALTAR_SYNCHRONIZE__ + +#define enable_fiqs() __asm__ __volatile("msr DAIFClr, #1") +#define disable_fiqs() __asm__ __volatile("msr DAIFSet, #1") +#define enable_irqs() __asm__ __volatile("msr DAIFClr, #2") +#define disable_irqs() __asm__ __volatile("msr DAIFSet, #2") + +enum level { TASK, IRQ, FIQ }; + +void gilbraltar_enter_critical(enum level); +void gilbraltar_leave_critical(void); + +#endif diff --git a/include/sysconfig.h b/include/sysconfig.h index de1d6e2..cc05513 100644 --- a/include/sysconfig.h +++ b/include/sysconfig.h @@ -8,7 +8,7 @@ * value. This value must be a multiple of 16 KByte. */ #ifndef KERNEL_MAX_SIZE -#define KERNEL_MAX_SIZE (6 * MEGABYTE) +#define KERNEL_MAX_SIZE (2 * MEGABYTE) #endif /* KERNEL_STACK_SIZE is the size of the stack set on startup for the main diff --git a/include/tag.h b/include/tag.h index bad0137..73e66cf 100644 --- a/include/tag.h +++ b/include/tag.h @@ -1,10 +1,16 @@ #ifndef __GILBRALTAR_TAG__ #define __GILBRALTAR_TAG__ -#define CODE_REQUEST 0x00000000 +#include +#include + +#define CODE_REQUEST 0x00000000 #define CODE_RESPONSE_SUCCESS 0x80000000 #define CODE_RESPONSE_FAILURE 0x80000001 -#define PROPTAG_END 0x00000000 +#define PROPTAG_END 0x00000000 + +bool gilbraltar_get_tags(void *, size_t); +bool gilbraltar_get_tag(uint32_t, void *, size_t, size_t); #endif diff --git a/include/translation_table.h b/include/translation_table.h new file mode 100644 index 0000000..df7c7ea --- /dev/null +++ b/include/translation_table.h @@ -0,0 +1,112 @@ +#ifndef __GILBRALTAR_TRANSITION_TABLE__ +#define __GILBRALTAR_TRANSITION_TABLE__ + +#include +#include + +#define ARMV8MMU_TABLE_ENTRIES 8192 + +// index into MAIR_EL1 register +#define ATTR_INDX_NORMAL 0 +#define ATTR_INDX_DEVICE 1 +#define ATTR_INDX_COHERENT 2 + +// Level 2 +struct __attribute__((packed)) TARMV8MMU_LEVEL2_TABLE_DESCRIPTOR { + uint64_t value11 : 2, // set to 3 + ignored1 : 14, // set to 0 + table_addr : 32, // table base [47:16] + reserved0 : 4, // set to 0 + ignored2 : 7, // set to 0 + pxn_table : 1, // set to 0 + uxn_table : 1, // set to 0 + ap_table : 2, +#define AP_TABLE_ALL_ACCESS 0 + ns_table : 1 // RES0, set to 0 + ; +}; + +#define ARMV8MMUL2TABLEADDR(addr) (((addr) >> 16) & 0xffffffff) +#define ARMV8MMUL2TABLEPTR(table) ((void *)((table) << 16)) + +struct __attribute__((packed)) TARMV8MMU_LEVEL2_BLOCK_DESCRIPTOR { + uint64_t value01 : 2, // set to 1 + // lower attributes : 10, + attr_indx : 3, // [2:0], see MAIR_EL1 + ns : 1, // RES0, set to 0 + ap : 2, // [2:1] +#define ATTR_IB_AP_RW_EL1 0 +#define ATTR_IB_AP_RW_ALL 1 +#define ATTR_IB_AP_RO_EL1 2 +#define ATTR_IB_AP_RO_ALL 3 + sh : 2, // [1:0] +#define ATTR_IB_SH_NON_SHAREABLE 0 +#define ATTR_IB_SH_OUTER_SHAREABLE 2 +#define ATTR_IB_SH_INNER_SHAREABLE 3 + af : 1, // set to 1, will fault otherwise + ng : 1, // set to 0 + reserved0_1 : 17, // set to 0 + output_addr : 19, // [47:29] + reserved0_2 : 4, // set to 0 + // upper attributes : 12 + continuous : 1, // set to 0 + pxn : 1, // set to 0, 1 for device memory + uxn : 1, // set to 1 + ignored : 9 // set to 0 + ; +}; + +#define ARMV8MMU_LEVEL2_BLOCK_SIZE (512 * MEGABYTE) +#define ARMV8MMUL2BLOCKADDR(addr) (((addr) >> 29) & 0x7ffff) +#define ARMV8MMUL2BLOCKPTR(block) ((void *)((table) << 29)) + +struct __attribute__((packed)) TARMV8MMU_LEVEL2_INVALID_DESCRIPTOR { + uint64_t value0 : 1, // set to 0 + ignored : 63; +}; + +union __attribute__((packed)) TARMV8MMU_LEVEL2_DESCRIPTOR { + struct TARMV8MMU_LEVEL2_TABLE_DESCRIPTOR table; + struct TARMV8MMU_LEVEL2_BLOCK_DESCRIPTOR block; + struct TARMV8MMU_LEVEL2_INVALID_DESCRIPTOR invalid; +}; + +// Level 3 +struct __attribute__((packed)) TARMV8MMU_LEVEL3_PAGE_DESCRIPTOR { + uint64_t value11 : 2, // set to 3 + // lower attributes : 10, + attr_indx : 3, // [2:0], see MAIR_EL1 + ns : 1, // RES0, set to 0 + ap : 2, // [2:1] + sh : 2, // [1:0] + af : 1, // set to 1, will fault otherwise + ng : 1, // set to 0 + reserved0_1 : 4, // set to 0 + output_addr : 32, // [47:16] + reserved0_2 : 4, // set to 0 + // upper attributes : 12 + continuous : 1, // set to 0 + pxn : 1, // set to 0, 1 for device memory + uxn : 1, // set to 1 + ignored : 9 // set to 0 + ; +}; + +#define ARMV8MMU_LEVEL3_PAGE_SIZE 0x10000 +#define ARMV8MMUL3PAGEADDR(addr) (((addr) >> 16) & 0xffffffff) +#define ARMV8MMUL3PAGEPTR(page) ((void *)((page) << 16)) + +struct __attribute__((packed)) TARMV8MMU_LEVEL3_INVALID_DESCRIPTOR { + uint64_t value0 : 1, // set to 0 + ignored : 63; +}; + +union __attribute__((packed)) TARMV8MMU_LEVEL3_DESCRIPTOR { + struct TARMV8MMU_LEVEL3_PAGE_DESCRIPTOR page; + struct TARMV8MMU_LEVEL3_INVALID_DESCRIPTOR invalid; +}; + +void gilbraltar_translation_table_init(size_t); +uintptr_t gilbraltar_translation_table_base(void); + +#endif diff --git a/interrupt_handler.c b/interrupt_handler.c index 4bc28c3..b196071 100644 --- a/interrupt_handler.c +++ b/interrupt_handler.c @@ -1,4 +1,8 @@ +#include + void gilbraltar_interrupt_handler(void) { + gilbraltar_log(DEBUG, "Interruption.\r\n"); + while (1) __asm__ __volatile("wfi"); } diff --git a/kernel.c b/kernel.c index 7bc35df..dde4a26 100644 --- a/kernel.c +++ b/kernel.c @@ -1,3 +1,78 @@ -extern void main(void); +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -void gilbraltar_sysinit(void) { main(); } +extern int main(int, char *const *); + +extern char __bss_start; +extern char _etext[]; +extern char _end[]; + +#define PROPTAG_GET_COMMAND_LINE 0x00050001 + +struct __attribute__((packed)) command_line { + uint32_t id; + uint32_t value_len; + uint32_t param_len; + uint8_t str[2048]; +}; + +static size_t split(char *src, char *dst[], size_t len) { + int i = 0; + char *rem = src; + + while (rem != NULL && *rem != '\0' && i < len) { + char *e = strstr(rem, " "); + dst[i++] = rem; + if (e != NULL) { + *e = '\0'; + while (*(++e) == ' ') + ; + } + rem = e; + } + + return (i); +} + +void gilbraltar_sysinit(void) { + enable_fiqs(); + enable_irqs(); + memset(&__bss_start, 0, (uintptr_t)_end - (uintptr_t)__bss_start); + crt_init_ssp(); + + gilbraltar_serial_init(); + gilbraltar_memory_init(); + + struct command_line p; + char *cmdline[64] = {NULL}; + size_t ac = 1; + cmdline[0] = "gilbraltar"; + + if (!gilbraltar_get_tag(PROPTAG_GET_COMMAND_LINE, &p, sizeof(p), 2048)) { + gilbraltar_log(ERROR, "Impossible to retrieve cmdline.txt.\r\n"); + ac = 1; + } else if (p.param_len >= sizeof(p.str)) { + gilbraltar_log(ERROR, "cmdline.txt too long.\r\n"); + ac = 1; + } else { + p.str[p.param_len] = '\0'; + ac = split((char *)p.str, cmdline + 1, 62); + } + + gilbraltar_dtb_init(); + + int ret = main(ac + 1, cmdline); + gilbraltar_log(DEBUG, "End of program: %3d.", ret); + + if (ret == 0) + poweroff(); +} diff --git a/log.c b/log.c index a9b4652..9e6cfb4 100644 --- a/log.c +++ b/log.c @@ -1,8 +1,8 @@ +#include #include #include -#include -static enum log_level actual_level = INFO; +static enum log_level actual_level = DEBUG; size_t gilbraltar_log(enum log_level level, const char *fmt, ...) { if (actual_level < level) @@ -27,6 +27,4 @@ size_t gilbraltar_log(enum log_level level, const char *fmt, ...) { } } -void gilbraltar_log_set(enum log_level level) { - actual_level = level; -} +void gilbraltar_log_set(enum log_level level) { actual_level = level; } diff --git a/mbox.c b/mbox.c index b425ca5..729d334 100644 --- a/mbox.c +++ b/mbox.c @@ -1,18 +1,23 @@ -#include +#include #include +#include uint32_t gilbraltar_mbox_write_read(uintptr_t dma) { + assert((dma & 3) == 0); // [dma] must be aligned to 32-bit + dma |= 0xc0000000U; - while (read32(MAILBOX1_STATUS) & MAILBOX_STATUS_FULL); + while (read32(MAILBOX1_STATUS) & MAILBOX_STATUS_FULL) + ; write32(MAILBOX1_WRITE, BCM_MAILBOX_PROP_OUT | dma); uint32_t result; do { - while (read32(MAILBOX0_STATUS) & MAILBOX_STATUS_EMPTY); + while (read32(MAILBOX0_STATUS) & MAILBOX_STATUS_EMPTY) + ; result = read32(MAILBOX0_READ); } while ((result & 0xf) != BCM_MAILBOX_PROP_OUT); - return (result & ~0xf); + return ((result & ~0xf) & 0x3fffffff); } diff --git a/memory.c b/memory.c new file mode 100644 index 0000000..64df9d6 --- /dev/null +++ b/memory.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include + +// System registers + +#define SCTLR_EL1_WXN (1 << 19) +#define SCTLR_EL1_I (1 << 12) +#define SCTLR_EL1_C (1 << 2) +#define SCTLR_EL1_A (1 << 1) +#define SCTLR_EL1_M (1 << 0) + +#define TCR_EL1_IPS__SHIFT 32 +#define TCR_EL1_IPS__MASK (7UL << 32) +#define TCR_EL1_IPS_4GB 0UL +#define TCR_EL1_IPS_64GB 1UL +#define TCR_EL1_IPS_1TB 2UL + +#define TCR_EL1_EPD1 (1 << 23) +#define TCR_EL1_A1 (1 << 22) + +#define TCR_EL1_TG0__SHIFT 14 +#define TCR_EL1_TG0__MASK (3 << 14) +#define TCR_EL1_TG0_64KB 1 + +#define TCR_EL1_SH0__SHIFT 12 +#define TCR_EL1_SH0__MASK (3 << 12) +#define TCR_EL1_SH0_INNER 3 + +#define TCR_EL1_ORGN0__SHIFT 10 +#define TCR_EL1_ORGN0__MASK (3 << 10) +#define TCR_EL1_ORGN0_WR_BACK_ALLOCATE 1 +#define TCR_EL1_ORGN0_WR_BACK 3 + +#define TCR_EL1_IRGN0__SHIFT 8 +#define TCR_EL1_IRGN0__MASK (3 << 8) +#define TCR_EL1_IRGN0_WR_BACK_ALLOCATE 1 +#define TCR_EL1_IRGN0_WR_BACK 3 + +#define TCR_EL1_EPD0 (1 << 7) + +#define TCR_EL1_T0SZ__SHIFT 0 +#define TCR_EL1_T0SZ__MASK (0x3f << 0) +#define TCR_EL1_T0SZ_4GB 32 +#define TCR_EL1_T0SZ_64GB 28 +#define TCR_EL1_T0SZ_128GB 27 + +static void enable_mmu(void) { + uint64_t mair_el1 = + 0xff << ATTR_INDX_NORMAL * + 8 // inner/outer write-back non-transient, allocating + | 0x04 << ATTR_INDX_DEVICE * 8 // Device-nGnRE + | 0x00 << ATTR_INDX_COHERENT * 8; // Device-nGnRnE + + __asm__ __volatile("msr mair_el1, %0" : : "r"(mair_el1)); + __asm__ __volatile("msr ttbr0_el1, %0" + : + : "r"(gilbraltar_translation_table_base())); + + uint64_t tcr_el1; + __asm__ __volatile("mrs %0, tcr_el1" : "=r"(tcr_el1)); + + tcr_el1 &= ~(TCR_EL1_IPS__MASK | TCR_EL1_A1 | TCR_EL1_TG0__MASK | + TCR_EL1_SH0__MASK | TCR_EL1_ORGN0__MASK | TCR_EL1_IRGN0__MASK | + TCR_EL1_EPD0 | TCR_EL1_T0SZ__MASK); + tcr_el1 |= TCR_EL1_EPD1 | TCR_EL1_TG0_64KB << TCR_EL1_TG0__SHIFT | + TCR_EL1_SH0_INNER << TCR_EL1_SH0__SHIFT | + TCR_EL1_ORGN0_WR_BACK_ALLOCATE << TCR_EL1_ORGN0__SHIFT | + TCR_EL1_IRGN0_WR_BACK_ALLOCATE << TCR_EL1_IRGN0__SHIFT | + TCR_EL1_IPS_1TB << TCR_EL1_IPS__SHIFT | + TCR_EL1_T0SZ_128GB << TCR_EL1_T0SZ__SHIFT; + + __asm__ __volatile("msr tcr_el1, %0" : : "r"(tcr_el1)); + + uint64_t sctlr_el1; + __asm__ __volatile("mrs %0, sctlr_el1" : "=r"(sctlr_el1)); + + sctlr_el1 &= ~(SCTLR_EL1_WXN | SCTLR_EL1_A); + sctlr_el1 |= SCTLR_EL1_I | SCTLR_EL1_C | SCTLR_EL1_M; + __asm__ __volatile("msr sctlr_el1, %0" : : "r"(sctlr_el1) : "memory"); +} + +void gilbraltar_memory_init(void) { + size_t rsv = ARM_MEM_SIZE - MEM_HEAP_START - PAGE_RESERVE; + + gilbraltar_pager_init(MEM_HEAP_START + rsv, PAGE_RESERVE); + gilbraltar_log(INFO, " pager @ 0x%08lx - 0x%08lx\r\n", + MEM_HEAP_START + rsv, MEM_HEAP_START + rsv + PAGE_RESERVE); + + gilbraltar_translation_table_init(ARM_MEM_SIZE); + enable_mmu(); + instruction_sync_barrier(); +} diff --git a/nolibc/assert.c b/nolibc/assert.c index ae89be3..10a3750 100644 --- a/nolibc/assert.c +++ b/nolibc/assert.c @@ -13,6 +13,6 @@ void _assert_fail(const char *file, const char *line, const char *e) puts(line); puts(": Assertion `"); puts(e); - puts("' failed\n"); + puts("' failed\r\n"); abort(); } diff --git a/nolibc/puts.c b/nolibc/puts.c index 98a5fb8..734b7e3 100644 --- a/nolibc/puts.c +++ b/nolibc/puts.c @@ -1,17 +1,17 @@ #include #include -extern void solo5_console_write(const char *, size_t); +extern void gilbraltar_serial_write(const char *, size_t); int puts(const char *s) { size_t len = strlen(s); - solo5_console_write(s, len); + gilbraltar_serial_write(s, len); return (int)(len); // We should never have a string length above MAX_INT, do we? } int putchar(int chr) { - solo5_console_write((char *) &chr, 1); + gilbraltar_serial_write((char *) &chr, 1); return (1); } diff --git a/openlibm/src/e_lgamma_r.c b/openlibm/src/e_lgamma_r.c index df3ae23..6f48412 100644 --- a/openlibm/src/e_lgamma_r.c +++ b/openlibm/src/e_lgamma_r.c @@ -201,6 +201,8 @@ static const double zero= 0.00000000000000000000e+00; return -y; } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" OLM_DLLEXPORT double __ieee754_lgamma_r(double x, int *signgamp) @@ -296,3 +298,5 @@ __ieee754_lgamma_r(double x, int *signgamp) if(hx<0) r = nadj - r; return r; } + +#pragma GCC diagnostic pop diff --git a/openlibm/src/e_lgammaf_r.c b/openlibm/src/e_lgammaf_r.c index 7446dfc..09c532f 100644 --- a/openlibm/src/e_lgammaf_r.c +++ b/openlibm/src/e_lgammaf_r.c @@ -134,6 +134,8 @@ static const float zero= 0.0000000000e+00; return -y; } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" OLM_DLLEXPORT float __ieee754_lgammaf_r(float x, int *signgamp) @@ -229,3 +231,5 @@ __ieee754_lgammaf_r(float x, int *signgamp) if(hx<0) r = nadj - r; return r; } + +#pragma GCC diagnostic pop diff --git a/pager.c b/pager.c new file mode 100644 index 0000000..86540da --- /dev/null +++ b/pager.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include + +#define FREE_PAGE_MAGIC 0x50474d43 +#define PAGE_MASK (PAGE_SIZE - 1) + +struct free_page { + uint32_t magic; + struct free_page *next; +}; + +static uint8_t *pager_next = 0; +static uint8_t *pager_limit = 0; +static struct free_page *free_list = 0; +static uint32_t spinlock = 0; + +void gilbraltar_pager_init(uintptr_t base, size_t size) { + pager_next = (uint8_t *)((base + PAGE_SIZE - 1) & ~PAGE_MASK); + pager_limit = (uint8_t *)((base + size) & ~PAGE_MASK); +} + +size_t gilbraltar_pager_free_space(void) { return (pager_limit - pager_next); } + +void *gilbraltar_palloc(void) { + assert(pager_next != 0); + gilbraltar_spinlock_acquire(IRQ, &spinlock); + gilbraltar_log(DEBUG, "Allocate a new page (actual: %08lx)\r\n", + (uintptr_t)pager_next); + struct free_page *free_page; + + if ((free_page = free_list) != 0) { + assert(free_page->magic == FREE_PAGE_MAGIC); + free_list = free_page->next; + free_page->magic = 0; + } else { + free_page = (struct free_page *)pager_next; + pager_next += PAGE_SIZE; + + if (pager_next > pager_limit) { + gilbraltar_spinlock_release(IRQ, &spinlock); + gilbraltar_log(ERROR, "Out of page.\r\n"); + abort(); + } + } + + gilbraltar_log(DEBUG, "New page @ %08lx.\r\n", (uintptr_t)free_page); + gilbraltar_spinlock_release(IRQ, &spinlock); + return (free_page); +} + +void gilbraltar_pager_free(void *page) { + struct free_page *free_page = (struct free_page *)page; + + gilbraltar_spinlock_acquire(IRQ, &spinlock); + free_page->magic = FREE_PAGE_MAGIC; + free_page->next = free_list; + free_list = free_page; + gilbraltar_spinlock_release(IRQ, &spinlock); +} diff --git a/power.c b/power.c new file mode 100644 index 0000000..033279b --- /dev/null +++ b/power.c @@ -0,0 +1,21 @@ +#include +#include + +#define PM_RSTC_WRCFG_FULL_RESET 0x20 + +void reboot(void) { + write32(ARM_PM_WDOG, ARM_PM_PASSWD | 1); + write32(ARM_PM_RSTC, ARM_PM_PASSWD | PM_RSTC_WRCFG_FULL_RESET); + + for (;;) + ; // wait for reset +} + +void poweroff(void) { + __asm__ __volatile("mov x0, %0\n" + "smc #0\n" ::"r"(0x84000008UL) // function code SYSTEM_OFF + ); + + for (;;) + ; +} diff --git a/printf.c b/printf.c index cebfe40..a738fb9 100644 --- a/printf.c +++ b/printf.c @@ -1,12 +1,11 @@ -#include #include +#include -int printf(const char *restrict fmt, ...) -{ - int ret; - va_list ap; - va_start(ap, fmt); - ret = vfprintf(stdout, fmt, ap); - va_end(ap); - return ret; +int printf(const char *restrict fmt, ...) { + int ret; + va_list ap; + va_start(ap, fmt); + ret = vfprintf(stdout, fmt, ap); + va_end(ap); + return ret; } diff --git a/serial.c b/serial.c index 4779588..5604665 100644 --- a/serial.c +++ b/serial.c @@ -1,12 +1,45 @@ -#include +#include #include #include +#include +#include +#include +#include +#include #define DEFAULT_BAUDRATE 115200 +#define SERIAL_BUF_SIZE 0x1000 +#define SERIAL_BUF_MASK (SERIAL_BUF_SIZE - 1) + +/* NOTE(dinosaure): [serial.c] is usable only **after** the initialization of + * the .bss section: + * memset (&__bss_start, 0, (uintptr_t) _end - (uintptr_t) __bss_start); + * + * TODO(dinosaure): we should probably initialize .bss in [startup.S] + */ +static bool initialized = false; +static uint8_t tx_buf[SERIAL_BUF_SIZE] = {0}; +static uint8_t tx_rd = 0; +static uint8_t tx_wr = 0; +// static uint32_t spinlock = 0; + +static void flush_tx_buf(void) { + assert(initialized); + + while (tx_rd != tx_wr) { + if (!(read32(ARM_UART0_FR) & 0x20)) { + write32(ARM_UART0_DR, tx_buf[tx_rd++]); + tx_rd &= SERIAL_BUF_MASK; + } + } +} void gilbraltar_serial_init(void) { + if (initialized) + return; + uint32_t baudrate = DEFAULT_BAUDRATE; - uint32_t clock_rate = gilbraltar_get_clock(2); + uint32_t clock_rate = gilbraltar_get_rate_of_clock(2); // UART clock uint32_t baud16 = baudrate * 16; uint32_t int_div = clock_rate / baud16; uint32_t fract_div_2 = (clock_rate % baud16) * 8 / baudrate; @@ -18,30 +51,46 @@ void gilbraltar_serial_init(void) { write32(ARM_UART0_FBRD, fract_div); write32(ARM_UART0_LCRH, (1 << 4) | (3 << 5)); write32(ARM_UART0_CR, (1 << 0) | (1 << 8) | (1 << 9)); + + initialized = true; + flush_tx_buf(); } void gilbraltar_serial_send(uint8_t chr) { - while (1) - if (!(read32(ARM_UART0_FR) & 0x20)) break; + if (initialized) { + while (1) + if (!(read32(ARM_UART0_FR) & 0x20)) + break; - write32(ARM_UART0_DR, chr); + write32(ARM_UART0_DR, chr); + } else { + // gilbraltar_spinlock_acquire(IRQ, &spinlock); + + if (((tx_wr + 1) & SERIAL_BUF_MASK) != tx_rd) { + tx_buf[tx_wr++] = chr; + tx_wr &= SERIAL_BUF_MASK; + } + + // gilbraltar_spinlock_release(IRQ, &spinlock); + } } uint8_t gilbraltar_serial_recv(void) { while (1) - if (!(read32(ARM_UART0_FR) & 0x10)) break; + if (!(read32(ARM_UART0_FR) & 0x10)) + break; return (read32(ARM_UART0_DR) & 0xff); } void gilbraltar_serial_puts(const char *str) { - while (*str) gilbraltar_serial_send(*str++); + while (*str) + gilbraltar_serial_send(*str++); } -void gilbraltar_serial_putchar(int chr) { - gilbraltar_serial_send(chr & 0xff); -} +void gilbraltar_serial_putchar(int chr) { gilbraltar_serial_send(chr & 0xff); } void gilbraltar_serial_write(const char *str, size_t len) { - while (len--) gilbraltar_serial_send(*str++); + while (len--) + gilbraltar_serial_send(*str++); } diff --git a/spinlock.c b/spinlock.c new file mode 100644 index 0000000..70a4d94 --- /dev/null +++ b/spinlock.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +static bool enabled = false; + +void gilbraltar_spinlock_init(void) { enabled = true; } + +void gilbraltar_spinlock_acquire(enum level level, uint32_t *s) { + if (level >= IRQ) + gilbraltar_enter_critical(level); + + if (enabled) { + gilbraltar_log(DEBUG, "Acquire %08lx.\r\n", (uintptr_t)s); + + __asm__ __volatile("mov x1, %0\n" + "mov w2, #1\n" + "prfm pstl1keep, [x1]\n" + "sevl\n" + "1: wfe\n" + "ldaxr w3, [x1]\n" + "cbnz w3, 1b\n" + "stxr w3, w2, [x1]\n" + "cbnz w3, 1b\n" + : + : "r"((uintptr_t)&s[0]) + : "x1", "x2", "x3"); + + gilbraltar_log(DEBUG, "%08lx acquired.\r\n", (uintptr_t)s); + } +} + +void gilbraltar_spinlock_release(enum level level, uint32_t *s) { + if (enabled) { + __asm__ __volatile("mov x1, %0\n" + "stlr wzr, [x1]\n" + : + : "r"((uintptr_t)&s[0]) + : "x1"); + } + + if (level >= IRQ) + gilbraltar_leave_critical(); +} diff --git a/synchronize.c b/synchronize.c new file mode 100644 index 0000000..10700ad --- /dev/null +++ b/synchronize.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include + +#define MAX_CRITICAL_LEVEL 20 + +static volatile unsigned int critical_level[CORES] = {0}; +static volatile uint64_t store[CORES][MAX_CRITICAL_LEVEL]; + +/* This function can be used to disable IRQ and/or FIQ interrupts for the + * current core. + */ +void gilbraltar_enter_critical(enum level level) { + assert(level == IRQ || level == FIQ); + uint64_t mpidr; + + __asm__ __volatile("mrs %0, mpidr_el1" : "=r"(mpidr)); + mpidr >>= 8; + + unsigned int core = mpidr & (CORES - 1); + uint64_t flags; + + __asm__ __volatile("mrs %0, daif" : "=r"(flags)); + // if we are already on FIQ, we must not go back to IRQ here + assert(level == FIQ || !(flags & 0x40)); + gilbraltar_log(DEBUG, "Disable IRQs and FIQs for %02x, flags:%08lx.\r\n", + core, flags); + __asm__ __volatile("msr DAIFSet, #3"); // disable both IRQ and FIQ + store[core][critical_level[core]++] = flags; + + // if we want the IRQ level, keep the FIQ level + if (level == IRQ) + enable_fiqs(); + + data_mem_barrier(); + gilbraltar_log(DEBUG, "Critical zone.\r\n"); +} + +void gilbraltar_leave_critical() { + uint64_t mpidr; + + __asm__ __volatile("mrs %0, mpidr_el1" : "=r"(mpidr)); + mpidr >>= 8; + + unsigned int core = mpidr & (CORES - 1); + data_mem_barrier(); + disable_fiqs(); + assert(critical_level[core] > 0); + uint64_t flags = store[core][--critical_level[core]]; + + gilbraltar_log(DEBUG, "Re-enable flags %08lx for %02x.\r\n", flags, core); + + // re-set old flags + __asm__ __volatile("msr daif, %0" ::"r"(flags)); +} diff --git a/tag.c b/tag.c new file mode 100644 index 0000000..9969487 --- /dev/null +++ b/tag.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct __attribute__((packed)) property_buf { + uint32_t size; + uint32_t code; + uint8_t tags[0]; +}; + +struct __attribute__((packed)) property_tag { + uint32_t id; + uint32_t value_len; + uint32_t param_len; +}; + +bool gilbraltar_get_tags(void *tags, size_t len) { + struct property_buf *buf = + (struct property_buf *)get_coherent_page(PROP_MAILBOX); + uintptr_t dma = (uintptr_t)buf; + uint32_t *top = (uint32_t *)(buf->tags + len); + + assert((((uintptr_t)buf) & (16 - 1)) == 0); + assert(len >= sizeof(struct property_tag) + sizeof(uint32_t)); + uint32_t size = sizeof(struct property_buf) + len + sizeof(uint32_t); + assert((size & 3) == 0); + + buf->size = size; + buf->code = CODE_REQUEST; + memcpy(buf->tags, tags, len); + *top = PROPTAG_END; + data_sync_barrier(); + + if (gilbraltar_mbox_write_read(dma) != dma) + return false; + + data_mem_barrier(); + + if (buf->code != CODE_RESPONSE_SUCCESS) + return false; + + memcpy(tags, buf->tags, len); + return true; +} + +#define VALUE_LENGTH_RESPONSE (1 << 31) + +bool gilbraltar_get_tag(uint32_t tag, void *buf, size_t len, size_t param_len) { + struct property_tag *hdr = buf; + hdr->id = tag; + hdr->value_len = len - sizeof(struct property_tag); + hdr->param_len = param_len & ~VALUE_LENGTH_RESPONSE; + + if (!gilbraltar_get_tags(buf, len)) + return false; + + hdr->param_len &= ~VALUE_LENGTH_RESPONSE; + + if (hdr->param_len == 0) + return false; + + return true; +} diff --git a/test03.map b/test03.map new file mode 100644 index 0000000..6ba0504 --- /dev/null +++ b/test03.map @@ -0,0 +1,574 @@ +Archive member included to satisfy reference by file (symbol) + +./libgilbraltar.a(log.o) test/test03.o (gilbraltar_log) +./libgilbraltar.a(startup.o) (_start) +./libgilbraltar.a(exception_stub.o) + ./libgilbraltar.a(startup.o) (VectorTable) +./libgilbraltar.a(kernel.o) ./libgilbraltar.a(startup.o) (gilbraltar_sysinit) +./libgilbraltar.a(interrupt_handler.o) + ./libgilbraltar.a(exception_stub.o) (gilbraltar_interrupt_handler) +./libgilbraltar.a(exception_handler.o) + ./libgilbraltar.a(exception_stub.o) (gilbraltar_exception_handler) +./libgilbraltar.a(crt.o) ./libgilbraltar.a(log.o) (__stack_chk_guard) +./libgilbraltar.a(serial.o) ./libgilbraltar.a(kernel.o) (gilbraltar_serial_init) +./libgilbraltar.a(power.o) ./libgilbraltar.a(kernel.o) (poweroff) +./libgilbraltar.a(tag.o) ./libgilbraltar.a(kernel.o) (gilbraltar_get_tag) +./libgilbraltar.a(coherent_page.o) + ./libgilbraltar.a(tag.o) (get_coherent_page) +./libgilbraltar.a(dtb.o) ./libgilbraltar.a(kernel.o) (gilbraltar_dtb_init) +./libgilbraltar.a(memory.o) ./libgilbraltar.a(kernel.o) (gilbraltar_memory_init) +./libgilbraltar.a(pager.o) ./libgilbraltar.a(memory.o) (gilbraltar_pager_init) +./libgilbraltar.a(translation_table.o) + ./libgilbraltar.a(memory.o) (gilbraltar_translation_table_base) +./libgilbraltar.a(mbox.o) ./libgilbraltar.a(tag.o) (gilbraltar_mbox_write_read) +./libgilbraltar.a(clock.o) ./libgilbraltar.a(serial.o) (gilbraltar_get_rate_of_clock) +./libgilbraltar.a(spinlock.o) + ./libgilbraltar.a(pager.o) (gilbraltar_spinlock_acquire) +./libgilbraltar.a(synchronize.o) + ./libgilbraltar.a(spinlock.o) (gilbraltar_enter_critical) +nolibc/libnolibc.a(assert.o) ./libgilbraltar.a(serial.o) (_assert_fail) +nolibc/libnolibc.a(memcpy.o) ./libgilbraltar.a(tag.o) (memcpy) +nolibc/libnolibc.a(memset.o) ./libgilbraltar.a(kernel.o) (memset) +nolibc/libnolibc.a(strstr.o) ./libgilbraltar.a(kernel.o) (strstr) +nolibc/libnolibc.a(puts.o) nolibc/libnolibc.a(assert.o) (puts) +nolibc/libnolibc.a(vsnprintf.o) + ./libgilbraltar.a(log.o) (vsnprintf) +nolibc/libnolibc.a(sysdeps.o) + ./libgilbraltar.a(coherent_page.o) (abort) +nolibc/libnolibc.a(memchr.o) nolibc/libnolibc.a(strstr.o) (memchr) +nolibc/libnolibc.a(memcmp.o) nolibc/libnolibc.a(strstr.o) (memcmp) +nolibc/libnolibc.a(strlen.o) nolibc/libnolibc.a(puts.o) (strlen) +nolibc/libnolibc.a(strchr.o) nolibc/libnolibc.a(strstr.o) (strchr) +nolibc/libnolibc.a(strchrnul.o) + nolibc/libnolibc.a(strchr.o) (__strchrnul) +nolibc/libnolibc.a(vfprintf.o) + nolibc/libnolibc.a(vsnprintf.o) (vfprintf) +nolibc/libnolibc.a(ctype.o) nolibc/libnolibc.a(vfprintf.o) (isdigit) +nolibc/libnolibc.a(stubs.o) nolibc/libnolibc.a(vfprintf.o) (strerror) +nolibc/libnolibc.a(printf.o) nolibc/libnolibc.a(stubs.o) (printf) +openlibm/libopenlibm.a(s_frexp.c.o) + nolibc/libnolibc.a(vfprintf.o) (frexp) +openlibm/libopenlibm.a(s_isfinite.c.o) + nolibc/libnolibc.a(vfprintf.o) (__isfinite) +openlibm/libopenlibm.a(s_signbit.c.o) + nolibc/libnolibc.a(vfprintf.o) (__signbit) +/usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + nolibc/libnolibc.a(vfprintf.o) (__extenddftf2) +/usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + nolibc/libnolibc.a(vfprintf.o) (__trunctfdf2) +/usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) (__sfp_handle_exceptions) + +There are no discarded input sections + +Memory Configuration + +Name Origin Length Attributes +*default* 0x0000000000000000 0xffffffffffffffff + +Linker script and memory map + +LOAD test/test03.o +Address of section .init set to 0x80000 +START GROUP +LOAD ./libgilbraltar.a +LOAD nolibc/libnolibc.a +LOAD openlibm/libopenlibm.a +LOAD /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a +END GROUP + +.init 0x0000000000080000 0xa8 + *(.init) + .init 0x0000000000080000 0xa8 ./libgilbraltar.a(startup.o) + 0x0000000000080000 _start + +.text 0x0000000000080800 0x7960 + *(.text*) + .text 0x0000000000080800 0x7c test/test03.o + 0x0000000000080800 main + .text 0x000000000008087c 0x1b0 ./libgilbraltar.a(log.o) + 0x000000000008087c gilbraltar_log + 0x0000000000080a08 gilbraltar_log_set + .text 0x0000000000080a2c 0x0 ./libgilbraltar.a(startup.o) + *fill* 0x0000000000080a2c 0x5d4 + .text 0x0000000000081000 0x9d8 ./libgilbraltar.a(exception_stub.o) + 0x0000000000081000 VectorTable + 0x0000000000081784 unexpected_stub + 0x00000000000817bc synchronous_stub + 0x00000000000817f4 system_error_stub + 0x000000000008182c IRQ_stub + 0x00000000000818dc FIQ_stub + 0x0000000000081988 SMC_stub + .text 0x00000000000819d8 0x2dc ./libgilbraltar.a(kernel.o) + 0x0000000000081ac0 gilbraltar_sysinit + .text 0x0000000000081cb4 0x28 ./libgilbraltar.a(interrupt_handler.o) + 0x0000000000081cb4 gilbraltar_interrupt_handler + 0x0000000000081cd4 gilbraltar_secure_monitor_handler + .text 0x0000000000081cdc 0x400 ./libgilbraltar.a(exception_handler.o) + 0x0000000000081cdc gilbraltar_exception_handler + .text 0x00000000000820dc 0x1c ./libgilbraltar.a(crt.o) + 0x00000000000820dc __stack_chk_fail + .text 0x00000000000820f8 0x440 ./libgilbraltar.a(serial.o) + 0x0000000000082224 gilbraltar_serial_init + 0x0000000000082354 gilbraltar_serial_send + 0x000000000008243c gilbraltar_serial_recv + 0x0000000000082484 gilbraltar_serial_puts + 0x00000000000824c8 gilbraltar_serial_putchar + 0x00000000000824ec gilbraltar_serial_write + .text 0x0000000000082538 0x7c ./libgilbraltar.a(power.o) + 0x000000000008255c reboot + 0x000000000008259c poweroff + .text 0x00000000000825b4 0x5ac ./libgilbraltar.a(tag.o) + 0x00000000000825b4 gilbraltar_get_tags + 0x0000000000082810 gilbraltar_get_tag + .text 0x0000000000082b60 0x44 ./libgilbraltar.a(coherent_page.o) + 0x0000000000082b60 get_coherent_page + .text 0x0000000000082ba4 0x20c ./libgilbraltar.a(dtb.o) + 0x0000000000082ba4 gilbraltar_dtb_init + .text 0x0000000000082db0 0x104 ./libgilbraltar.a(memory.o) + 0x0000000000082e50 gilbraltar_memory_init + .text 0x0000000000082eb4 0x268 ./libgilbraltar.a(pager.o) + 0x0000000000082eb4 gilbraltar_pager_init + 0x0000000000082f0c gilbraltar_pager_free_space + 0x0000000000082f2c gilbraltar_palloc + 0x00000000000830a8 gilbraltar_pager_free + .text 0x000000000008311c 0x554 ./libgilbraltar.a(translation_table.o) + 0x00000000000833d8 gilbraltar_translation_table_base + 0x00000000000833e8 gilbraltar_translation_table_init + .text 0x0000000000083670 0x10c ./libgilbraltar.a(mbox.o) + 0x00000000000836ac gilbraltar_mbox_write_read + .text 0x000000000008377c 0x184 ./libgilbraltar.a(clock.o) + 0x000000000008377c gilbraltar_get_rate_of_clock + .text 0x0000000000083900 0x108 ./libgilbraltar.a(spinlock.o) + 0x0000000000083900 gilbraltar_spinlock_init + 0x0000000000083918 gilbraltar_spinlock_acquire + 0x00000000000839b8 gilbraltar_spinlock_release + .text 0x0000000000083a08 0x21c ./libgilbraltar.a(synchronize.o) + 0x0000000000083a08 gilbraltar_enter_critical + 0x0000000000083b44 gilbraltar_leave_critical + *fill* 0x0000000000083c24 0x1c + .text 0x0000000000083c40 0x50 nolibc/libnolibc.a(assert.o) + 0x0000000000083c40 _assert_fail + *fill* 0x0000000000083c90 0x10 + .text 0x0000000000083ca0 0x3e0 nolibc/libnolibc.a(memcpy.o) + 0x0000000000083ca0 memcpy + .text 0x0000000000084080 0xe0 nolibc/libnolibc.a(memset.o) + 0x0000000000084080 memset + .text 0x0000000000084160 0x584 nolibc/libnolibc.a(strstr.o) + 0x0000000000084520 strstr + *fill* 0x00000000000846e4 0x1c + .text 0x0000000000084700 0x64 nolibc/libnolibc.a(puts.o) + 0x0000000000084700 puts + 0x0000000000084740 putchar + *fill* 0x0000000000084764 0x1c + .text 0x0000000000084780 0x14c nolibc/libnolibc.a(vsnprintf.o) + 0x00000000000847d0 vsnprintf + *fill* 0x00000000000848cc 0x14 + .text 0x00000000000848e0 0xbc nolibc/libnolibc.a(sysdeps.o) + 0x000000000008490c write + 0x0000000000084960 exit + 0x0000000000084968 abort + 0x0000000000084988 __getauxval + *fill* 0x000000000008499c 0x4 + .text 0x00000000000849a0 0xbc nolibc/libnolibc.a(memchr.o) + 0x00000000000849a0 memchr + *fill* 0x0000000000084a5c 0x4 + .text 0x0000000000084a60 0x38 nolibc/libnolibc.a(memcmp.o) + 0x0000000000084a60 memcmp + *fill* 0x0000000000084a98 0x8 + .text 0x0000000000084aa0 0x78 nolibc/libnolibc.a(strlen.o) + 0x0000000000084aa0 strlen + *fill* 0x0000000000084b18 0x8 + .text 0x0000000000084b20 0x2c nolibc/libnolibc.a(strchr.o) + 0x0000000000084b20 strchr + *fill* 0x0000000000084b4c 0x14 + .text 0x0000000000084b60 0xd8 nolibc/libnolibc.a(strchrnul.o) + 0x0000000000084b60 __strchrnul + *fill* 0x0000000000084c38 0x8 + .text 0x0000000000084c40 0x1e38 nolibc/libnolibc.a(vfprintf.o) + 0x0000000000084f88 printf_core + 0x00000000000869c8 vfprintf + *fill* 0x0000000000086a78 0x8 + .text 0x0000000000086a80 0x70 nolibc/libnolibc.a(ctype.o) + 0x0000000000086a80 isalpha + 0x0000000000086aa0 isdigit + 0x0000000000086ab0 isprint + 0x0000000000086ac0 isspace + 0x0000000000086ae0 isupper + *fill* 0x0000000000086af0 0x10 + .text 0x0000000000086b00 0xec0 nolibc/libnolibc.a(stubs.o) + 0x0000000000086b00 fflush + 0x0000000000086b6c rename + 0x0000000000086b8c sscanf + 0x0000000000086bac fread + 0x0000000000086c20 getc + 0x0000000000086c90 ungetc + 0x0000000000086d00 fwrite + 0x0000000000086d70 fputc + 0x0000000000086de0 fputs + 0x0000000000086e50 putc + 0x0000000000086ec0 ferror + 0x0000000000086f30 fopen + 0x0000000000086fa0 fclose + 0x0000000000087010 getenv + 0x0000000000087080 secure_getenv + 0x00000000000870f0 system + 0x0000000000087110 chdir + 0x0000000000087180 close + 0x00000000000871a0 getcwd + 0x00000000000871c0 getpid + 0x0000000000087230 getppid + 0x00000000000872a0 isatty + 0x00000000000872c0 lseek + 0x00000000000872e0 read + 0x0000000000087300 readlink + 0x0000000000087320 unlink + 0x0000000000087340 rmdir + 0x0000000000087360 ftruncate + 0x0000000000087380 execv + 0x00000000000873a0 closedir + 0x0000000000087410 opendir + 0x0000000000087480 readdir + 0x00000000000874f0 fcntl + 0x0000000000087510 open + 0x0000000000087580 setjmp + 0x00000000000875a0 signal + 0x00000000000875c0 raise + 0x00000000000875e0 strerror + 0x0000000000087600 stat + 0x0000000000087670 mkdir + 0x0000000000087690 pthread_join + 0x00000000000876a4 pthread_create + 0x00000000000876c0 pthread_attr_init + 0x00000000000876e0 pthread_cleanup_push + 0x0000000000087700 pthread_cleanup_pop + 0x0000000000087720 pthread_mutex_lock + 0x0000000000087740 pthread_mutex_trylock + 0x0000000000087760 pthread_mutex_unlock + 0x0000000000087780 pthread_mutex_destroy + 0x00000000000877a0 pthread_mutex_init + 0x00000000000877c0 pthread_mutexattr_init + 0x00000000000877e0 pthread_mutexattr_destroy + 0x0000000000087800 pthread_mutexattr_settype + 0x0000000000087820 pthread_sigmask + 0x0000000000087840 pthread_equal + 0x0000000000087860 pthread_condattr_init + 0x0000000000087880 pthread_cond_init + 0x00000000000878a0 pthread_cond_destroy + 0x00000000000878c0 pthread_cond_wait + 0x00000000000878e0 pthread_cond_signal + 0x0000000000087900 pthread_cond_broadcast + 0x0000000000087920 pthread_self + 0x0000000000087940 pthread_detach + 0x0000000000087960 sigfillset + 0x0000000000087980 sigwait + 0x00000000000879a0 usleep + .text 0x00000000000879c0 0xbc nolibc/libnolibc.a(printf.o) + 0x00000000000879c0 printf + *fill* 0x0000000000087a7c 0x4 + .text 0x0000000000087a80 0x78 openlibm/libopenlibm.a(s_frexp.c.o) + 0x0000000000087a80 frexp + *fill* 0x0000000000087af8 0x8 + .text 0x0000000000087b00 0x64 openlibm/libopenlibm.a(s_isfinite.c.o) + 0x0000000000087b00 __isfinite + 0x0000000000087b20 __isfinitef + 0x0000000000087b40 __isfinitel + *fill* 0x0000000000087b64 0x1c + .text 0x0000000000087b80 0x38 openlibm/libopenlibm.a(s_signbit.c.o) + 0x0000000000087b80 __signbit + 0x0000000000087b8c __signbitf + 0x0000000000087ba0 __signbitl + .text 0x0000000000087bb8 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + *fill* 0x0000000000087bb8 0x8 + .text.__extenddftf2 + 0x0000000000087bc0 0x158 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + 0x0000000000087bc0 __extenddftf2 + .text 0x0000000000087d18 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + *fill* 0x0000000000087d18 0x8 + .text.__trunctfdf2 + 0x0000000000087d20 0x3c4 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + 0x0000000000087d20 __trunctfdf2 + .text 0x00000000000880e4 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + *fill* 0x00000000000880e4 0xc + .text.__sfp_handle_exceptions + 0x00000000000880f0 0x70 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + 0x00000000000880f0 __sfp_handle_exceptions + 0x0000000000088160 _etext = . + +.iplt 0x0000000000088160 0x0 + .iplt 0x0000000000088160 0x0 test/test03.o + +.rodata 0x0000000000088160 0xa40 + *(.rodata*) + .rodata 0x0000000000088160 0x22 test/test03.o + *fill* 0x0000000000088182 0x6 + .rodata 0x0000000000088188 0x6d ./libgilbraltar.a(kernel.o) + *fill* 0x00000000000881f5 0x3 + .rodata 0x00000000000881f8 0x10 ./libgilbraltar.a(interrupt_handler.o) + .rodata 0x0000000000088208 0x97 ./libgilbraltar.a(exception_handler.o) + *fill* 0x000000000008829f 0x1 + .rodata 0x00000000000882a0 0x23 ./libgilbraltar.a(crt.o) + *fill* 0x00000000000882c3 0x5 + .rodata 0x00000000000882c8 0x21 ./libgilbraltar.a(serial.o) + *fill* 0x00000000000882e9 0x7 + .rodata 0x00000000000882f0 0x8b ./libgilbraltar.a(tag.o) + *fill* 0x000000000008837b 0x5 + .rodata 0x0000000000088380 0x4b ./libgilbraltar.a(dtb.o) + *fill* 0x00000000000883cb 0x5 + .rodata 0x00000000000883d0 0x26 ./libgilbraltar.a(memory.o) + *fill* 0x00000000000883f6 0x2 + .rodata 0x00000000000883f8 0x9c ./libgilbraltar.a(pager.o) + *fill* 0x0000000000088494 0x4 + .rodata 0x0000000000088498 0x28 ./libgilbraltar.a(translation_table.o) + .rodata 0x00000000000884c0 0x1f ./libgilbraltar.a(mbox.o) + *fill* 0x00000000000884df 0x1 + .rodata 0x00000000000884e0 0x9b ./libgilbraltar.a(clock.o) + *fill* 0x000000000008857b 0x5 + .rodata 0x0000000000088580 0x2a ./libgilbraltar.a(spinlock.o) + *fill* 0x00000000000885aa 0x6 + .rodata 0x00000000000885b0 0xf2 ./libgilbraltar.a(synchronize.o) + *fill* 0x00000000000886a2 0x6 + .rodata.str1.8 + 0x00000000000886a8 0x297 nolibc/libnolibc.a(assert.o) + 0x23 (size before relaxing) + .rodata.str1.8 + 0x000000000008893f 0xa nolibc/libnolibc.a(sysdeps.o) + *fill* 0x000000000008893f 0x1 + .rodata 0x0000000000088940 0x260 nolibc/libnolibc.a(vfprintf.o) + .rodata.str1.8 + 0x0000000000088ba0 0x52 nolibc/libnolibc.a(vfprintf.o) + .rodata.str1.8 + 0x0000000000088ba0 0x207 nolibc/libnolibc.a(stubs.o) + +.rela.dyn 0x0000000000088ba0 0x0 + .rela.iplt 0x0000000000088ba0 0x0 test/test03.o + .rela.text 0x0000000000088ba0 0x0 test/test03.o + +.ARM.exidx 0x0000000000088ba0 0x0 + 0x0000000000088ba0 __exidx_start = . + *(.ARM.exidx*) + 0x0000000000088ba0 __exidx_end = . + +.eh_frame + *(.eh_frame*) + +.data 0x0000000000088ba0 0xc4 + *(.data*) + .data 0x0000000000088ba0 0x0 test/test03.o + .data 0x0000000000088ba0 0x4 ./libgilbraltar.a(log.o) + .data 0x0000000000088ba4 0x0 ./libgilbraltar.a(startup.o) + *fill* 0x0000000000088ba4 0x4 + .data 0x0000000000088ba8 0x20 ./libgilbraltar.a(exception_stub.o) + 0x0000000000088ba8 FIQ_data + 0x0000000000088bc0 IRQ_return_address + .data 0x0000000000088bc8 0x0 ./libgilbraltar.a(kernel.o) + .data 0x0000000000088bc8 0x0 ./libgilbraltar.a(interrupt_handler.o) + .data 0x0000000000088bc8 0x18 ./libgilbraltar.a(exception_handler.o) + .data 0x0000000000088be0 0x8 ./libgilbraltar.a(crt.o) + 0x0000000000088be0 __stack_chk_guard + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(serial.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(power.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(tag.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(coherent_page.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(dtb.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(memory.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(pager.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(translation_table.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(mbox.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(clock.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(spinlock.o) + .data 0x0000000000088be8 0x0 ./libgilbraltar.a(synchronize.o) + .data 0x0000000000088be8 0x0 nolibc/libnolibc.a(assert.o) + .data 0x0000000000088be8 0x0 nolibc/libnolibc.a(memcpy.o) + .data 0x0000000000088be8 0x0 nolibc/libnolibc.a(memset.o) + .data 0x0000000000088be8 0x0 nolibc/libnolibc.a(strstr.o) + .data 0x0000000000088be8 0x0 nolibc/libnolibc.a(puts.o) + .data 0x0000000000088be8 0x0 nolibc/libnolibc.a(vsnprintf.o) + .data 0x0000000000088be8 0x28 nolibc/libnolibc.a(sysdeps.o) + 0x0000000000088be8 stdout + 0x0000000000088bf0 stderr + .data 0x0000000000088c10 0x0 nolibc/libnolibc.a(memchr.o) + .data 0x0000000000088c10 0x0 nolibc/libnolibc.a(memcmp.o) + .data 0x0000000000088c10 0x0 nolibc/libnolibc.a(strlen.o) + .data 0x0000000000088c10 0x0 nolibc/libnolibc.a(strchr.o) + .data 0x0000000000088c10 0x0 nolibc/libnolibc.a(strchrnul.o) + .data 0x0000000000088c10 0x0 nolibc/libnolibc.a(vfprintf.o) + .data 0x0000000000088c10 0x0 nolibc/libnolibc.a(ctype.o) + .data 0x0000000000088c10 0x54 nolibc/libnolibc.a(stubs.o) + .data 0x0000000000088c64 0x0 nolibc/libnolibc.a(printf.o) + .data 0x0000000000088c64 0x0 openlibm/libopenlibm.a(s_frexp.c.o) + .data 0x0000000000088c64 0x0 openlibm/libopenlibm.a(s_isfinite.c.o) + .data 0x0000000000088c64 0x0 openlibm/libopenlibm.a(s_signbit.c.o) + .data 0x0000000000088c64 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .data 0x0000000000088c64 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .data 0x0000000000088c64 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.igot.plt 0x0000000000088c68 0x0 + .igot.plt 0x0000000000088c68 0x0 test/test03.o + +.tdata 0x0000000000088c64 0x0 + 0x0000000000088c64 _stdata = . + *(.tdata) + 0x0000000000088c64 _edata = . + +.tbss + *(.tbss) + +.bss 0x0000000000088c70 0x1364 + 0x0000000000088c70 __bss_start = . + *(.bss*) + .bss 0x0000000000088c70 0x0 test/test03.o + .bss 0x0000000000088c70 0x0 ./libgilbraltar.a(log.o) + .bss 0x0000000000088c70 0x0 ./libgilbraltar.a(startup.o) + .bss 0x0000000000088c70 0x80 ./libgilbraltar.a(exception_stub.o) + .bss 0x0000000000088cf0 0x0 ./libgilbraltar.a(kernel.o) + .bss 0x0000000000088cf0 0x0 ./libgilbraltar.a(interrupt_handler.o) + .bss 0x0000000000088cf0 0x0 ./libgilbraltar.a(exception_handler.o) + .bss 0x0000000000088cf0 0x0 ./libgilbraltar.a(crt.o) + .bss 0x0000000000088cf0 0x100a ./libgilbraltar.a(serial.o) + .bss 0x0000000000089cfa 0x0 ./libgilbraltar.a(power.o) + .bss 0x0000000000089cfa 0x0 ./libgilbraltar.a(tag.o) + .bss 0x0000000000089cfa 0x0 ./libgilbraltar.a(coherent_page.o) + *fill* 0x0000000000089cfa 0x6 + .bss 0x0000000000089d00 0x8 ./libgilbraltar.a(dtb.o) + .bss 0x0000000000089d08 0x0 ./libgilbraltar.a(memory.o) + .bss 0x0000000000089d08 0x1c ./libgilbraltar.a(pager.o) + *fill* 0x0000000000089d24 0x4 + .bss 0x0000000000089d28 0x10 ./libgilbraltar.a(translation_table.o) + .bss 0x0000000000089d38 0x0 ./libgilbraltar.a(mbox.o) + .bss 0x0000000000089d38 0x0 ./libgilbraltar.a(clock.o) + .bss 0x0000000000089d38 0x1 ./libgilbraltar.a(spinlock.o) + *fill* 0x0000000000089d39 0x7 + .bss 0x0000000000089d40 0x290 ./libgilbraltar.a(synchronize.o) + .bss 0x0000000000089fd0 0x0 nolibc/libnolibc.a(assert.o) + .bss 0x0000000000089fd0 0x0 nolibc/libnolibc.a(memcpy.o) + .bss 0x0000000000089fd0 0x0 nolibc/libnolibc.a(memset.o) + .bss 0x0000000000089fd0 0x0 nolibc/libnolibc.a(strstr.o) + .bss 0x0000000000089fd0 0x0 nolibc/libnolibc.a(puts.o) + .bss 0x0000000000089fd0 0x0 nolibc/libnolibc.a(vsnprintf.o) + .bss 0x0000000000089fd0 0x4 nolibc/libnolibc.a(sysdeps.o) + 0x0000000000089fd0 errno + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(memchr.o) + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(memcmp.o) + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(strlen.o) + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(strchr.o) + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(strchrnul.o) + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(vfprintf.o) + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(ctype.o) + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(stubs.o) + .bss 0x0000000000089fd4 0x0 nolibc/libnolibc.a(printf.o) + .bss 0x0000000000089fd4 0x0 openlibm/libopenlibm.a(s_frexp.c.o) + .bss 0x0000000000089fd4 0x0 openlibm/libopenlibm.a(s_isfinite.c.o) + .bss 0x0000000000089fd4 0x0 openlibm/libopenlibm.a(s_signbit.c.o) + .bss 0x0000000000089fd4 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .bss 0x0000000000089fd4 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .bss 0x0000000000089fd4 0x0 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + *(COMMON) + 0x0000000000089fd4 _end = . +OUTPUT(test03.elf elf64-littleaarch64) +LOAD linker stubs + +.comment 0x0000000000000000 0x45 + .comment 0x0000000000000000 0x45 test/test03.o + 0x46 (size before relaxing) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(log.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(kernel.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(interrupt_handler.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(exception_handler.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(crt.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(serial.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(power.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(tag.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(coherent_page.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(dtb.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(memory.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(pager.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(translation_table.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(mbox.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(clock.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(spinlock.o) + .comment 0x0000000000000045 0x46 ./libgilbraltar.a(synchronize.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(assert.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(memcpy.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(memset.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(strstr.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(puts.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(vsnprintf.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(sysdeps.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(memchr.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(memcmp.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(strlen.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(strchr.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(strchrnul.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(vfprintf.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(ctype.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(stubs.o) + .comment 0x0000000000000045 0x46 nolibc/libnolibc.a(printf.o) + .comment 0x0000000000000045 0x46 openlibm/libopenlibm.a(s_frexp.c.o) + .comment 0x0000000000000045 0x46 openlibm/libopenlibm.a(s_isfinite.c.o) + .comment 0x0000000000000045 0x46 openlibm/libopenlibm.a(s_signbit.c.o) + .comment 0x0000000000000045 0x46 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .comment 0x0000000000000045 0x46 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .comment 0x0000000000000045 0x46 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_info 0x0000000000000000 0x76a + .debug_info 0x0000000000000000 0x2ef /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .debug_info 0x00000000000002ef 0x39e /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_info 0x000000000000068d 0xdd /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_abbrev 0x0000000000000000 0x35e + .debug_abbrev 0x0000000000000000 0x159 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .debug_abbrev 0x0000000000000159 0x183 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_abbrev 0x00000000000002dc 0x82 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_loclists + 0x0000000000000000 0xacb + .debug_loclists + 0x0000000000000000 0x451 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .debug_loclists + 0x0000000000000451 0x653 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_loclists + 0x0000000000000aa4 0x27 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_aranges 0x0000000000000000 0x90 + .debug_aranges + 0x0000000000000000 0x30 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .debug_aranges + 0x0000000000000030 0x30 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_aranges + 0x0000000000000060 0x30 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_rnglists + 0x0000000000000000 0x1d6 + .debug_rnglists + 0x0000000000000000 0x84 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .debug_rnglists + 0x0000000000000084 0x13b /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_rnglists + 0x00000000000001bf 0x17 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_line 0x0000000000000000 0xb07 + .debug_line 0x0000000000000000 0x276 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .debug_line 0x0000000000000276 0x7f9 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_line 0x0000000000000a6f 0x98 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_str 0x0000000000000000 0x294 + .debug_str 0x0000000000000000 0x294 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + 0x1f3 (size before relaxing) + .debug_str 0x0000000000000294 0x252 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_str 0x0000000000000294 0x11c /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_line_str + 0x0000000000000000 0x213 + .debug_line_str + 0x0000000000000000 0x213 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + 0x19c (size before relaxing) + .debug_line_str + 0x0000000000000213 0x199 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_line_str + 0x0000000000000213 0x193 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) + +.debug_frame 0x0000000000000000 0xb0 + .debug_frame 0x0000000000000000 0x38 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(extenddftf2.o) + .debug_frame 0x0000000000000038 0x50 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(trunctfdf2.o) + .debug_frame 0x0000000000000088 0x28 /usr/bin/../lib/gcc/aarch64-none-elf/13.3.1/libgcc.a(sfp-exceptions.o) diff --git a/translation_table.c b/translation_table.c new file mode 100644 index 0000000..d09c0dd --- /dev/null +++ b/translation_table.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include + +#define LEVEL2_TABLE_ENTRIES 256 + +static union TARMV8MMU_LEVEL2_DESCRIPTOR *l2_table; +static size_t mem = 0; +extern uint8_t _etext; + +static union TARMV8MMU_LEVEL3_DESCRIPTOR * +new_level_l3_table(uintptr_t base_addr) { + union TARMV8MMU_LEVEL3_DESCRIPTOR *l3_table = + (union TARMV8MMU_LEVEL3_DESCRIPTOR *)gilbraltar_palloc(); + + for (unsigned page = 0; page < ARMV8MMU_TABLE_ENTRIES; page++) { + struct TARMV8MMU_LEVEL3_PAGE_DESCRIPTOR *desc = &l3_table[page].page; + + desc->value11 = 3; + desc->attr_indx = ATTR_INDX_NORMAL; + desc->ns = 0; + desc->ap = ATTR_IB_AP_RW_EL1; + desc->sh = ATTR_IB_SH_INNER_SHAREABLE; + desc->af = 1; + desc->ng = 0; + desc->reserved0_1 = 0; + desc->output_addr = ARMV8MMUL3PAGEADDR(base_addr); + desc->reserved0_2 = 0; + desc->continuous = 0; + desc->pxn = 0; + desc->uxn = 1; + desc->ignored = 0; + + if (base_addr >= (uint64_t)&_etext) { + desc->pxn = 1; + + if ((base_addr >= mem && base_addr < GIGABYTE) || + base_addr > (8 * GIGABYTE - 1)) { + desc->attr_indx = ATTR_INDX_DEVICE; + desc->sh = ATTR_IB_SH_OUTER_SHAREABLE; + } else if (base_addr >= MEM_COHERENT_REGION && + base_addr < MEM_HEAP_START) { + desc->attr_indx = ATTR_INDX_COHERENT; + desc->sh = ATTR_IB_SH_OUTER_SHAREABLE; + } + } + + base_addr += ARMV8MMU_LEVEL3_PAGE_SIZE; + } + + return (l3_table); +} + +uintptr_t gilbraltar_translation_table_base(void) { + return ((uintptr_t)l2_table); +} + +void gilbraltar_translation_table_init(size_t size) { + l2_table = (union TARMV8MMU_LEVEL2_DESCRIPTOR *)gilbraltar_palloc(); + gilbraltar_log(INFO, "L2 table allocated.\r\n"); + + memset(l2_table, 0, PAGE_SIZE); + + for (unsigned entry = 0; entry < LEVEL2_TABLE_ENTRIES; entry++) { + uint64_t base_addr = + (uint64_t)entry * ARMV8MMU_TABLE_ENTRIES * ARMV8MMU_LEVEL3_PAGE_SIZE; + + if (base_addr >= 8 * GIGABYTE && + !(MEM_IOMEM_AXI_START <= base_addr && base_addr <= MEM_IOMEM_AXI_END) && + !(MEM_IOMEM_SOC_START <= base_addr && base_addr <= MEM_IOMEM_SOC_END) && + !(MEM_IOMEM_PCIE_START <= base_addr && base_addr <= MEM_IOMEM_PCIE_END)) + continue; // as far as we can + + gilbraltar_log(INFO, "New L3 table.\r\n"); + union TARMV8MMU_LEVEL3_DESCRIPTOR *l3_table = new_level_l3_table(base_addr); + struct TARMV8MMU_LEVEL2_TABLE_DESCRIPTOR *desc = &l2_table[entry].table; + + desc->value11 = 3; + desc->ignored1 = 0; + desc->table_addr = ARMV8MMUL2TABLEADDR((uint64_t)l3_table); + desc->reserved0 = 0; + desc->ignored2 = 0; + desc->pxn_table = 0; + desc->uxn_table = 0; + desc->ap_table = AP_TABLE_ALL_ACCESS; + desc->ns_table = 0; + } + + data_sync_barrier(); +}