From 4050eaffb3a1cc360cb8b30394e450a5342d1f76 Mon Sep 17 00:00:00 2001 From: Armin Luntzer <armin.luntzer@univie.ac.at> Date: Tue, 6 Dec 2016 17:15:07 +0100 Subject: [PATCH] * add printk() * begin preparing paging on SPARC target --- Makefile | 16 +++++--- arch/sparc/Kconfig | 17 ++++++++- arch/sparc/kernel/Makefile | 4 ++ arch/sparc/kernel/bootmem.c | 68 +++++++++++++++++++++++++++++++++ arch/sparc/kernel/init.c | 10 +++++ arch/sparc/kernel/mm.c | 11 ++++++ arch/sparc/kernel/page.c | 36 +++++++++++++++++ arch/sparc/kernel/setup.c | 34 +++++++++++++++++ include/compiler.h | 44 +++++++++++++++++++++ include/kernel/kernel.h | 23 +++++++++++ include/kernel/kernel_levels.h | 60 +++++++++++++++++++++++++++++ include/kernel/printk.h | 12 ++++++ kernel/Kconfig | 13 +++++++ kernel/Makefile | 1 + kernel/printk.c | 70 ++++++++++++++++++++++++++++++++++ scripts/Makefile.lib | 6 +-- 16 files changed, 415 insertions(+), 10 deletions(-) create mode 100644 arch/sparc/kernel/bootmem.c create mode 100644 arch/sparc/kernel/init.c create mode 100644 arch/sparc/kernel/mm.c create mode 100644 arch/sparc/kernel/page.c create mode 100644 include/compiler.h create mode 100644 include/kernel/kernel.h create mode 100644 include/kernel/kernel_levels.h create mode 100644 include/kernel/printk.h create mode 100644 kernel/printk.c diff --git a/Makefile b/Makefile index fa72d66..60f85f5 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 0bdb2c8..f6c89ab 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 0857c4b..d91ba92 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 0000000..28e0a51 --- /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 0000000..faf2966 --- /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 0000000..e9e3cc8 --- /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 0000000..4dfd728 --- /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 828c709..ca335e4 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 0000000..ae05cf6 --- /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 0000000..2b5892a --- /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 0000000..c2205ff --- /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 0000000..e9a3a03 --- /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 e69de29..64afbec 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 e69de29..c0728ac 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 0000000..a87779d --- /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 1d1bc29..ffb5639 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) -- GitLab