diff --git a/Makefile b/Makefile index fa72d66aa6f61346e6baaabb0941784d6e056a32..60f85f56a6b6e15ad22ab3d1b077eeb40ca1053c 100644 --- a/Makefile +++ b/Makefile @@ -263,13 +263,14 @@ NOSTDINC_FLAGS = CFLAGS_KERNEL = AFLAGS_KERNEL = -# Use MYAPPINCLUDE when you must reference the include/ directory. +# Use KERNELINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option -MYAPPINCLUDE := \ +KERNELINCLUDE := \ + -I$(srctree)/arch/$(SRCARCH)/include \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ -Iinclude -include include/generated/autoconf.h -KBUILD_CPPFLAGS := -D__MYAPP__ +KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common \ @@ -289,7 +290,7 @@ export CPP AR NM STRIP OBJCOPY OBJDUMP export MAKE AWK PERL PYTHON export HOSTCXX HOSTCXXFLAGS CHECK CHECKFLAGS -export KBUILD_CPPFLAGS NOSTDINC_FLAGS MYAPPINCLUDE OBJCOPYFLAGS LDFLAGS +export KBUILD_CPPFLAGS NOSTDINC_FLAGS KERNELINCLUDE OBJCOPYFLAGS LDFLAGS export KBUILD_CFLAGS CFLAGS_KERNEL export KBUILD_AFLAGS AFLAGS_KERNEL export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL @@ -569,7 +570,8 @@ export KBUILD_IMAGE ?= leanos export INSTALL_PATH ?= ./install -core-y := arch/sparc/ +core-y := arch/$(SRCARCH)/ +kernel-y := kernel/ init-y := init/ libs-y := lib/ @@ -578,13 +580,15 @@ libs-y := lib/ leanos-dirs := $(patsubst %/,%,$(filter %/, \ $(init-y) \ $(core-y) \ + $(kernel-y) \ $(libs-y))) # leanos-core := $(patsubst %/, %/built-in.o, $(core-y)) +leanos-kernel := $(patsubst %/, %/built-in.o, $(kernel-y)) leanos-init := $(patsubst %/, %/built-in.o, $(init-y)) leanos-libs := $(patsubst %/, %/lib.a, $(libs-y)) -leanos-deps := $(leanos-init) $(leanos-core) $(leanos-libs) +leanos-deps := $(leanos-init) $(leanos-core) $(leanos-kernel) $(leanos-libs) quiet_cmd_leanos = LD $@ cmd_leanos = $(CC) $(LDFLAGS) -o $@ \ diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 0bdb2c87352c6285014e4b1ccf53358a9c2e2ce8..f6c89ab6dfdcf49d7e3ba07f864ebacd78330000 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -1,7 +1,22 @@ - +menu "SPARC Configuration" ### Arch specific settings +config PAGE_OFFSET + bool "Use an offset in physical/virtual page address conversion" + default n + help + Use a fixed offset when computing the virtual and physical page + addresses. + +config EXTRA_SPARC_PHYS_BANKS + int "Number of extra physical memory banks" + default 0 + range 0 31 + help + Set number of additional physical memory banks if the machine has more + than one. +endmenu diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 0857c4b52a0c5ade3b8226c59bc1ee4b59539d71..d91ba92498f984fa9ac95c7165e31f4ffcb32975 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -3,5 +3,9 @@ CHECKFLAGS += -D__sparc__ obj-y += setup.o +obj-y += init.o +obj-y += page.o +obj-y += bootmem.o +obj-y += mm.o #libs-y += lib/ diff --git a/arch/sparc/kernel/bootmem.c b/arch/sparc/kernel/bootmem.c new file mode 100644 index 0000000000000000000000000000000000000000..28e0a5155a25558d3695fa641af714de47769a5e --- /dev/null +++ b/arch/sparc/kernel/bootmem.c @@ -0,0 +1,68 @@ +/** + * @file arch/sparc/kernel/bootmem.c + */ + +#include <page.h> + +#include <kernel/printk.h> + + +void bootmem_init(void) +{ + int i; + + unsigned long start_pfn; + unsigned long end_pfn = 0UL; + + + pr_notice("End of program at: %lx\n", (unsigned long) _end); + + /* start allocatable memory with page aligned address of last symbol in + * image + */ + start_pfn = (unsigned long) PAGE_ALIGN((unsigned long) &_end); + + /* locate the memory bank we're in and start the mapping from + * the first free page after the image. + */ + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + + if (start_pfn < sp_banks[i].base_addr) + continue; + + end_pfn = sp_banks[i].base_addr + sp_banks[i].num_bytes; + + if (start_pfn < end_pfn) + break; + + end_pfn = 0UL; + } + + BUG_ON(!end_pfn); /* found no suitable memory, we're boned */ + + /* Map what is not used for the kernel code to the virtual page start. + * Since we don't have a bootstrap process for remapping the kernel, + * for now, we will run the code from the 1:1 mapping of our physical + * base and move everything else into high memory. + */ + + start_pfn = (unsigned long) __pa(start_pfn); + + /* Now shift down to get the real physical page frame number. */ + start_pfn >>= PAGE_SHIFT; + + end_pfn = (unsigned long) __pa(end_pfn); + + end_pfn = end_pfn >> PAGE_SHIFT; + + pr_notice("start_pfn: %lx\n", start_pfn); + pr_notice("end_pfn: %lx\n", end_pfn); + + + init_page_map(MEM_PAGE_NODE(0), start_pfn, end_pfn); + + + + + +} diff --git a/arch/sparc/kernel/init.c b/arch/sparc/kernel/init.c new file mode 100644 index 0000000000000000000000000000000000000000..faf296604e7e0175c678b14368947c7df85a5699 --- /dev/null +++ b/arch/sparc/kernel/init.c @@ -0,0 +1,10 @@ +/** + * @file arch/sparc/kernel/init.c + */ + +#include <mm.h> + +void paging_init(void) +{ + bootmem_init(); +} diff --git a/arch/sparc/kernel/mm.c b/arch/sparc/kernel/mm.c new file mode 100644 index 0000000000000000000000000000000000000000..e9e3cc8373dee00c9c2148a37a21b5f9dcc3e173 --- /dev/null +++ b/arch/sparc/kernel/mm.c @@ -0,0 +1,11 @@ +/** + * @file arch/sparc/kernel/mm.c + */ + +#include <mm.h> + + +unsigned long phys_base; +unsigned long pfn_base; + +struct sparc_physical_banks sp_banks[SPARC_PHYS_BANKS+1]; diff --git a/arch/sparc/kernel/page.c b/arch/sparc/kernel/page.c new file mode 100644 index 0000000000000000000000000000000000000000..4dfd728791b07589d2388529cc63e0e8ebb809b2 --- /dev/null +++ b/arch/sparc/kernel/page.c @@ -0,0 +1,36 @@ +/** + * @file arch/sparc/kernel/page.c + */ + +#include <page.h> + +struct pg_data page_mem[SPARC_PHYS_BANKS+1]; + + + +unsigned long init_page_map(struct pg_data *pg, + unsigned long start_pfn, + unsigned long end_pfn) +{ + unsigned long mapsize = 0; +#if 0 + pg->bdata->node_map_mem = __va(PFN_PHYS(start_pfn)); + pg->bdata->node_mem_map = __va(PFN_PHYS(start_pfn)); + pg->bdata->node_min_pfn = start_pfn; + pg->bdata->node_low_pfn = end_pfn; + link_bootmem(pg->bdata); + + /* + * Initially all pages are reserved - setup_arch() has to + * register free RAM areas explicitly. + */ + mapsize = bootmap_bytes(end - start); + memset(bdata->node_bootmem_map, 0xff, mapsize); + + bdebug("nid=%td start=%lx map=%lx end=%lx mapsize=%lx\n", + bdata - bootmem_node_data, start, mapstart, end, mapsize); + +#endif + return mapsize; +} + diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 828c709066da354fc049a8d8413f026b1dbae49f..ca335e448faa80e14f001049d8f2e86fc0a2297a 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -2,6 +2,40 @@ * @file arch/sparc/kernel/setup.c */ +#include <string.h> /* memset() */ + +#include <init.h> +#include <mm.h> +#include <compiler.h> + + +/** + * @brief configure available memory banks + * + * TODO the memory layout should either be presented in a separate + * board configuration file or, preferably, be derived from an AMBA + * bus scan. + */ + +static void mem_init(void) +{ + memset(&sp_banks, 0x0, ARRAY_SIZE(sp_banks)); + + sp_banks[0].base_addr = 0x40000000; + sp_banks[0].num_bytes = 0x00800000; +#if 0 + sp_banks[1].base_addr = 0x60000000; + sp_banks[1].num_bytes = 0x04000000; +#endif +} + + +/** + * @brief architecture setup entry point + */ + void setup_arch(void) { + mem_init(); + paging_init(); } diff --git a/include/compiler.h b/include/compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..ae05cf64f5c2eb7b12bb7049d75d975cae35ff1f --- /dev/null +++ b/include/compiler.h @@ -0,0 +1,44 @@ +/** + * @file compiler.h + * @author Armin Luntzer (armin.luntzer@univie.ac.at), + * @date 2015 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief a collection of preprocessor macros + */ + + +#ifndef COMPILER_H +#define COMPILER_H + + +/** + * Compile time check usable outside of function scope. + * Stolen from Linux (hpi_internal.h) + */ +#define compile_time_assert(cond, msg) typedef char ASSERT_##msg[(cond) ? 1 : -1] + + +/** + * same with the stuff below + */ + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +/* optimisation barrier */ +#define barrier() __asm__ __volatile__("": : :"memory") + +#endif diff --git a/include/kernel/kernel.h b/include/kernel/kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..2b5892a7e41f8eea478351be4901a21dba42eb8f --- /dev/null +++ b/include/kernel/kernel.h @@ -0,0 +1,23 @@ +#ifndef _KERNEL_H_ +#define _KERNEL_H_ + +#include <compiler.h> + + +#define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) ALIGN_MASK(x, (typeof(x))(a) - 1) + + +/* this is a bit crude, but must do for now */ +#define panic(x) {}while(1) + +#include <stdio.h> +#define BUG() do { \ + printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \ + panic("BUG!"); \ +} while (0) + +#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0) + + +#endif /* _KERNEL_H_ */ diff --git a/include/kernel/kernel_levels.h b/include/kernel/kernel_levels.h new file mode 100644 index 0000000000000000000000000000000000000000..c2205fff76838f7f4e16cadb91471c5f74c5aee5 --- /dev/null +++ b/include/kernel/kernel_levels.h @@ -0,0 +1,60 @@ +#ifndef _KERNEL_LEVELS_H_ +#define _KERNEL_LEVELS_H_ + +/* stole that from linux/kern_levels.h */ + +#define KERN_SOH "\001" /* ASCII Start Of Header */ +#define KERN_SOH_ASCII '\001' + +#define KERN_EMERG KERN_SOH "0" /* system is unusable */ +#define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */ +#define KERN_CRIT KERN_SOH "2" /* critical conditions */ +#define KERN_ERR KERN_SOH "3" /* error conditions */ +#define KERN_WARNING KERN_SOH "4" /* warning conditions */ +#define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */ +#define KERN_INFO KERN_SOH "6" /* informational */ +#define KERN_DEBUG KERN_SOH "7" /* debug-level messages */ + +#define KERN_DEFAULT KERN_SOH "d" /* the default kernel loglevel */ + + + +/* we're boned */ +#define pr_emerg(fmt, ...) \ + printk(KERN_EMERG fmt, ##__VA_ARGS__) + +/* immediate action required, we are likely boned*/ +#define pr_alert(fmt, ...) \ + printk(KERN_ALERT fmt, ##__VA_ARGS__) + +/* critical condition occured, we are probably boned */ +#define pr_crit(fmt, ...) \ + printk(KERN_CRIT fmt, ##__VA_ARGS__) + +/* some error occured, we are probably fine */ +#define pr_err(fmt, ...) \ + printk(KERN_ERR fmt, ##__VA_ARGS__) + +/* outlook not so good */ +#define pr_warning(fmt, ...) \ + printk(KERN_WARNING fmt, ##__VA_ARGS__) + +#define pr_warn pr_warning + +/* something worth knowing */ +#define pr_notice(fmt, ...) \ + printk(KERN_NOTICE fmt, ##__VA_ARGS__) + +/* still interesting */ +#define pr_info(fmt, ...) \ + printk(KERN_INFO fmt, ##__VA_ARGS__) + +/* Quite correct, sir, blabber on. */ +#define pr_debug(fmt, ...) \ + printk(KERN_DEBUG fmt, ##__VA_ARGS__) + + +void printk_set_level(int lvl); + + +#endif /* _KERNEL_LEVELS_H_ */ diff --git a/include/kernel/printk.h b/include/kernel/printk.h new file mode 100644 index 0000000000000000000000000000000000000000..e9a3a039298ef6579cbea09526beb8c58be818da --- /dev/null +++ b/include/kernel/printk.h @@ -0,0 +1,12 @@ +/** + * @file include/kernel/printk.h + */ + +#ifndef _KERNEL_KERNEL_LEVELS_H_ +#define _KERNEL_KERNEL_LEVELS_H_ + +#include <kernel/kernel_levels.h> + +int printk(const char *fmt, ...); + +#endif /* _KERNEL_KERNEL_LEVELS_H_ */ diff --git a/kernel/Kconfig b/kernel/Kconfig index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..64afbec3289e3f730cb91eb33d97b45295918f09 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -0,0 +1,13 @@ +config KERNEL_LEVEL + int "Kernel debug level" + default "7" + help + Limit the kernel's debug message level: + 0: emergency + 1: alerts + 2: critical conditions + 3: error conditions + 4: warnings + 5: notices + 6: informational + 7: debug diff --git a/kernel/Makefile b/kernel/Makefile index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c0728ac094f9b069bb49141f3a1b4439e42a505e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -0,0 +1 @@ +obj-y += printk.o diff --git a/kernel/printk.c b/kernel/printk.c new file mode 100644 index 0000000000000000000000000000000000000000..a87779df7710b74b9eb59a6e0360989a08c744b3 --- /dev/null +++ b/kernel/printk.c @@ -0,0 +1,70 @@ +/** + * @file kernel/printk.c + * + * @note printk levels obviously stolen from linux (include/linux/printk.h) + * @copyright Linus Torvalds et. al. + * + * TODO this obviously needs custom support when not using newlib/bcc + */ + + +#include <stdarg.h> +#include <stdio.h> + +#include <kernel/kernel_levels.h> + +#if defined(CONFIG_KERNEL_LEVEL) +#define KERNEL_LEVEL (CONFIG_KERNEL_LEVEL + '0') +#else +#define KERNEL_LEVEL '7' +#endif + +static int printk_get_level(const char *buffer) +{ + if (buffer[0] == KERN_SOH_ASCII && buffer[1]) { + switch (buffer[1]) { + case '0' ... '7': + case 'd': /* KERN_DEFAULT */ + return buffer[1]; + } + } + return 0; +} + + +static inline const char *printk_skip_level(const char *buffer) +{ + if (printk_get_level(buffer)) + return buffer + 2; + + return buffer; +} + +/** + * @brief see printf(3) + * + */ + +int printk(const char *fmt, ...) +{ + int ret = 0; + int level; + + va_list args; + + + level = printk_get_level(fmt); + + va_start(args, fmt); + + if (level) { + if (level < KERNEL_LEVEL) + ret = vprintf(printk_skip_level(fmt), args); + } else { + ret = vprintf(fmt, args); + } + + va_end(args); + + return ret; +} diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 1d1bc293749cb88c8d2fefa1619f2fb192bef479..ffb5639bb0be400ce18f5ebe92d1cf190bb39af5 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -91,13 +91,13 @@ __a_flags = $(call flags,_a_flags) __cpp_flags = $(call flags,_cpp_flags) endif -c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(MYAPPINCLUDE) \ +c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KERNELINCLUDE) \ $(__c_flags) $(modkern_cflags) -a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(MYAPPINCLUDE) \ +a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KERNELINCLUDE) \ $(__a_flags) $(modkern_aflags) -cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(MYAPPINCLUDE) \ +cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KERNELINCLUDE) \ $(__cpp_flags) ld_flags = $(LDFLAGS) $(ldflags-y)