Skip to content
Snippets Groups Projects
Commit e806024f authored by Armin Luntzer's avatar Armin Luntzer
Browse files

* set up a xentium kernel build directory

* add xentium kernels to modules.image
* add autoloading of xentium kernels
* add ar_get_file_list()
* add more string functions
* stuff
parent 253bcee5
No related branches found
No related tags found
No related merge requests found
......@@ -307,7 +307,8 @@ export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_ve
# Files to ignore in find ... statements
export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o \
-name CVS -o -name .pc -o -name .hg -o -name .git \) \
-name CVS -o -name .pc -o -name .hg -o -name .git \
-o -name sysroot \) \
-prune -o
export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
--exclude CVS --exclude .pc --exclude .hg --exclude .git
......@@ -587,6 +588,7 @@ core-y := arch/$(SRCARCH)/
kernel-y := kernel/
init-y := init/
libs-y := lib/
xentium-y := dsp/ # this should be CONFIG_XENTIUM_WHATEVER
-include arch/$(ARCH)/Makefile
......@@ -594,7 +596,8 @@ leanos-dirs := $(patsubst %/,%,$(filter %/, \
$(init-y) \
$(core-y) \
$(kernel-y) \
$(libs-y)))
$(libs-y)) \
$(xentium-y))
#
leanos-core := $(patsubst %/, %/built-in.o, $(core-y))
leanos-kernel := $(patsubst %/, %/built-in.o, $(kernel-y))
......
obj-y += xentium/
# we just hijack the host build system because it's the easiest way...
#
# Xentium kernels are built as executables, with library functions
# explicitly listed as object dependencies. The executables are later collected
# in scripts/link-leanos.sh and added to the embedded AR image.
#
# The address of the .text section for the first xentium kernel is determined
# by the confiuration in dsp/xentium/sysroot/lib/default.ld, all subsequent
# programs will start after the _end symbol of the previous
#
# To achieve this, list dsp kernel targets in hostprogs-y and configure targets
# so that the next target depends on the finalised previous target and take
# the value of the _end symbol as the new .text start
#
# This isn't a pretty solution, but that's what you get for not supporting
# relocations. It works for now and it is at least slightly more comfortable
# than configuring all text base addresses by hand
#
obj- := dummy.o
HOSTCC := xentium-clang
HOSTLD := xentium-ld
HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -Idsp/xentium
HOSTLDFLAGS += -Tdsp/xentium/sysroot/lib/default.ld
HOSTLDFLAGS += --sysroot=dsp/xentium/sysroot
hostprogs-y := testkernel.xen
hostprogs-y += otherkernel.xen
testkernelkernel.xen :
HOSTLOADLIBES_testkernel.xen :=
testkernel.xen-objs := testkernel.o xen_printf.o
otherkernel.xen : testkernel.xen
HOSTLOADLIBES_otherkernel.xen := -Ttext $$(readelf -s dsp/xentium/testkernel.xen|grep -w _end |awk '{print $$2}')
otherkernel.xen-objs := testkernel.o xen_printf.o
always := $(hostprogs-y)
WARNING
the LD script is likely fucking us with the set up of the stack pointer, need to address this...
File added
/*
* Copyright (c) 2011, Recore Systems B.V., The Netherlands,
* web: www.recoresystems.com, email: info@recoresystems.com
*
* Any reproduction in whole or in parts is prohibited
* without the written consent of the copyright owner.
*
* All Rights Reserved.
*/
STARTUP(crt0.o)
INPUT(-lc -lcompiler_rt)
OUTPUT_FORMAT("elf32-xentium")
OUTPUT_ARCH(xentium)
ENTRY(_start)
_MINIMUM_STACK_SIZE = 1K;
MEMORY
{
dbank0 : ORIGIN = 0x00000000, LENGTH = 8K
dbank1 : ORIGIN = 0x00002000, LENGTH = 8K
dbank2 : ORIGIN = 0x00004000, LENGTH = 8K
dbank3 : ORIGIN = 0x00006000, LENGTH = 8K
ram : ORIGIN = 0x50000000, LENGTH = 256M
}
PHDRS
{
code PT_LOAD;
data PT_LOAD;
tcm PT_LOAD;
}
SECTIONS
{
/* RAM code and data */
.text : {
*(.text)
. = ALIGN(16*4) ; /* Align to the next cache line boundary */
} > ram : code
.rodata ALIGN(0x40) : {
*(.rodata .rodata.*)
. = ALIGN(4) ;
} > ram : data
.data ALIGN(0x40) : {
*(.data)
. = ALIGN(4) ;
} > ram : data
.bss ALIGN(0x40) : {
__bss_start = .;
*(.bss)
. = ALIGN(4) ;
} > ram : data
_end = __bss_start + SIZEOF(.bss);
/* TCM */
.dbank0 ORIGIN(dbank0) : { *(.dbank0) } > dbank0 : tcm
.dbank0_noinit ALIGN(0x4) (NOLOAD) : { *(.dbank0_noinit) } > dbank0 : tcm
.dbank1 ORIGIN(dbank1) : { *(.dbank1) } > dbank1 : tcm
.dbank1_noinit ALIGN(0x4) (NOLOAD) : { *(.dbank1_noinit) } > dbank1 : tcm
.dbank2 ORIGIN(dbank2) : { *(.dbank2) } > dbank2 : tcm
.dbank2_noinit ALIGN(0x4) (NOLOAD) : { *(.dbank2_noinit) } > dbank2 : tcm
.dbank3 ORIGIN(dbank3) : { *(.dbank3) } > dbank3 : tcm
.dbank3_noinit ALIGN(0x4) (NOLOAD) : { *(.dbank3_noinit) } > dbank3 : tcm
/*
* Set the stack pointer to top of data bank 3 or top of the RAM depending on
* the available space in data bank 3.
*/
_remaining_db3 = (LENGTH(dbank3) - SIZEOF(.dbank3) - SIZEOF(.dbank3_noinit));
_top_db3 = ORIGIN(dbank3)+LENGTH(dbank3);
_top_ram = ORIGIN(ram)+LENGTH(ram);
_stack = (_remaining_db3 > _MINIMUM_STACK_SIZE) ? _top_db3 : _top_ram;
/* Check that there is enough space in the RAM for the stack */
_remaining_ram = (LENGTH(ram) - (_end - _start));
ASSERT(_remaining_ram > 0, "The stack does not fit in ram")
}
File added
%define SYS_argvlen 12
%define SYS_argv 13
.file "crt0.s"
.text
.globl _start
.align 4
.type _start,@function
_start:
; Start by setting up a stack.
A0 OR 0, hi16(_stack) ; The linker script specifies the address
; where the stack should start with the
; _stack symbol. Get the high part of it
; on A0X...
A0 OR A0X, lo16(_stack) ; or in the low part...
RA14 = A0X ; and assign it to the stack pointer register
; (RA14).
; Now that we have a stack we can start using function calls if needed.
A0 ADD RA14, -4 ; Decrement stack pointer.
C0 LINK ; Get return address.
RA14 = A0X
E0 STW A0X[0], C0X ; Store return address in the stack.
; Zero the memory in the .bss section.
A0 OR 0, hi16(__bss_start) ; The linker script specifies the address
; where the .bss section should start with
; the __bss_start symbol. Get the high part
; of it on A0X.
S0 OR 0, hi16(_end) ; The linker script specifies the address
; where the .bss section should end with
; the _end symbol. Get the high part
; of it on S0X.
A0 OR A0X, lo16(__bss_start) ; Or the low part of the address of the
; __bss_start symbol into the high part
; already on A0X.
S0 OR S0X, lo16(_end) ; Or the low part of the address of the
; _end symbol into the high part already on
; S0X.
; This commented out section of code uses the memset function to do the actual
; zeroing of the .bss section. If we have an optimized implementation of the
; memset function we might want to use this instead of the code below.
; Currently however it just makes the executable bigger.
;
; RA6 = A0X ; The first parameter of the memset function
; ; is the pointer to the block of memory to
; ; fill. Set it to the address the .bss
; ; section (__bss_start).
; A0 SUB S0X, A0X ; Calculate the size of the .bss section
; ; (_end - __bss_start)
;
; RB6 = 0 ; The second parameter of the memset function
; ; is the value the block of memory should be
; ; set to. Set it to 0.
; RC6 = A0X ; The third parameter of the memset function
; ; is the number of bytes to set. Set it to
; ; the size of the .bss section we just
; ; calculated.
;
; C0 BR memset ; Call the memset function to do the actual
; ; zeroing.
;
; NOP 2
;
P0 CMPLTU A0X, S0X ; Check if current address in .bss,
; __bss_start, (A0X) is less than _end (S0X).
C0 BRZ P0X, .L2 ; If it is not, the size of .bss is 0, so no
; need to initialize .bss. Jump over the
; .bss initialization loop.
NOP 2
; Begin .bss initialization loop
.L1:
E0 STB A0X[0], 0 ; Write 0 to current address in .bss.
A0 ADD A0X, 1 ; Increment current address in .bss
P0 CMPLTU A0X, S0X ; Check if new current address in .bss is
; still less than _end.
C0 BRNZ P0X, .L1 ; If it is jump back to the beginning of the
; .bss initialization loop.
NOP 2
; End .bss initialization loop/
; Initialisation for calls to main with arguments
; from the command line
.L2:
C0 TRAP SYS_argvlen
C0 TRAP SYS_argv
.L3:
C0 BR main ; Call the main function.
NOP 2
E0 LDW RA14[0]
A0 ADD RA14, +4
RA14 = A0X
C0 BRA E0X ; Jump back to the MPPB Xentium bootloader.
NOP 2
.Ltmp0:
.size _start, .Ltmp0-_start
......@@ -44,8 +44,11 @@ struct archive {
};
void ar_list_files(struct archive *a);
void ar_list_symbols(struct archive *a);
void ar_print_files(struct archive *a);
void ar_print_symbols(struct archive *a);
char *ar_get_file_list(struct archive *a);
void *ar_find_file(struct archive *a, const char *name);
void *ar_find_symbol(struct archive *a, const char *name);
void ar_free(struct archive *a);
......
......@@ -12,7 +12,11 @@ int sprintf(char *str, const char *format, ...);
int strcmp(const char *s1, const char *s2);
char *strpbrk(const char *s, const char *accept);
char *strsep(char **stringp, const char *delim);
char *strdup(const char *s);
char *strstr(const char *haystack, const char *needle);
size_t strlen(const char *s);
int memcmp(const void *s1, const void *s2, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
char *strcpy(char *dest, const char *src);
......
......@@ -16,7 +16,6 @@
#include <kernel/sbrk.h>
#include <kernel/sysctl.h>
#include <kernel/xentium.h>
#define MSG "MAIN: "
......@@ -24,6 +23,7 @@ void module_image_load_embedded(void);
void *module_lookup_embedded(char *mod_name);
void *module_lookup_symbol_embedded(char *sym_name);
void *module_read_embedded(char *mod_name);
void module_load_xen_kernels(void);
static void kernel_init(void)
{
......@@ -40,7 +40,6 @@ int main(void)
{
void *addr;
struct elf_module m;
struct xen_kernel x;
kernel_init();
......@@ -65,14 +64,8 @@ int main(void)
/* addr = module_lookup_symbol_embedded("somefunction"); */
/* XXX the image is not necessary aligned properly, so we can't access
* it directly, until we have a MNA trap */
#if 1
addr = module_read_embedded("testkernel.ko");
printk(MSG "testkernel module address is %p\n", addr);
if (addr)
xentium_kernel_load(&x, addr);
#endif
#if 0
addr = module_read_embedded("noc_dma.ko");
......@@ -86,6 +79,10 @@ int main(void)
#if 0
modules_list_loaded();
#endif
/* load all available Xentium kernels from the embedded modules image */
module_load_xen_kernels();
return 0;
}
......
......@@ -5,6 +5,11 @@
#include <kernel/printk.h>
#include <kernel/ar.h>
#include <kernel/kmem.h>
#include <kernel/string.h>
#include <kernel/xentium.h>
#define MSG "MODIMG: "
extern unsigned char _binary_modules_image_start __attribute__((weak));
extern unsigned char _binary_modules_image_end __attribute__((weak));
......@@ -19,8 +24,8 @@ void module_image_load_embedded(void)
(unsigned int)&_binary_modules_image_size, &mod_ar);
#if 0
ar_list_files(&mod_ar);
ar_list_symbols(&mod_ar);
ar_print_files(&mod_ar);
ar_print_symbols(&mod_ar);
#endif
}
......@@ -54,3 +59,49 @@ void *module_read_embedded(char *mod_name)
return ptr;
}
/**
* @brief try to load all xentium kernels found in the embedded image
*
* @note assumes all files with suffix ".xen" are a kernel
*/
void module_load_xen_kernels(void)
{
char *list;
char *fname;
void *file;
struct xen_kernel x;
list = ar_get_file_list(&mod_ar);
if (!list)
return;
while (1) {
fname = strsep(&list, " ");
if (!fname)
break;
if (!strstr(fname, ".xen"))
continue;
pr_info(MSG "Loading Xentium kernel %s\n", fname);
file = module_read_embedded(fname);
if (!file)
pr_err(MSG "Failed to read file %s\n", fname);
if (!xentium_kernel_load(&x, file))
pr_err(MSG "Error loading Xentium kernel %s\n", fname);
kfree(file);
}
kfree(list);
}
......@@ -16,6 +16,50 @@
#define BANK_SIZE ( 8*1024 )
#define TCM_SIZE ( 32*1024 )
#define XEN_MAILBOX_OFFSET ( 512*1024 )
//=============================================================
// XENTIUM structure
//=============================================================
typedef struct {
// TCM
unsigned int tcm[TCM_SIZE/4];
unsigned int dummy[(XEN_MAILBOX_OFFSET-TCM_SIZE)/4];
// Status bits + control registers
unsigned int mlbx[4]; //0x00080000 .. 0x0008000C
unsigned int signal[8]; //0x00080010 .. 0x0008002C
unsigned int dma; //0x00080030 .. 0x00080030
unsigned int dummy1; //0x00080034 .. 0x00080034
unsigned int timer[2]; //0x00080038 .. 0x0008003C
unsigned int irq; //0x00080040 .. 0x00080040
unsigned int dummy2; //0x00080044 .. 0x00080044
unsigned int status; //0x00080048 .. 0x00080048
unsigned int pc; //0x0008004C .. 0x0008004C
unsigned int fsm_state; //0x00080050 .. 0x00080050
} volatile S_xen;
typedef struct S_xdev{
/* Status bits + control registers */
volatile unsigned int mlbx[4]; //0x00080000 .. 0x0008000C
volatile unsigned int signal[8]; //0x00080010 .. 0x0008002C
volatile unsigned int dma; //0x00080030 .. 0x00080030
volatile unsigned int dummy1; //0x00080034 .. 0x00080034
volatile unsigned int timer[2]; //0x00080038 .. 0x0008003C
volatile unsigned int irq; //0x00080040 .. 0x00080040
volatile unsigned int dummy2; //0x00080044 .. 0x00080044
volatile unsigned int status; //0x00080048 .. 0x00080048
volatile unsigned int pc; //0x0008004C .. 0x0008004C
volatile unsigned int fsm_state; //0x00080050 .. 0x00080050
} S_xdev;
typedef volatile unsigned int S_tcm;
S_xen* p_xen0 = (S_xen*) (0x20000000);
S_xen* p_xen1 = (S_xen*) (0x20100000);
......@@ -278,6 +322,8 @@ int xentium_kernel_load(struct xen_kernel *x, void *p)
if (xentium_load_kernel(x))
goto cleanup;
p_xen0->mlbx[0] = 0x30000000;
// p_xen1->mlbx[0] = 0x30000000;
if (_xen.cnt == _xen.sz) {
......
......@@ -382,15 +382,12 @@ static unsigned int ar_get_filecount(char *p, struct archive *a)
/**
* @brief print symbols in the archive
* @brief print list of symbols in the archive
*
* @param a a struct archive
* @param name the file name to search for
*
* @return a pointer or NULL if not found
*/
void ar_list_symbols(struct archive *a)
void ar_print_symbols(struct archive *a)
{
unsigned long i;
......@@ -421,15 +418,12 @@ void ar_list_symbols(struct archive *a)
/**
* @brief print files in the archive
* @brief print list of files in the archive
*
* @param a a struct archive
* @param name the file name to search for
*
* @return a pointer or NULL if not found
*/
void ar_list_files(struct archive *a)
void ar_print_files(struct archive *a)
{
unsigned long i;
......@@ -459,6 +453,57 @@ void ar_list_files(struct archive *a)
}
/**
* @brief get a space-separated list of file names in the archive
*
* @param a a struct archive
*
* @return a pointer or NULL if not found
*/
char *ar_get_file_list(struct archive *a)
{
unsigned long i;
size_t sz = 0;
char *files = NULL;
if (!a)
goto exit;
if (!a->fname)
goto exit;
if (!a->fnamesz)
goto exit;
for (i = 0; i < a->n_file; i++)
sz += a->fnamesz[i] + 1;
if (!sz)
goto exit;
files = (char *) kzalloc(sz);
if (!files)
goto exit;
sz = 0;
for (i = 0; i < a->n_file; i++) {
memcpy(&files[sz], a->fname[i], a->fnamesz[i]);
sz += a->fnamesz[i];
files[sz++] = ' ';
}
/* terminate end of string */
files[sz - 1] = '\0';
exit:
return files;
}
/**
* @brief return a pointer to an archive file
......
......@@ -7,8 +7,10 @@
*/
#include <kernel/kmem.h>
#include <kernel/export.h>
#include <kernel/types.h>
#include <kernel/string.h>
/**
......@@ -90,8 +92,8 @@ char *strsep(char **stringp, const char *delim)
end = strpbrk(start, delim);
if (end) {
(*end)++;
(*end) = '\0';
end++;
}
*stringp = end;
......@@ -101,6 +103,34 @@ char *strsep(char **stringp, const char *delim)
EXPORT_SYMBOL(strsep);
/**
* @brief return a pointer to a new string which is a duplicate of string s
*
* @parm s the string to duplicate
*
* @note the pointer is allocated using kmalloc() and may be freed with kfree()
*/
char *strdup(const char *s)
{
size_t len;
char *dup;
if (!s)
return NULL;
len = strlen(s) + 1;
dup = kzalloc(len);
if (dup)
memcpy(dup, s, len);
return dup;
}
EXPORT_SYMBOL(strdup);
/**
* @brief calculate the length of a string
*
......@@ -121,6 +151,82 @@ size_t strlen(const char *s)
EXPORT_SYMBOL(strlen);
/**
* @brief finds the first occurrence of the substring needle in the string
* haystack
*
* @param haystack the string to be searched
* @param needle the string to search for
*
* @returns a pointer to the beginning of a substring or NULL if not found
*/
char *strstr(const char *haystack, const char *needle)
{
size_t len_h;
size_t len_n;
len_n = strlen(needle);
if (!len_n)
return (char *) haystack;
len_h = strlen(haystack);
for ( ; len_h >= len_n; len_h--) {
if (!memcmp(haystack, needle, len_n))
return (char *) haystack;
haystack++;
}
return NULL;
}
EXPORT_SYMBOL(strstr);
/**
* @brief compares the first n bytes of the memory areas s1 and s2
*
* @param s1 the first string
* @param s2 the second string
* @param n the number of bytes to compare
*
* @returns <0, 0 or > 0 if s1 is the first n bytes are found of s1 are found to
* be less than, to match or be greater than s2
*
* @note s1 and s2 are interpreted as unsigned char
*/
int memcmp(const void *s1, const void *s2, size_t n)
{
const unsigned char *su1, *su2;
int res = 0;
su1 = (const unsigned char *) s1;
su2 = (const unsigned char *) s2;
while (n) {
if ((*su1) != (*su2)) {
if ((*su1) < (*su2))
return -1;
else
return 1;
}
su1++;
su2++;
n--;
}
return 0;
}
EXPORT_SYMBOL(memcmp);
/**
* @brief copy a memory area
*
......
......@@ -294,18 +294,21 @@ fi
# this is a 3rd pass option, we need modules.order beforehand
if [ "$1" = "embed" ]; then
if [ ! -s ${srctree}/modules.order ]; then
echo >&2
echo >&2 modules.order empty or nonexistant, cannot embed image.
echo >&2 Maybe you have no loadable modules configured?
echo >&2 Kernel image unchanged.
echo >&2
exit
fi
# if [ ! -s ${srctree}/modules.order ]; then
# echo >&2
# echo >&2 modules.order empty or nonexistant, cannot embed image.
# echo >&2 Maybe you have no loadable modules configured?
# echo >&2 Kernel image unchanged.
# echo >&2
# exit
# fi
embedflags="-Wl,--format=binary -Wl,modules.image -Wl,--format=default"
rm -f modules.image
${AR} rcs ${srctree}/modules.image $(tr '\n' ' ' < ${srctree}/modules.order)
${AR} rcs ${srctree}/modules.image \
$(tr '\n' ' ' < ${srctree}/modules.order) \
$(find dsp/xentium -name *.xen)
leanos_link "${kallsymso}" leanos "${embedflags}"
exit
fi
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment