From 5dfac4879ce5f34503ae7537eefd3fc48d6fa750 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 25 Aug 2021 23:47:08 +0300 Subject: libfdt seems to work At least as far as reading memory info, cool. One issue I have is that .(ro)data is apparently accessed by absolute addresses, so I need to know at which address the kernel is going to be loaded. I would prefer completely position independent code, but if that's not possible then eh. --- Makefile | 10 +-- arch/riscv/conf/boot.cmd | 6 +- arch/riscv/conf/init-link.S | 1 - arch/riscv/conf/kernel-link.S | 3 +- arch/riscv/config.h | 3 + arch/riscv/include/pages.h | 24 +++++--- arch/riscv/include/vmap.h | 3 - arch/riscv/init/head.S | 5 +- arch/riscv/init/init.c | 140 +++++++++++------------------------------- arch/riscv/main.c | 2 +- common/string.c | 37 ++++++----- config.h | 0 include/apos/link.lds.h | 8 --- include/apos/main.h | 2 +- include/fdt.h | 1 + include/libfdt.h | 1 + include/libfdt_env.h | 17 +++++ lib/libfdt_env.h | 17 ----- 18 files changed, 107 insertions(+), 173 deletions(-) create mode 100644 arch/riscv/config.h create mode 100644 config.h delete mode 100644 include/apos/link.lds.h create mode 100644 include/fdt.h create mode 100644 include/libfdt.h create mode 100644 include/libfdt_env.h delete mode 100644 lib/libfdt_env.h diff --git a/Makefile b/Makefile index d7f02c1..5097ff0 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ DO != echo > deps.mk -CFLAGS = -fno-pie -ggdb3 -ffreestanding -nostdlib +CFLAGS = -fno-pie -ggdb3 -ffreestanding -nostdlib -std=c11 -Wall -Wextra -mcmodel=medany DEPFLAGS = -MT $@ -MMD -MP -MF $@.d all: apos.bin @@ -23,9 +23,11 @@ CLEANUP_CMD := include arch/$(ARCH)/source.mk -INCLUDE_FLAGS := -Iinclude -Iarch/$(ARCH)/include $(USE_FDT:y=-Idtc/libfdt) +INCLUDE_FLAGS := -I include -I arch/$(ARCH)/include\ + -include config.h -include arch/$(ARCH)/config.h COMPILE = $(CROSS_COMPILE)$(CC) $(CFLAGS) $(DEPFLAGS) $(INCLUDE_FLAGS) +GENELF = $(CROSS_COMPILE)$(CC) $(CFLAGS) $(INCLUDE_FLAGS) GENLINK = $(CROSS_COMPILE)$(CPP) $(DEPFLAGS) $(INCLUDE_FLAGS) STRIPLINK = sed -n '/^[^\#]/p' @@ -45,10 +47,10 @@ apos.bin: kernel.elf init.elf cat init.bin kernel.bin > $@ kernel.elf: $(KERNEL_OBJECTS) $(KERNEL_LD) - $(COMPILE) -T$(KERNEL_LD) $(KERNEL_OBJECTS) -o $@ + $(GENELF) -T $(KERNEL_LD) $(KERNEL_OBJECTS) -o $@ init.elf: $(INIT_OBJECTS) $(INIT_LD) - $(COMPILE) -T$(INIT_LD) $(INIT_OBJECTS) -o $@ + $(GENELF) -T $(INIT_LD) $(INIT_OBJECTS) -o $@ clean: $(CLEANUP_CMD) diff --git a/arch/riscv/conf/boot.cmd b/arch/riscv/conf/boot.cmd index ddbc319..782c1e8 100644 --- a/arch/riscv/conf/boot.cmd +++ b/arch/riscv/conf/boot.cmd @@ -1,2 +1,4 @@ -fatload ${devtype} ${devnum} ${kernel_addr_r} apos.itb -bootm ${kernel_addr_r} +fdt move ${fdt_addr} ${fdt_addr_r} +fdt addr ${fdt_addr_r} +load ${devtype} ${devnum} ${kernel_addr_r} apos.itb +bootm ${kernel_addr_r} - ${fdt_addr_r} diff --git a/arch/riscv/conf/init-link.S b/arch/riscv/conf/init-link.S index db18822..f1ceadc 100644 --- a/arch/riscv/conf/init-link.S +++ b/arch/riscv/conf/init-link.S @@ -1,4 +1,3 @@ -#include #include OUTPUT_ARCH(riscv) diff --git a/arch/riscv/conf/kernel-link.S b/arch/riscv/conf/kernel-link.S index 873c7de..ebcc877 100644 --- a/arch/riscv/conf/kernel-link.S +++ b/arch/riscv/conf/kernel-link.S @@ -1,4 +1,3 @@ -#include #include OUTPUT_ARCH(riscv) @@ -7,7 +6,7 @@ ENTRY(main) SECTIONS { . = ABSOLUTE(VM_KERN); .text ALIGN(4K) : AT(0) { - *(.text.start); + *(.kernel.start); *(.text); . = ALIGN(4K); } diff --git a/arch/riscv/config.h b/arch/riscv/config.h new file mode 100644 index 0000000..1818316 --- /dev/null +++ b/arch/riscv/config.h @@ -0,0 +1,3 @@ +#include +#define PM_KERN 0x83800000 +#define VM_KERN ((-1) - SZ_1G) diff --git a/arch/riscv/include/pages.h b/arch/riscv/include/pages.h index 4ae2ab9..9e16c00 100644 --- a/arch/riscv/include/pages.h +++ b/arch/riscv/include/pages.h @@ -1,36 +1,40 @@ #ifndef APOS_RISCV_PAGES_H #define APOS_RISCV_PAGES_H -typedef char pagemask_t; -typedef char lockbit_t; +#include -struct kilopages { +typedef uint8_t pagemask_t; +typedef uint8_t lockbit_t; +/* assume riscv64 for now */ +typedef uint64_t pm_t; + +struct mm_kpages { pagemask_t page[64]; }; -struct megapages { +struct mm_mpages { lockbit_t lockbit[64]; pagemask_t empty[64]; pagemask_t full[64]; - struct kilopages kilo[512]; + struct mm_kpages kilo[512]; }; /* Sv39 */ -struct gigapages { +struct mm_gpages { lockbit_t lockbit[64]; pagemask_t empty[64]; pagemask_t full[64]; - struct megapages mega[512]; + struct mm_mpages mega[512]; }; -struct terapages { +struct mm_tpages { lockbit_t lockbit[64]; pagemask_t empty[64]; pagemask_t full[64]; - struct gigapages giga[512]; + struct mm_gpages giga[512]; }; -struct mm_pagearr_info { +struct mm_ptinfo { short tera_num; struct terapages *tera_top; diff --git a/arch/riscv/include/vmap.h b/arch/riscv/include/vmap.h index a1cf52f..aee3725 100644 --- a/arch/riscv/include/vmap.h +++ b/arch/riscv/include/vmap.h @@ -12,7 +12,4 @@ #define VM_A (1 << 6) #define VM_D (1 << 7) -#define VM_TOP (-1) -#define VM_KERN (VM_TOP - SZ_1G) - #endif /* APOS_RISCV_VMAP_H */ diff --git a/arch/riscv/init/head.S b/arch/riscv/init/head.S index 703d265..bbd2945 100644 --- a/arch/riscv/init/head.S +++ b/arch/riscv/init/head.S @@ -2,9 +2,6 @@ .global _start .type _start, @function _start: - /* store kernel load address */ - auipc a4, 0 - /* stack grows downward */ - mv sp, a4 + /* stack pointer is whatever? */ /* go to proper init */ j init diff --git a/arch/riscv/init/init.c b/arch/riscv/init/init.c index 30c60ac..bb16876 100644 --- a/arch/riscv/init/init.c +++ b/arch/riscv/init/init.c @@ -1,118 +1,50 @@ #include #include #include +#include #include #include #include -struct page_ret { - size_t left; - size_t num; - size_t top; +struct mem_layout { + pm_t base; + pm_t top; }; -extern void main(struct mm_pagearr_info *pageinfo); - -void __init init_zero(size_t ptr, size_t bytes) -{ - char *byte_ptr = (char *)ptr; - - /* Not entirely sure if it would be faster to use a larget type than - * char, Linux seems to have memset16/32/64 but I guess I should check - * the generated assembly. - */ - while(bytes--) - *byte_ptr++ = 0; -} - -struct page_ret __init init_pages(size_t ram_size, size_t ram_top, - size_t page_size, size_t struct_size) -{ - size_t num_pages = ram_size / page_size; - size_t size_pages = num_pages * struct_size; - - struct page_ret pageret; - pageret.top = ram_top - size_pages; - pageret.num = num_pages; - pageret.left = ram_size - (num_pages * page_size); - - init_zero(pageret.top, size_pages); - - return pageret; -}; - -size_t __init init_align_down(size_t num, size_t a) -{ - size_t rem = num % a; - return num - rem; -} - -size_t __init init_align_up(size_t num, size_t a) +struct mem_layout get_memlayout(void *fdt) { - return init_align_down(num, a) + a; + fdt32_t *size_ptr = (fdt32_t *)fdt_getprop(fdt, 0, "#size-cells", NULL); + fdt32_t *addr_ptr = (fdt32_t *)fdt_getprop(fdt, 0, "#address-cells", NULL); + + uint32_t size_cells = fdt32_to_cpu(*size_ptr); + uint32_t addr_cells = fdt32_to_cpu(*addr_ptr); + + int mem_offset = fdt_path_offset(fdt, "/memory"); + uint8_t *mem_reg = (uint8_t *)fdt_getprop(fdt, mem_offset, "reg", NULL); + + pm_t base; + /* if riscv128 comes around we will probably see addr_cells == 4, but + * I'm not too concerned about it at the moment */ + if (addr_cells == 2) { + base = fdt64_to_cpu(*(fdt64_t *)mem_reg); + mem_reg += sizeof(fdt64_t); + } else { + base = fdt32_to_cpu(*(fdt32_t *)mem_reg); + mem_reg += sizeof(fdt32_t); + } + + pm_t top; + if (size_cells == 2) + top = fdt64_to_cpu(*(fdt64_t *)mem_reg) + base; + else + top = fdt32_to_cpu(*(fdt64_t *)mem_reg) + base; + + struct mem_layout ret = {base, top}; + return ret; } -void __init init_enter_vm(unsigned long *root_page) +void init(void *fdt) { - asm volatile ("csrw 0x180, %0\n" "sfence.vma\n" - : - : "rK" (SATP_MODE_39 | ((unsigned long)root_page >> 12)) - : "memory"); -} - -void __init call_main() -{ - while(1){}; -} - -void __init init(void *ram_base, void *ram_top, void *initrd, void *fdt, void *boot) -{ - size_t ram_size = ram_top - ram_base; - - struct mm_pagearr_info pagearr; - struct page_ret pageret; - - /* create crude page status map at the top of physical RAM */ - pageret = init_pages(ram_size, (size_t)ram_top, - SZ_512G, sizeof(struct terapages)); - pagearr.tera_top = (struct terapages *)pageret.top; - pagearr.tera_num = pageret.num; - - pageret = init_pages(pageret.left, pageret.top, - SZ_1G, sizeof(struct gigapages)); - pagearr.giga_top = (struct gigapages *)pageret.top; - pagearr.giga_num = pageret.num; - - pageret = init_pages(pageret.left, pageret.top, - SZ_2M, sizeof(struct megapages)); - pagearr.mega_top = (struct megapages *)pageret.top; - pagearr.mega_num = pageret.num; - - pageret = init_pages(pageret.left, pageret.top, - SZ_4K, sizeof(struct kilopages)); - pagearr.kilo_top = (struct kilopages *)pageret.top; - pagearr.kilo_num = pageret.num; - - unsigned long *root_page = (unsigned long *) - (init_align_down((size_t)pagearr.kilo_top, SZ_4K) - SZ_4K); - - unsigned long *mid_page = (unsigned long)root_page - SZ_4K; - unsigned long *bot_page = (unsigned long)mid_page - SZ_4K; - - /* TODO: should init insert page data into the created arrays? */ - unsigned long root_addr = (((unsigned long)boot >> 12) >> 18) & 0x1ff; - unsigned long mid_addr = (((unsigned long)boot >> 12) >> 9) & 0x1ff; - unsigned long bot_addr = (((unsigned long)boot >> 12) >> 0) & 0x1ff; - - root_page[root_addr] = (((unsigned long)mid_page & ~0x3ff) >> 2) | VM_V; - mid_page[mid_addr] = ((unsigned long)bot_page & ~0x3ff) >> 2 | VM_V; - bot_page[bot_addr] = (((unsigned long)boot & ~0x3ff) >> 2) | VM_V | VM_R | VM_W | VM_X; - - //root_page[0] = (((unsigned long)ram_base & ~0x3ff) >> 2) | VM_V | VM_R | VM_W | VM_X; - - /* enter virtual memory */ - init_enter_vm(root_page); - - /* enter main */ - call_main(); + struct mem_layout pmem = get_memlayout(fdt); + /* struct mm_ptinfo ptbl = create_pagetable(pmem); */ } diff --git a/arch/riscv/main.c b/arch/riscv/main.c index 382f311..9334fb3 100644 --- a/arch/riscv/main.c +++ b/arch/riscv/main.c @@ -6,7 +6,7 @@ void yeet() int a = 23; } -void __main main(struct mm_pagearr_info *pageinfo) +void __main main(struct mm_ptinfo *pageinfo) { yeet(); while(1){}; diff --git a/common/string.c b/common/string.c index ab65f2a..af9c54a 100644 --- a/common/string.c +++ b/common/string.c @@ -84,7 +84,7 @@ __weak int strncmp(const char *str1, const char *str2, size_t num) const char *s1 = (const char *)str1; const char *s2 = (const char *)str2; - while ((*(s1++) == *(s2++)) && *s1 && *s2 && num--) ; + while ((*(s1++) == *(s2++)) && *s1 && *s2 && --num) ; return (int)(s1[-1] - s2[-1]); } @@ -97,10 +97,11 @@ __weak char *strchr(const char *str, int chr) while (num-- && *(s1--) != chr) ; + num++; if (!num) return 0; - return (char *)s1; + return (char *)(s1 + 1); } #undef strtok @@ -134,23 +135,25 @@ __weak char *strstr(const char *str1, const char *str2) size_t sl = strlen(str1); size_t pl = strlen(str2); - const char *s1 = str1; + const unsigned char *s1 = (const unsigned char *)str1; + const unsigned char *haystack = (const unsigned char *)s1; + const unsigned char *needle = (const unsigned char *)str2; for (size_t i = 0; i < 256; ++i) table[i] = pl; /* generate deltas */ for (size_t i = 0; i < pl - 1; ++i) - table[str2[i]] = pl - i - 1; + table[needle[i]] = pl - i - 1; size_t skip = 0; while (sl - skip >= pl) { - s1 = &str1[skip]; + s1 = &haystack[skip]; - if (!memcmp(s1, s2, pl)) + if (!memcmp(s1, needle, pl)) return (char *)s1; - skip += table[str1[skip + pl - 1]]; + skip += table[haystack[skip + pl - 1]]; } return 0; @@ -164,6 +167,7 @@ __weak char *strrchr(const char *str, int chr) while (num-- && *(s1--) != chr) ; + num++; if (!num) return 0; @@ -185,9 +189,9 @@ __weak char *strpbrk(const char *str1, const char *str2) __weak size_t strcspn(const char *str1, const char *str2) { char table[256] = { 0 }; - const char *s1 = str1; - const char *s2 = s1; - const char *t1 = str2; + const unsigned char *s1 = (const unsigned char *)str1; + const unsigned char *s2 = (const unsigned char *)s1; + const unsigned char *t1 = (const unsigned char *)str2; /* populate table */ while (*(t1++)) @@ -206,9 +210,9 @@ __weak size_t strcspn(const char *str1, const char *str2) __weak size_t strspn(const char *str1, const char *str2) { char table[256] = { 0 }; - const char *s1 = str1; - const char *s2 = s1; - const char *t1 = str2; + const unsigned char *s1 = (const unsigned char *)str1; + const unsigned char *s2 = (const unsigned char *)s1; + const unsigned char *t1 = (const unsigned char *)str2; /* populate table */ while (*(t1++)) @@ -260,12 +264,13 @@ __weak void *memchr(const void *ptr, int val, size_t num) const char *p1 = (char *)ptr; char c = (char)val; - while (num-- && *(p1--) != c) ; + while (num-- && *(p1++) != c) ; + num++; if (!num) return 0; - return (void *)p1; + return (void *)(p1 - 1); } #undef memcpy @@ -301,7 +306,7 @@ __weak int memcmp(const void *ptr1, const void *ptr2, size_t num) const char *p1 = (const char *)ptr1; const char *p2 = (const char *)ptr2; - while ((*(p1++) == *(p2++)) && num--) ; + while ((*(p1++) == *(p2++)) && --num) ; return (int)(p1[-1] - p2[-1]); } diff --git a/config.h b/config.h new file mode 100644 index 0000000..e69de29 diff --git a/include/apos/link.lds.h b/include/apos/link.lds.h deleted file mode 100644 index ddb1f65..0000000 --- a/include/apos/link.lds.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef APOS_LINK_LDS_H -#define APOS_LINK_LDS_H - -#ifndef PM_KERN -#define PM_KERN 0 -#endif - -#endif /* APOS_LINK_LDS_H */ diff --git a/include/apos/main.h b/include/apos/main.h index 5292df7..15fff73 100644 --- a/include/apos/main.h +++ b/include/apos/main.h @@ -3,6 +3,6 @@ #include -#define __main __section(".text.start") __noinline +#define __main __section(".kernel.start") __noinline #endif /* APOS_MAIN_H */ diff --git a/include/fdt.h b/include/fdt.h new file mode 100644 index 0000000..9236a45 --- /dev/null +++ b/include/fdt.h @@ -0,0 +1 @@ +#include "../dtc/libfdt/fdt.h" diff --git a/include/libfdt.h b/include/libfdt.h new file mode 100644 index 0000000..65b3ca6 --- /dev/null +++ b/include/libfdt.h @@ -0,0 +1 @@ +#include "../dtc/libfdt/libfdt.h" diff --git a/include/libfdt_env.h b/include/libfdt_env.h new file mode 100644 index 0000000..166b558 --- /dev/null +++ b/include/libfdt_env.h @@ -0,0 +1,17 @@ +#ifndef LIBFDT_ENV_H +/* take over libfdt */ +#define LIBFDT_ENV_H + +#include +#include + +typedef int16_t fdt16_t; +typedef int32_t fdt32_t; +typedef int64_t fdt64_t; + +#define fdt32_to_cpu(x) be32_to_cpu(x) +#define cpu_to_fdt32(x) cpu_to_be32(x) +#define fdt64_to_cpu(x) be64_to_cpu(x) +#define cpu_to_fdt64(x) cpu_to_be64(x) + +#endif /* LIBFDT_ENV_H */ diff --git a/lib/libfdt_env.h b/lib/libfdt_env.h deleted file mode 100644 index 166b558..0000000 --- a/lib/libfdt_env.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef LIBFDT_ENV_H -/* take over libfdt */ -#define LIBFDT_ENV_H - -#include -#include - -typedef int16_t fdt16_t; -typedef int32_t fdt32_t; -typedef int64_t fdt64_t; - -#define fdt32_to_cpu(x) be32_to_cpu(x) -#define cpu_to_fdt32(x) cpu_to_be32(x) -#define fdt64_to_cpu(x) be64_to_cpu(x) -#define cpu_to_fdt64(x) cpu_to_be64(x) - -#endif /* LIBFDT_ENV_H */ -- cgit v1.3