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(); +}