From 050f537884afb02b580024fa9f198b167f130195 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Wed, 28 Oct 2009 14:11:43 +0200 Subject: [PATCH 1/7] Bare container type is converted to Examples container type. Examples container type is designed to keep applications using codezero userspace libraries, which is aiming to help newcomers who would like to develop programs on top of the l4 microkernel. Now bare bone application is one of the examples. In the near future, lots of new programs will be introduced to show the various aspects of codezero eco-system. --- config/cml/container_ruleset.template | 34 ++++++++---- config/configuration.py | 9 ++- configure.py | 8 +-- .../example0}/SConstruct | 32 +++++------ .../example0}/container.c | 2 +- .../example0}/include/test.h | 0 conts/examples/example0/main.c | 12 ++++ .../example0}/src/test.c | 0 conts/examples/example1/SConstruct | 55 +++++++++++++++++++ conts/examples/example1/container.c | 21 +++++++ conts/{bare_src => examples/example1}/hello.c | 0 .../examples/example1/include/test.h | 0 conts/{bare_src => examples/example1}/main.c | 0 .../examples/example1/src/test.c | 0 scripts/conts/containers.py | 6 +- scripts/examples/__init__.py | 0 .../examples_generator.py} | 49 +++++++++-------- scripts/examples/files/SConstruct.in | 0 .../{bare => examples}/files/build.readme.in | 0 .../files/container.desc.in | 0 .../{bare => examples}/files/container.h.in | 0 .../{bare => examples}/files/linker.lds.in | 0 22 files changed, 162 insertions(+), 66 deletions(-) rename conts/{bare_src => examples/example0}/SConstruct (53%) rename conts/{bare_src => examples/example0}/container.c (91%) rename conts/{bare_src => examples/example0}/include/test.h (100%) create mode 100644 conts/examples/example0/main.c rename conts/{bare_src => examples/example0}/src/test.c (100%) create mode 100644 conts/examples/example1/SConstruct create mode 100644 conts/examples/example1/container.c rename conts/{bare_src => examples/example1}/hello.c (100%) rename scripts/bare/__init__.py => conts/examples/example1/include/test.h (100%) rename conts/{bare_src => examples/example1}/main.c (100%) rename scripts/bare/files/SConstruct.in => conts/examples/example1/src/test.c (100%) create mode 100644 scripts/examples/__init__.py rename scripts/{bare/bare_generator.py => examples/examples_generator.py} (78%) create mode 100644 scripts/examples/files/SConstruct.in rename scripts/{bare => examples}/files/build.readme.in (100%) rename scripts/{bare => examples}/files/container.desc.in (100%) rename scripts/{bare => examples}/files/container.h.in (100%) rename scripts/{bare => examples}/files/linker.lds.in (100%) diff --git a/config/cml/container_ruleset.template b/config/cml/container_ruleset.template index 67e55fd..d06580f 100644 --- a/config/cml/container_ruleset.template +++ b/config/cml/container_ruleset.template @@ -1,6 +1,6 @@ symbols CONT%(cn)d_TYPE_LINUX 'Linux Container' -CONT%(cn)d_TYPE_BARE 'Bare Container' +CONT%(cn)d_TYPE_EXAMPLES 'Examples Container' CONT%(cn)d_TYPE_POSIX 'Codezero POSIX Services' CONT%(cn)d_TYPE_TEST 'Test Container' CONT%(cn)d_OPT_NAME 'Container Name' @@ -113,12 +113,12 @@ default CONT%(cn)d_VIRT4_END from 0x0 default CONT%(cn)d_VIRT5_START from 0x0 default CONT%(cn)d_VIRT5_END from 0x0 -default CONT%(cn)d_OPT_NAME from (CONT%(cn)d_TYPE_LINUX==y) ? "linux%(cn)d" : ((CONT%(cn)d_TYPE_BARE==y) ? "bare%(cn)d" : ((CONT%(cn)d_TYPE_TEST==y) ? "test%(cn)d" : "posix%(cn)d")) +default CONT%(cn)d_OPT_NAME from (CONT%(cn)d_TYPE_LINUX==y) ? "linux%(cn)d" : ((CONT%(cn)d_TYPE_EXAMPLES==y) ? "example%(cn)d" : ((CONT%(cn)d_TYPE_TEST==y) ? "test%(cn)d" : "posix%(cn)d")) -when CONT%(cn)d_TYPE_LINUX==y suppress cont%(cn)d_bare_pager_params cont%(cn)d_posix_pager_params -when CONT%(cn)d_TYPE_BARE==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_posix_pager_params -when CONT%(cn)d_TYPE_TEST==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_posix_pager_params -when CONT%(cn)d_TYPE_POSIX==y suppress cont%(cn)d_linux_pager_params +when CONT%(cn)d_TYPE_LINUX==y suppress cont%(cn)d_default_pager_params cont%(cn)d_posix_pager_params cont%(cn)d_examples_params +when CONT%(cn)d_TYPE_EXAMPLES==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_posix_pager_params +when CONT%(cn)d_TYPE_TEST==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_posix_pager_params cont%(cn)d_examples_params +when CONT%(cn)d_TYPE_POSIX==y suppress cont%(cn)d_linux_pager_params cont%(cn)d_examples_params symbols cont%(cn)d_menu 'Container %(cn)d Parameters' @@ -128,10 +128,20 @@ container%(cn)d_type 'Container %(cn)d Type' container%(cn)d_options 'Container %(cn)d Options' cont%(cn)d_linux_pager_params 'Container %(cn)d Linux Pager Parameters' -cont%(cn)d_bare_pager_params 'Container %(cn)d Default Pager Parameters' +cont%(cn)d_default_pager_params 'Container %(cn)d Default Pager Parameters' cont%(cn)d_posix_pager_params 'Container %(cn)d POSIX Pager Parameters' -menu cont%(cn)d_bare_pager_params +cont%(cn)d_examples_params 'Example Applications List' +CONT%(cn)d_EXAMPLE_APP0 'Empty Application' +CONT%(cn)d_EXAMPLE_APP1 'Hello world' + + +choices cont%(cn)d_examples_params + CONT%(cn)d_EXAMPLE_APP0 + CONT%(cn)d_EXAMPLE_APP1 + default CONT%(cn)d_EXAMPLE_APP0 + +menu cont%(cn)d_default_pager_params CONT%(cn)d_PAGER_LMA@ CONT%(cn)d_PAGER_VMA@ @@ -178,20 +188,20 @@ menu cont%(cn)d_physmem_list menu container%(cn)d_options CONT%(cn)d_OPT_NAME$ + cont%(cn)d_examples_params cont%(cn)d_linux_pager_params - cont%(cn)d_bare_pager_params + cont%(cn)d_default_pager_params cont%(cn)d_posix_pager_params cont%(cn)d_physmem_list cont%(cn)d_virtmem_list choices container%(cn)d_type CONT%(cn)d_TYPE_LINUX - CONT%(cn)d_TYPE_BARE + CONT%(cn)d_TYPE_EXAMPLES CONT%(cn)d_TYPE_POSIX CONT%(cn)d_TYPE_TEST - default CONT%(cn)d_TYPE_BARE + default CONT%(cn)d_TYPE_EXAMPLES menu cont%(cn)d_menu container%(cn)d_type container%(cn)d_options - diff --git a/config/configuration.py b/config/configuration.py index 0e9bf59..6c0de05 100644 --- a/config/configuration.py +++ b/config/configuration.py @@ -10,6 +10,7 @@ class Container: self.name = None self.type = None self.id = id + self.example_id = 0 self.pager_lma = 0 self.pager_vma = 0 self.pager_size = 0 @@ -167,6 +168,9 @@ class configuration: dirname = val[1:-1].lower() self.containers[id].dirname = dirname self.containers[id].name = dirname + elif param[:len("EXAMPLE_APP")] == "EXAMPLE_APP": + param1 = param.split("_", 1) + self.containers[id].example_id = param1[1][-1:] else: param1, param2 = param.split("_", 1) if param1 == "TYPE": @@ -174,11 +178,10 @@ class configuration: self.containers[id].type = "linux" elif param2 == "POSIX": self.containers[id].type = "posix" - elif param2 == "BARE": - self.containers[id].type = "bare" + elif param2 == "EXAMPLES": + self.containers[id].type = "examples" elif param2 == "TEST": self.containers[id].type = "test" - # Extract parameters for containers def get_container_parameters(self, name, val): matchobj = re.match(r"(CONFIG_CONT){1}([0-9]){1}(\w+)", name) diff --git a/configure.py b/configure.py index 28d75d6..617bfa0 100755 --- a/configure.py +++ b/configure.py @@ -4,7 +4,7 @@ import os, sys, shelve, shutil from os.path import join from config.projpaths import * from config.configuration import * -from scripts.bare.bare_generator import * +from scripts.examples.examples_generator import * from scripts.kernel.generate_kernel_cinfo import * from scripts.cml.generate_container_cml import * from optparse import OptionParser @@ -185,9 +185,9 @@ def configure_system(options, args): configuration_save(config) - # Generate bare container files if new ones defined - bare_cont_gen = BareContGenerator() - bare_cont_gen.bare_container_generate(config) + # Generate example container files if new ones defined + examples_cont_gen = ExamplesContGenerator() + examples_cont_gen.examples_container_generate(config) # Print out the configuration if asked if options.print_config: diff --git a/conts/bare_src/SConstruct b/conts/examples/example0/SConstruct similarity index 53% rename from conts/bare_src/SConstruct rename to conts/examples/example0/SConstruct index 3bd1575..23e059c 100644 --- a/conts/bare_src/SConstruct +++ b/conts/examples/example0/SConstruct @@ -13,45 +13,39 @@ sys.path.append(PROJRELROOT) from config.projpaths import * from config.configuration import * -from configure import * + config = configuration_retrieve() -arch = config.arch -gcc_cpu_flag = config.gcc_cpu_flag -# Wrapper library for system calls +arch = config.arch + LIBL4_RELDIR = 'conts/libl4' KERNEL_INCLUDE = join(PROJROOT, 'include') LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR) LIBL4_INCLUDE = join(LIBL4_DIR, 'include') LIBL4_LIBPATH = join(BUILDDIR, LIBL4_RELDIR) -# Some user-space libraries +# Locally important paths are here LIBC_RELDIR = 'conts/libc' LIBC_DIR = join(PROJROOT, LIBC_RELDIR) LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR) LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \ join(LIBC_DIR, 'include/arch' + '/' + arch)] -LIBMEM_RELDIR = 'conts/libmem' -LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) -LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR) -LIBMEM_INCLUDE = LIBMEM_DIR -env = Environment(CC = config.user_toolchain + 'gcc', +env = Environment(CC = 'arm-none-linux-gnueabi-gcc', # We don't use -nostdinc because sometimes we need standard headers, # such as stdarg.h e.g. for variable args, as in printk(). - CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', \ - '-Werror', ('-mcpu=' + gcc_cpu_flag)], \ + CCFLAGS = ['-g', '-mcpu=arm926ej-s', '-nostdlib', '-ffreestanding', \ + '-std=gnu99', '-Wall', '-Werror'], \ LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"],\ ASFLAGS = ['-D__ASSEMBLY__'], \ - PROGSUFFIX = '.elf', # The suffix to use for final executable - ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path - LIBS = ['gcc', 'libl4', 'c-userspace', 'libmm', 'libmc', 'libmalloc', \ - 'gcc', 'c-userspace'], # libgcc.a - This is required for division routines. - CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBC_INCLUDE, LIBMEM_INCLUDE], - LIBPATH = [LIBL4_LIBPATH, LIBC_LIBPATH, LIBMEM_LIBPATH], - CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h') + PROGSUFFIX = '.elf', # The suffix to use for final executable\ + ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path\ + LIBS = ['gcc', 'libl4', 'c-userspace', 'gcc', 'c-userspace'], # libgcc.a - This is required for division routines. + CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBC_INCLUDE], + LIBPATH = [LIBL4_LIBPATH, LIBC_LIBPATH], + CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h') src = Glob('*.[cS]') src += Glob('src/*.[cS]') diff --git a/conts/bare_src/container.c b/conts/examples/example0/container.c similarity index 91% rename from conts/bare_src/container.c rename to conts/examples/example0/container.c index 7bcbf9e..f570c3d 100644 --- a/conts/bare_src/container.c +++ b/conts/examples/example0/container.c @@ -8,7 +8,7 @@ #include -void main(void); +extern void main(void); void __container_init(void) { diff --git a/conts/bare_src/include/test.h b/conts/examples/example0/include/test.h similarity index 100% rename from conts/bare_src/include/test.h rename to conts/examples/example0/include/test.h diff --git a/conts/examples/example0/main.c b/conts/examples/example0/main.c new file mode 100644 index 0000000..8397a52 --- /dev/null +++ b/conts/examples/example0/main.c @@ -0,0 +1,12 @@ +/* + * Main function for this container + */ +#include +#include +#include + +int main(void) +{ + return 0; +} + diff --git a/conts/bare_src/src/test.c b/conts/examples/example0/src/test.c similarity index 100% rename from conts/bare_src/src/test.c rename to conts/examples/example0/src/test.c diff --git a/conts/examples/example1/SConstruct b/conts/examples/example1/SConstruct new file mode 100644 index 0000000..23e059c --- /dev/null +++ b/conts/examples/example1/SConstruct @@ -0,0 +1,55 @@ +# -*- mode: python; coding: utf-8; -*- +# +# Codezero -- Virtualization microkernel for embedded systems. +# +# Copyright © 2009 B Labs Ltd +# +import os, shelve, sys +from os.path import * + +PROJRELROOT = '../..' + +sys.path.append(PROJRELROOT) + +from config.projpaths import * +from config.configuration import * + + +config = configuration_retrieve() + +arch = config.arch + +LIBL4_RELDIR = 'conts/libl4' +KERNEL_INCLUDE = join(PROJROOT, 'include') +LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR) +LIBL4_INCLUDE = join(LIBL4_DIR, 'include') +LIBL4_LIBPATH = join(BUILDDIR, LIBL4_RELDIR) + +# Locally important paths are here +LIBC_RELDIR = 'conts/libc' +LIBC_DIR = join(PROJROOT, LIBC_RELDIR) +LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR) +LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \ + join(LIBC_DIR, 'include/arch' + '/' + arch)] + + +env = Environment(CC = 'arm-none-linux-gnueabi-gcc', + # We don't use -nostdinc because sometimes we need standard headers, + # such as stdarg.h e.g. for variable args, as in printk(). + CCFLAGS = ['-g', '-mcpu=arm926ej-s', '-nostdlib', '-ffreestanding', \ + '-std=gnu99', '-Wall', '-Werror'], \ + LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"],\ + ASFLAGS = ['-D__ASSEMBLY__'], \ + PROGSUFFIX = '.elf', # The suffix to use for final executable\ + ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path\ + LIBS = ['gcc', 'libl4', 'c-userspace', 'gcc', 'c-userspace'], # libgcc.a - This is required for division routines. + CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBC_INCLUDE], + LIBPATH = [LIBL4_LIBPATH, LIBC_LIBPATH], + CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h') + +src = Glob('*.[cS]') +src += Glob('src/*.[cS]') + +objs = env.Object(src) +prog = env.Program('main.elf', objs) +Depends(prog, 'include/linker.lds') diff --git a/conts/examples/example1/container.c b/conts/examples/example1/container.c new file mode 100644 index 0000000..f570c3d --- /dev/null +++ b/conts/examples/example1/container.c @@ -0,0 +1,21 @@ +/* + * Container entry point for pager + * + * Copyright (C) 2007-2009 B Labs Ltd. + */ + +#include +#include + + +extern void main(void); + +void __container_init(void) +{ + /* Generic L4 initialisation */ + __l4_init(); + + /* Entry to main */ + main(); +} + diff --git a/conts/bare_src/hello.c b/conts/examples/example1/hello.c similarity index 100% rename from conts/bare_src/hello.c rename to conts/examples/example1/hello.c diff --git a/scripts/bare/__init__.py b/conts/examples/example1/include/test.h similarity index 100% rename from scripts/bare/__init__.py rename to conts/examples/example1/include/test.h diff --git a/conts/bare_src/main.c b/conts/examples/example1/main.c similarity index 100% rename from conts/bare_src/main.c rename to conts/examples/example1/main.c diff --git a/scripts/bare/files/SConstruct.in b/conts/examples/example1/src/test.c similarity index 100% rename from scripts/bare/files/SConstruct.in rename to conts/examples/example1/src/test.c diff --git a/scripts/conts/containers.py b/scripts/conts/containers.py index 4514880..a0cb77f 100755 --- a/scripts/conts/containers.py +++ b/scripts/conts/containers.py @@ -55,7 +55,7 @@ def source_to_builddir(srcdir, id): return join(BUILDDIR, cont_builddir) # We simply use SCons to figure all this out from container.id -# This is very similar to default container builder: +# This is very similar to examples container builder: # In fact this notion may become a standard convention for # calling specific bare containers def build_posix_container(config, projpaths, container): @@ -110,7 +110,7 @@ def build_default_container(config, projpaths, container): os.path.walk(projdir, glob_by_walk, ['*.elf', images]) # Calculate and store size of pager - pager_binary = "conts/bare" + str(container.id) + "/main.elf" + pager_binary = "conts/example" + str(container.id) + "/main.elf" config.containers[container.id].pager_size = \ conv_hex(elf_binary_size(join(PROJROOT, pager_binary))) @@ -124,7 +124,7 @@ def build_all_containers(): if container.type == 'linux': pass cont_images.append(build_linux_container(config, projpaths, container)) - elif container.type == 'bare': + elif container.type == 'examples': cont_images.append(build_default_container(config, projpaths, container)) elif container.type == 'posix': cont_images.append(build_posix_container(config, projpaths, container)) diff --git a/scripts/examples/__init__.py b/scripts/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/bare/bare_generator.py b/scripts/examples/examples_generator.py similarity index 78% rename from scripts/bare/bare_generator.py rename to scripts/examples/examples_generator.py index 3c6f1c2..17663d7 100755 --- a/scripts/bare/bare_generator.py +++ b/scripts/examples/examples_generator.py @@ -19,11 +19,11 @@ from config.projpaths import * from config.configuration import * from config.lib import * -class BareContGenerator: +class ExamplesContGenerator: def __init__(self): self.CONT_SRC_DIR = '' # Set when container is selected - self.BARE_SRC_BASEDIR = join(PROJROOT, 'conts') - self.EXAMPLE_PROJ_SRC_DIR = join(PROJROOT, 'conts/bare_src') + self.EXAMPLES_SRC_BASEDIR = join(PROJROOT, 'conts') + self.EXAMPLES_PROJ_SRC_DIR = join(PROJROOT, 'conts/examples') self.main_builder_name = 'build.py' self.main_configurator_name = 'configure.py' @@ -47,11 +47,12 @@ class BareContGenerator: self.build_desc_out = None self.src_main_out = None - def create_bare_srctree(self, config, cont): + def create_examples_srctree(self, config, cont): # First, create the base project directory and sources - shutil.copytree(self.EXAMPLE_PROJ_SRC_DIR, self.CONT_SRC_DIR) + str = 'example' + cont.example_id + shutil.copytree(join(self.EXAMPLES_PROJ_SRC_DIR, str), self.CONT_SRC_DIR) - def copy_bare_build_desc(self, config, cont): + def copy_examples_build_desc(self, config, cont): id_header = '[Container ID]\n' type_header = '\n[Container Type]\n' name_header = '\n[Container Name]\n' @@ -78,7 +79,7 @@ class BareContGenerator: fout.write(pager_physmem_header % ireg) fout.write('\t' + cont.physmem["START"][ireg] + ' - ' + cont.physmem["END"][ireg] + '\n') - def copy_bare_build_readme(self, config, cont): + def copy_examples_build_readme(self, config, cont): with open(self.build_readme_in) as fin: str = fin.read() with open(self.build_readme_out, 'w+') as fout: @@ -90,30 +91,30 @@ class BareContGenerator: self.main_configurator_name, \ self.main_configurator_name)) - def copy_bare_container_h(self, config, cont): + def copy_examples_container_h(self, config, cont): with open(self.container_h_in) as fin: str = fin.read() with open(self.container_h_out, 'w+') as fout: # Make any manipulations here fout.write(str % (cont.name, cont.id, cont.id)) - def create_bare_sources(self, config, cont): - self.create_bare_srctree(config, cont) - self.copy_bare_build_readme(config, cont) - self.copy_bare_build_desc(config, cont) + def create_examples_sources(self, config, cont): + self.create_examples_srctree(config, cont) + self.copy_examples_build_readme(config, cont) + self.copy_examples_build_desc(config, cont) self.generate_linker_script(config, cont) - self.copy_bare_container_h(config, cont) + self.copy_examples_container_h(config, cont) def update_configuration(self, config, cont): - self.copy_bare_build_desc(config, cont) + self.copy_examples_build_desc(config, cont) self.generate_linker_script(config, cont) - self.copy_bare_container_h(config, cont) + self.copy_examples_container_h(config, cont) - def check_create_bare_sources(self, config): + def check_create_examples_sources(self, config): for cont in config.containers: - if cont.type == "bare": + if cont.type == "examples": # Determine container directory name. - self.CONT_SRC_DIR = join(self.BARE_SRC_BASEDIR, cont.dirname.lower()) + self.CONT_SRC_DIR = join(self.EXAMPLES_SRC_BASEDIR, cont.dirname.lower()) self.build_readme_out = join(self.CONT_SRC_DIR, self.build_readme_name) self.build_desc_out = join(self.CONT_SRC_DIR, self.build_desc_name) self.linker_lds_out = join(join(self.CONT_SRC_DIR, 'include'), \ @@ -121,8 +122,8 @@ class BareContGenerator: self.container_h_out = join(join(self.CONT_SRC_DIR, 'include'), \ self.container_h_name) - if not os.path.exists(join(self.BARE_SRC_BASEDIR, cont.dirname)): - self.create_bare_sources(config, cont) + if not os.path.exists(join(self.EXAMPLES_SRC_BASEDIR, cont.dirname)): + self.create_examples_sources(config, cont) else: # Don't create new sources but update configuration self.update_configuration(config, cont) @@ -134,12 +135,12 @@ class BareContGenerator: fout.write(str % (conv_hex(cont.pager_vma), \ conv_hex(cont.pager_lma))) - def bare_container_generate(self, config): - self.check_create_bare_sources(config) + def examples_container_generate(self, config): + self.check_create_examples_sources(config) if __name__ == "__main__": config = configuration_retrieve() config.config_print() - bare_cont = BareContGenerator() - bare_cont.bare_container_generate(config) + examples_cont = ExamplesContGenerator() + examples_cont.examples_container_generate(config) diff --git a/scripts/examples/files/SConstruct.in b/scripts/examples/files/SConstruct.in new file mode 100644 index 0000000..e69de29 diff --git a/scripts/bare/files/build.readme.in b/scripts/examples/files/build.readme.in similarity index 100% rename from scripts/bare/files/build.readme.in rename to scripts/examples/files/build.readme.in diff --git a/scripts/bare/files/container.desc.in b/scripts/examples/files/container.desc.in similarity index 100% rename from scripts/bare/files/container.desc.in rename to scripts/examples/files/container.desc.in diff --git a/scripts/bare/files/container.h.in b/scripts/examples/files/container.h.in similarity index 100% rename from scripts/bare/files/container.h.in rename to scripts/examples/files/container.h.in diff --git a/scripts/bare/files/linker.lds.in b/scripts/examples/files/linker.lds.in similarity index 100% rename from scripts/bare/files/linker.lds.in rename to scripts/examples/files/linker.lds.in From 1f7711fa2a74cbb0da8501764c845f84315de348 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Thu, 5 Nov 2009 11:32:02 +0200 Subject: [PATCH 2/7] Automatic pager size calculation takes container name into account instead of a fixed one. --- scripts/conts/containers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/conts/containers.py b/scripts/conts/containers.py index a0cb77f..f42bca9 100755 --- a/scripts/conts/containers.py +++ b/scripts/conts/containers.py @@ -110,7 +110,7 @@ def build_default_container(config, projpaths, container): os.path.walk(projdir, glob_by_walk, ['*.elf', images]) # Calculate and store size of pager - pager_binary = "conts/example" + str(container.id) + "/main.elf" + pager_binary = "conts/" + container.name + "/main.elf" config.containers[container.id].pager_size = \ conv_hex(elf_binary_size(join(PROJROOT, pager_binary))) From 4bfd339db51941a5277e08492e0e4b999316db15 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Thu, 29 Oct 2009 22:00:38 +0200 Subject: [PATCH 3/7] libl4thread skeleton is introduced. With this library, it is aimed at easing thread manipulation, utcb handling etc. --- SConstruct.userlibs | 4 ++++ conts/libl4thread/SConscript | 25 +++++++++++++++++++++ conts/libl4thread/include/l4thread/thread.h | 9 ++++++++ conts/libl4thread/src/thread.c | 10 +++++++++ 4 files changed, 48 insertions(+) create mode 100644 conts/libl4thread/SConscript create mode 100644 conts/libl4thread/include/l4thread/thread.h create mode 100644 conts/libl4thread/src/thread.c diff --git a/SConstruct.userlibs b/SConstruct.userlibs index 330883b..599b814 100644 --- a/SConstruct.userlibs +++ b/SConstruct.userlibs @@ -44,9 +44,13 @@ libmm, libmc, libmalloc = SConscript('conts/libmem/SConscript', \ duplicate = 0, variant_dir = \ join(BUILDDIR, os.path.relpath('conts/libmem', PROJROOT))) +libl4thread = SConscript('conts/libl4thread/SConscript', \ + exports = { 'env' : env }, duplicate = 0, \ + variant_dir = join(BUILDDIR, os.path.relpath('conts/libl4thread', PROJROOT))) Alias('libl4', libl4) Alias('libc', libc) Alias('libmm', libmm) Alias('libmc', libmc) Alias('libmalloc', libmalloc) +Alias('libl4thread', libl4thread) diff --git a/conts/libl4thread/SConscript b/conts/libl4thread/SConscript new file mode 100644 index 0000000..2ca1bf8 --- /dev/null +++ b/conts/libl4thread/SConscript @@ -0,0 +1,25 @@ +# -*- mode: python; coding: utf-8; -*- +# +# Codezero -- Virtualization microkernel for embedded systems. +# +# Copyright © 2009 B Labs Ltd + +import os, sys + +# Get global paths +PROJRELROOT = '../..' + +sys.path.append(PROJRELROOT) + +from config.projpaths import * + +Import('env') + +e = env.Clone() +e.Append(CPPPATH = ['include/l4thread']) + +source = [Glob('*.[cS]') + Glob('src/*.[cS]')] +objects = e.StaticObject(source) +library = e.StaticLibrary('l4thread', objects) + +Return('library') diff --git a/conts/libl4thread/include/l4thread/thread.h b/conts/libl4thread/include/l4thread/thread.h new file mode 100644 index 0000000..31ced16 --- /dev/null +++ b/conts/libl4thread/include/l4thread/thread.h @@ -0,0 +1,9 @@ +/* + * + */ +#ifndef __LIB_THREAD_H__ +#define __LIB_THREAD_H__ + +void l4thread_print(void); + +#endif /* __LIB_THREAD_H__ */ diff --git a/conts/libl4thread/src/thread.c b/conts/libl4thread/src/thread.c new file mode 100644 index 0000000..21b574a --- /dev/null +++ b/conts/libl4thread/src/thread.c @@ -0,0 +1,10 @@ +/* + * + */ + +#include + +void l4thread_print(void) +{ + printf("Hello world from libl4thread!\n"); +} From ede050ad3750c0abfb3b4c9635609ff06d437483 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Thu, 29 Oct 2009 22:11:49 +0200 Subject: [PATCH 4/7] utcb handling helper routines for the thread library. This is one of the steps we need in the process of providing a similar interface for thread creation which can be found in the mainstream operating systems like Linux. --- conts/libl4thread/SConscript | 5 +- conts/libl4thread/include/l4thread/addr.h | 26 +++++ conts/libl4thread/include/l4thread/bit.h | 42 ++++++++ conts/libl4thread/include/l4thread/idpool.h | 30 ++++++ conts/libl4thread/include/l4thread/utcb.h | 25 +++++ conts/libl4thread/src/addr.c | 55 ++++++++++ conts/libl4thread/src/bit.c | 109 ++++++++++++++++++++ conts/libl4thread/src/idpool.c | 86 +++++++++++++++ conts/libl4thread/src/thread.c | 3 +- conts/libl4thread/src/utcb.c | 88 ++++++++++++++++ conts/libl4thread/src/utcb_test.c | 55 ++++++++++ 11 files changed, 522 insertions(+), 2 deletions(-) create mode 100644 conts/libl4thread/include/l4thread/addr.h create mode 100644 conts/libl4thread/include/l4thread/bit.h create mode 100644 conts/libl4thread/include/l4thread/idpool.h create mode 100644 conts/libl4thread/include/l4thread/utcb.h create mode 100644 conts/libl4thread/src/addr.c create mode 100644 conts/libl4thread/src/bit.c create mode 100644 conts/libl4thread/src/idpool.c create mode 100644 conts/libl4thread/src/utcb.c create mode 100644 conts/libl4thread/src/utcb_test.c diff --git a/conts/libl4thread/SConscript b/conts/libl4thread/SConscript index 2ca1bf8..876bf5c 100644 --- a/conts/libl4thread/SConscript +++ b/conts/libl4thread/SConscript @@ -15,8 +15,11 @@ from config.projpaths import * Import('env') +LIBMEM_RELDIR = 'conts/libmem' +LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) + e = env.Clone() -e.Append(CPPPATH = ['include/l4thread']) +e.Append(CPPPATH = ['include/l4thread', LIBMEM_DIR]) source = [Glob('*.[cS]') + Glob('src/*.[cS]')] objects = e.StaticObject(source) diff --git a/conts/libl4thread/include/l4thread/addr.h b/conts/libl4thread/include/l4thread/addr.h new file mode 100644 index 0000000..5bbc69d --- /dev/null +++ b/conts/libl4thread/include/l4thread/addr.h @@ -0,0 +1,26 @@ +/* + * Address allocation pool + * + * Copyright (C) 2007 Bahadir Balban + */ +#ifndef __ADDR_H__ +#define __ADDR_H__ + +#include + +/* Address pool to allocate from a range of addresses */ +struct address_pool { + struct id_pool *idpool; + unsigned long start; + unsigned long end; +}; + +int address_pool_init_with_idpool(struct address_pool *pool, + struct id_pool *idpool, + unsigned long start, unsigned long end); +int address_pool_init(struct address_pool *pool, unsigned long start, + unsigned long end); +void *address_new(struct address_pool *pool, int npages); +int address_del(struct address_pool *, void *addr, int npages); + +#endif /* __ADDR_H__ */ diff --git a/conts/libl4thread/include/l4thread/bit.h b/conts/libl4thread/include/l4thread/bit.h new file mode 100644 index 0000000..3ab6822 --- /dev/null +++ b/conts/libl4thread/include/l4thread/bit.h @@ -0,0 +1,42 @@ +#ifndef __BIT_H__ +#define __BIT_H__ + +unsigned int __clz(unsigned int bitvector); +int find_and_set_first_free_bit(u32 *word, unsigned int lastbit); +int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit, + int nbits); +int check_and_clear_bit(u32 *word, int bit); +int check_and_clear_contig_bits(u32 *word, int first, int nbits); + +int check_and_set_bit(u32 *word, int bit); + +/* Set */ +static inline void setbit(unsigned int *w, unsigned int flags) +{ + *w |= flags; +} + + +/* Clear */ +static inline void clrbit(unsigned int *w, unsigned int flags) +{ + *w &= ~flags; +} + +/* Test */ +static inline int tstbit(unsigned int *w, unsigned int flags) +{ + return *w & flags; +} + +/* Test and clear */ +static inline int tstclr(unsigned int *w, unsigned int flags) +{ + int res = tstbit(w, flags); + + clrbit(w, flags); + + return res; +} + +#endif /* __BIT_H__ */ diff --git a/conts/libl4thread/include/l4thread/idpool.h b/conts/libl4thread/include/l4thread/idpool.h new file mode 100644 index 0000000..67667c2 --- /dev/null +++ b/conts/libl4thread/include/l4thread/idpool.h @@ -0,0 +1,30 @@ +#ifndef __IDPOOL_H__ +#define __IDPOOL_H__ + +#include +#include +#include INC_GLUE(memory.h) + +struct id_pool { + int nwords; + int bitlimit; + u32 bitmap[]; +}; + +/* Copy one id pool to another by calculating its size */ +static inline void id_pool_copy(struct id_pool *to, struct id_pool *from, int totalbits) +{ + int nwords = BITWISE_GETWORD(totalbits); + + memcpy(to, from, nwords * SZ_WORD + sizeof(struct id_pool)); +} + +struct id_pool *id_pool_new_init(int mapsize); +int id_new(struct id_pool *pool); +int id_del(struct id_pool *pool, int id); +int id_get(struct id_pool *pool, int id); +int id_is_empty(struct id_pool *pool); +int ids_new_contiguous(struct id_pool *pool, int numids); +int ids_del_contiguous(struct id_pool *pool, int first, int numids); + +#endif /* __IDPOOL_H__ */ diff --git a/conts/libl4thread/include/l4thread/utcb.h b/conts/libl4thread/include/l4thread/utcb.h new file mode 100644 index 0000000..464bd45 --- /dev/null +++ b/conts/libl4thread/include/l4thread/utcb.h @@ -0,0 +1,25 @@ +/* + * UTCB handling helper routines + * + * Copyright (C) 2009 B Labs Ltd. + */ +#ifndef __UTCB_H__ +#define __UTCB_H__ + +#include + +struct utcb_desc { + struct link list; + unsigned long utcb_base; + struct id_pool *slots; +}; + +int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end); + +unsigned long utcb_new_slot(struct utcb_desc *desc); +int utcb_delete_slot(struct utcb_desc *desc, unsigned long address); + +struct utcb_desc *utcb_new_desc(void); +int utcb_delete_desc(struct utcb_desc *desc); + +#endif /* __UTCB_H__ */ diff --git a/conts/libl4thread/src/addr.c b/conts/libl4thread/src/addr.c new file mode 100644 index 0000000..10206bd --- /dev/null +++ b/conts/libl4thread/src/addr.c @@ -0,0 +1,55 @@ +/* + * This module allocates an unused address range from + * a given memory region defined as the pool range. + * + * Copyright (C) 2007 Bahadir Balban + */ +#include +#include + +/* + * Initializes an address pool, but uses an already + * allocated id pool for it. + */ +int address_pool_init_with_idpool(struct address_pool *pool, + struct id_pool *idpool, + unsigned long start, unsigned long end) +{ + pool->idpool = idpool; + pool->start = start; + pool->end = end; + + return 0; +} + +int address_pool_init(struct address_pool *pool, unsigned long start, unsigned long end) +{ + if ((pool->idpool = id_pool_new_init(__pfn(end - start))) < 0) + return (int)pool->idpool; + pool->start = start; + pool->end = end; + return 0; +} + +void *address_new(struct address_pool *pool, int npages) +{ + unsigned int pfn; + + if ((int)(pfn = ids_new_contiguous(pool->idpool, npages)) < 0) + return 0; + + return (void *)__pfn_to_addr(pfn) + pool->start; +} + +int address_del(struct address_pool *pool, void *addr, int npages) +{ + unsigned long pfn = __pfn(page_align(addr) - pool->start); + + if (ids_del_contiguous(pool->idpool, pfn, npages) < 0) { + printf("%s: Invalid address range returned to " + "virtual address pool.\n", __FUNCTION__); + return -1; + } + return 0; +} + diff --git a/conts/libl4thread/src/bit.c b/conts/libl4thread/src/bit.c new file mode 100644 index 0000000..b021211 --- /dev/null +++ b/conts/libl4thread/src/bit.c @@ -0,0 +1,109 @@ +/* + * Bit manipulation functions. + * + * Copyright (C) 2007 Bahadir Balban + */ +#include +#include +#include INC_GLUE(memory.h) + +/* Emulation of ARM's CLZ (count leading zeroes) instruction */ +unsigned int __clz(unsigned int bitvector) +{ + unsigned int x = 0; + while((!(bitvector & ((unsigned)1 << 31))) && (x < 32)) { + bitvector <<= 1; + x++; + } + return x; +} + +int find_and_set_first_free_bit(u32 *word, unsigned int limit) +{ + int success = 0; + int i; + + for(i = 0; i < limit; i++) { + /* Find first unset bit */ + if (!(word[BITWISE_GETWORD(i)] & BITWISE_GETBIT(i))) { + /* Set it */ + word[BITWISE_GETWORD(i)] |= BITWISE_GETBIT(i); + success = 1; + break; + } + } + /* Return bit just set */ + if (success) + return i; + else + return -1; +} + +int find_and_set_first_free_contig_bits(u32 *word, unsigned int limit, + int nbits) +{ + int i = 0, first = 0, last = 0, found = 0; + + /* Can't allocate more than the limit */ + if (nbits > limit) + return -1; + + /* This is a state machine that checks n contiguous free bits. */ + /* FIXME: It should be <= instead of <. Fix & test in a single patch */ + while (i + nbits < limit) { + first = i; + last = i; + while (!(word[BITWISE_GETWORD(last)] & BITWISE_GETBIT(last))) { + last++; + i++; + if (last == first + nbits) { + found = 1; + break; + } + } + if (found) + break; + i++; + } + + /* If found, set the bits */ + if (found) { + for (int x = first; x < first + nbits; x++) + word[BITWISE_GETWORD(x)] |= BITWISE_GETBIT(x); + return first; + } else + return -1; +} + +int check_and_clear_bit(u32 *word, int bit) +{ + /* Check that bit was set */ + if (word[BITWISE_GETWORD(bit)] & BITWISE_GETBIT(bit)) { + word[BITWISE_GETWORD(bit)] &= ~BITWISE_GETBIT(bit); + return 0; + } else { + printf("Trying to clear already clear bit\n"); + return -1; + } +} + +int check_and_set_bit(u32 *word, int bit) +{ + /* Check that bit was clear */ + if (!(word[BITWISE_GETWORD(bit)] & BITWISE_GETBIT(bit))) { + word[BITWISE_GETWORD(bit)] |= BITWISE_GETBIT(bit); + return 0; + } else { + //printf("Trying to set already set bit\n"); + return -1; + } +} + +int check_and_clear_contig_bits(u32 *word, int first, int nbits) +{ + for (int i = first; i < first + nbits; i++) + if (check_and_clear_bit(word, i) < 0) + return -1; + return 0; +} + diff --git a/conts/libl4thread/src/idpool.c b/conts/libl4thread/src/idpool.c new file mode 100644 index 0000000..423ac33 --- /dev/null +++ b/conts/libl4thread/src/idpool.c @@ -0,0 +1,86 @@ +/* + * Used for thread and space ids, and also for utcbs. + * + * Copyright (C) 2009 B Labs Ltd. + */ +#include +#include +#include +#include + +struct id_pool *id_pool_new_init(int totalbits) +{ + int nwords = BITWISE_GETWORD(totalbits) + 1; + struct id_pool *new = kzalloc((nwords * SZ_WORD) + + sizeof(struct id_pool)); + if (!new) + return PTR_ERR(-ENOMEM); + + new->nwords = nwords; + new->bitlimit = totalbits; + + return new; +} + +/* Search for a free slot up to the limit given */ +int id_new(struct id_pool *pool) +{ + return find_and_set_first_free_bit(pool->bitmap, pool->bitlimit); +} + +/* This finds n contiguous free ids, allocates and returns the first one */ +int ids_new_contiguous(struct id_pool *pool, int numids) +{ + int id = find_and_set_first_free_contig_bits(pool->bitmap, + pool->bitlimit, + numids); + if (id < 0) + printf("%s: Warning! New id alloc failed\n", __FUNCTION__); + return id; +} + +/* This deletes a list of contiguous ids given the first one and number of ids */ +int ids_del_contiguous(struct id_pool *pool, int first, int numids) +{ + int ret; + + if (pool->nwords * WORD_BITS < first + numids) + return -1; + if ((ret = check_and_clear_contig_bits(pool->bitmap, first, numids))) + printf("%s: Error: Invalid argument range.\n", __FUNCTION__); + return ret; +} + +int id_del(struct id_pool *pool, int id) +{ + int ret; + + if (pool->nwords * WORD_BITS < id) + return -1; + + if ((ret = check_and_clear_bit(pool->bitmap, id) < 0)) + printf("%s: Error: Could not delete id.\n", __FUNCTION__); + return ret; +} + +/* Return a specific id, if available */ +int id_get(struct id_pool *pool, int id) +{ + int ret; + + ret = check_and_set_bit(pool->bitmap, id); + + if (ret < 0) + return ret; + else + return id; +} + +int id_is_empty(struct id_pool *pool) +{ + for (int i = 0; i < pool->nwords; i++) + if (pool->bitmap[i]) + return 0; + return 1; +} + diff --git a/conts/libl4thread/src/thread.c b/conts/libl4thread/src/thread.c index 21b574a..c362960 100644 --- a/conts/libl4thread/src/thread.c +++ b/conts/libl4thread/src/thread.c @@ -1,9 +1,10 @@ /* * */ - #include +extern void utcb_test(unsigned long utcb_start, unsigned long utcb_end); + void l4thread_print(void) { printf("Hello world from libl4thread!\n"); diff --git a/conts/libl4thread/src/utcb.c b/conts/libl4thread/src/utcb.c new file mode 100644 index 0000000..9dcc187 --- /dev/null +++ b/conts/libl4thread/src/utcb.c @@ -0,0 +1,88 @@ +/* + * UTCB management in Codezero + * + * Copyright © 2009 B Labs Ltd + */ +#include +#include +#include +#include + +/* Globally disjoint utcb virtual region pool */ +static struct address_pool utcb_region_pool; + +int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end) +{ + int err; + + /* Initialise the global utcb virtual address pool */ + if ((err = address_pool_init(&utcb_region_pool, + utcb_start, utcb_end) < 0)) { + printf("UTCB address pool initialisation failed.\n"); + return err; + } + + return 0; +} + +static inline void *utcb_new_address(int npages) +{ + return address_new(&utcb_region_pool, npages); +} + +static inline int utcb_delete_address(void *utcb_address, int npages) +{ + return address_del(&utcb_region_pool, utcb_address, npages); +} + +/* Return an empty utcb slot in this descriptor */ +unsigned long utcb_new_slot(struct utcb_desc *desc) +{ + int slot; + + if ((slot = id_new(desc->slots)) < 0) + return 0; + else + return desc->utcb_base + (unsigned long)slot * UTCB_SIZE; +} + +int utcb_delete_slot(struct utcb_desc *desc, unsigned long address) +{ + BUG_ON(id_del(desc->slots, (address - desc->utcb_base) + / UTCB_SIZE) < 0); + return 0; +} + +struct utcb_desc *utcb_new_desc(void) +{ + struct utcb_desc *d; + + /* Allocate a new descriptor */ + if (!(d = kzalloc(sizeof(*d)))) + return 0; + + link_init(&d->list); + + /* We currently assume UTCB is smaller than PAGE_SIZE */ + BUG_ON(UTCB_SIZE > PAGE_SIZE); + + /* Initialise utcb slots */ + d->slots = id_pool_new_init(PAGE_SIZE / UTCB_SIZE); + + /* Obtain a new and unique utcb base */ + /* FIXME: Use variable size than a page */ + d->utcb_base = (unsigned long)utcb_new_address(1); + + return d; +} + +int utcb_delete_desc(struct utcb_desc *desc) +{ + /* Return descriptor address */ + utcb_delete_address((void *)desc->utcb_base, 1); + + /* Free the descriptor */ + kfree(desc); + + return 0; +} diff --git a/conts/libl4thread/src/utcb_test.c b/conts/libl4thread/src/utcb_test.c new file mode 100644 index 0000000..b05b7ca --- /dev/null +++ b/conts/libl4thread/src/utcb_test.c @@ -0,0 +1,55 @@ +/* + * This is for testing utcb port from POSIX + */ +#include +#include + +void utcb_test(unsigned long utcb_start, unsigned long utcb_end) +{ + struct utcb_desc *udesc[20]; + unsigned long addr; + int idx = -1; + + printf("%s\n", __FUNCTION__); + + utcb_pool_init(utcb_start, utcb_end); + + // Test-1 + for (int i = 0; i < 10; i++) + udesc[++idx] = utcb_new_desc(); + for (int j = 0; j < 20; ++j) + addr = utcb_new_slot(udesc[idx]); + + // Test 2 + for (int i = 0; i < 3; i++) + udesc[++idx] = utcb_new_desc(); + for (int j = 0; j < 10; ++j) + addr = utcb_new_slot(udesc[idx]); + for (int j = 0; j < 8; j++) { + utcb_delete_slot(udesc[idx], addr); + addr -= 0x100; + } + for (int j = 0; j < 2; ++j) + addr = utcb_new_slot(udesc[idx]); + for (int j = 0; j < 4; j++) { + utcb_delete_slot(udesc[idx], addr); + addr -= 0x100; + } + // Test 3 + for (int i = 0; i < 7; i++) { + utcb_delete_desc(udesc[idx]); + --idx; + } + for (int j = 0; j < 4; ++j) + addr = utcb_new_slot(udesc[idx]); + for (int j = 0; j < 2; j++) { + utcb_delete_slot(udesc[idx], addr); + addr -= 0x100; + } + for (int i = 0; i < 3; i++) + udesc[++idx] = utcb_new_desc(); + for (int i = 0; i < 7; i++) { + utcb_delete_desc(udesc[idx]); + --idx; + } +} From 8585482bd057cf7b02109c784e7108df44d8a913 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Thu, 5 Nov 2009 13:48:58 +0200 Subject: [PATCH 5/7] THREAD_RESUME is an alias to THREAD_RUN. --- include/l4/api/thread.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/l4/api/thread.h b/include/l4/api/thread.h index 1bc89a4..a8cabce 100644 --- a/include/l4/api/thread.h +++ b/include/l4/api/thread.h @@ -8,6 +8,7 @@ #define THREAD_DESTROY 0x30000000 #define THREAD_RECYCLE 0x40000000 #define THREAD_WAIT 0x50000000 +#define THREAD_RESUME THREAD_RUN #define THREAD_CREATE_MASK 0x0FF00000 #define TC_SHARE_CAPS 0x00100000 /* Share all thread capabilities */ From 352cb2daaa25f9ed4bdb4778d89a7af98fd91e38 Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Wed, 4 Nov 2009 20:48:59 +0200 Subject: [PATCH 6/7] The first step in creating a thread library. The difference between this thread library and the existing ones like pthreads is the necessity of informing the library about the address range of the stack and the l4 specific utcb. Utcb has not been supported yet. As for stack, there is also a drawback: library does not support mapping. In other words, the stack area in question has to be already mapped-in. Thus, for now we only support threads sharing their address spaces: TC_SHARE_SPACE. In this respect, it is very similar to pthreads. --- conts/libl4thread/SConscript | 10 +- conts/libl4thread/include/l4thread/thread.h | 12 +- conts/libl4thread/src/arch | 1 + conts/libl4thread/src/arch-arm/new_thread.S | 11 ++ conts/libl4thread/src/thread.c | 121 +++++++++++++++++++- conts/libl4thread/src/utcb_test.c | 55 --------- 6 files changed, 148 insertions(+), 62 deletions(-) create mode 120000 conts/libl4thread/src/arch create mode 100644 conts/libl4thread/src/arch-arm/new_thread.S delete mode 100644 conts/libl4thread/src/utcb_test.c diff --git a/conts/libl4thread/SConscript b/conts/libl4thread/SConscript index 876bf5c..abcda27 100644 --- a/conts/libl4thread/SConscript +++ b/conts/libl4thread/SConscript @@ -18,10 +18,14 @@ Import('env') LIBMEM_RELDIR = 'conts/libmem' LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR) -e = env.Clone() -e.Append(CPPPATH = ['include/l4thread', LIBMEM_DIR]) +LIBL4_RELDIR = 'conts/libl4' +LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR) +LIBL4_INCLUDE = join(LIBL4_DIR, 'include') -source = [Glob('*.[cS]') + Glob('src/*.[cS]')] +e = env.Clone() +e.Append(CPPPATH = ['include/l4thread', LIBMEM_DIR, LIBL4_INCLUDE]) + +source = [Glob('*.[cS]') + Glob('src/*.[cS]') + Glob('src/arch/*.[cS]')] objects = e.StaticObject(source) library = e.StaticLibrary('l4thread', objects) diff --git a/conts/libl4thread/include/l4thread/thread.h b/conts/libl4thread/include/l4thread/thread.h index 31ced16..658d17b 100644 --- a/conts/libl4thread/include/l4thread/thread.h +++ b/conts/libl4thread/include/l4thread/thread.h @@ -1,9 +1,19 @@ /* + * Thread creation userspace helpers * + * Copyright (C) 2009 B Labs Ltd. */ #ifndef __LIB_THREAD_H__ #define __LIB_THREAD_H__ -void l4thread_print(void); +#define STACK_TOP_ADDR(stack) ((unsigned long)(stack)) +#define STACK_BOTTOM_ADDR(stack) \ + ((unsigned long)((stack) + (sizeof(stack)))) + +int set_stack_params(unsigned long stack_top_addr, + unsigned long stack_bottom_addr, + unsigned long stack_size); +int thread_create(struct task_ids *ids, unsigned int flags, + int (*func)(void *), void *arg); #endif /* __LIB_THREAD_H__ */ diff --git a/conts/libl4thread/src/arch b/conts/libl4thread/src/arch new file mode 120000 index 0000000..3e9770f --- /dev/null +++ b/conts/libl4thread/src/arch @@ -0,0 +1 @@ +arch-arm/ \ No newline at end of file diff --git a/conts/libl4thread/src/arch-arm/new_thread.S b/conts/libl4thread/src/arch-arm/new_thread.S new file mode 100644 index 0000000..908569d --- /dev/null +++ b/conts/libl4thread/src/arch-arm/new_thread.S @@ -0,0 +1,11 @@ +#include + + +BEGIN_PROC(setup_new_thread) + ldr r0, [sp], #-4 @ Load first argument. + mov lr, pc @ Save return address + ldr pc, [sp], #-4 @ Load function pointer from stack +new_thread_exit: + b new_thread_exit @ We infinitely loop for now. +END_PROC(setup_new_thread) + diff --git a/conts/libl4thread/src/thread.c b/conts/libl4thread/src/thread.c index c362960..e11572c 100644 --- a/conts/libl4thread/src/thread.c +++ b/conts/libl4thread/src/thread.c @@ -1,11 +1,126 @@ /* + * Thread creation userspace helpers * + * Copyright (C) 2009 B Labs Ltd. */ #include +#include +#include +#include +#include -extern void utcb_test(unsigned long utcb_start, unsigned long utcb_end); +/* Symbolic constants and macros */ +#define STACK_PTR(addr) align((addr - 1), 8) +#define IS_STACK_SETUP() (lib_stack_size) -void l4thread_print(void) +/* Extern declarations */ +extern void setup_new_thread(void); + +/* Static variable definitions */ +static unsigned long lib_stack_top_addr; +static unsigned long lib_stack_bot_addr; +static unsigned long lib_stack_size; + +/* Function definitions */ +int set_stack_params(unsigned long stack_top_addr, + unsigned long stack_bottom_addr, + unsigned long stack_size) { - printf("Hello world from libl4thread!\n"); + if (IS_STACK_SETUP()) { + printf("libl4thread: You have already called: %s. Simply, " + "this will have no effect!\n", __FUNCTION__); + return -EPERM; + } + /* + * Stack grows downward so the top of the stack will have + * the lowest numbered address. + */ + if (stack_top_addr >= stack_bottom_addr) { + printf("libl4thread: Stack bottom address must be bigger " + "than stack top address!\n"); + return -EINVAL; + } + if (!stack_size) { + printf("libl4thread: Stack size cannot be zero!\n"); + return -EINVAL; + } + /* stack_size at least must be equal to the difference */ + if ((stack_bottom_addr - stack_top_addr) < stack_size) { + printf("libl4thread: the given range size is lesser than " + "the stack size!\n"); + return -EINVAL; + } + lib_stack_bot_addr = stack_bottom_addr; + lib_stack_top_addr = stack_top_addr; + lib_stack_size = stack_size; + + return 0; +} + +int thread_create(struct task_ids *ids, unsigned int flags, + int (*func)(void *), void *arg) +{ + struct exregs_data exregs; + int err; + + /* A few controls before granting access to thread creation */ + if (!IS_STACK_SETUP()) { + printf("libl4thread: Stack has not been set up. Before " + "calling thread_create, set_stack_params " + "has to be called!\n"); + return -EPERM; + } + + /* Is there enough stack space for the new thread? */ + if (lib_stack_top_addr >= lib_stack_bot_addr) { + printf("libl4thread: no stack space left!\n"); + return -ENOMEM; + } + + if (!(TC_SHARE_SPACE & flags)) { + printf("libl4thread: SAME address space is supported, which " + "means the only way to create a thread is with " + "TC_SHARE_SPACE flag. Other means of creating a " + "thread have not been supported yet!\n"); + return -EINVAL; + } + + /* Get parent's ids */ + l4_getid(ids); + + /* Create thread */ + if ((err = l4_thread_control(THREAD_CREATE | flags, ids)) < 0) { + printf("libl4thread: l4_thread_control(THREAD_CREATE) " + "failed with (%d)!\n", err); + return err; + } + + /* Setup new thread pc, sp, utcb */ + memset(&exregs, 0, sizeof(exregs)); + exregs_set_stack(&exregs, STACK_PTR(lib_stack_bot_addr)); + exregs_set_pc(&exregs, (unsigned long)setup_new_thread); + + if ((err = l4_exchange_registers(&exregs, ids->tid)) < 0) { + printf("libl4thread: l4_exchange_registers failed with " + "(%d)!\n", err); + return err; + } + + /* First word of new stack is arg */ + ((unsigned long *)STACK_PTR(lib_stack_bot_addr))[0] = + (unsigned long)arg; + /* Second word of new stack is function address */ + ((unsigned long *)STACK_PTR(lib_stack_bot_addr))[-1] = + (unsigned long)func; + /* Update the stack address */ + lib_stack_bot_addr -= lib_stack_size; + + /* Start the new thread */ + if ((err = l4_thread_control(THREAD_RUN, ids)) < 0) { + printf("libl4thread: l4_thread_control(THREAD_RUN) " + "failed with (%d)!\n", err); + return err; + } + + return 0; } diff --git a/conts/libl4thread/src/utcb_test.c b/conts/libl4thread/src/utcb_test.c deleted file mode 100644 index b05b7ca..0000000 --- a/conts/libl4thread/src/utcb_test.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This is for testing utcb port from POSIX - */ -#include -#include - -void utcb_test(unsigned long utcb_start, unsigned long utcb_end) -{ - struct utcb_desc *udesc[20]; - unsigned long addr; - int idx = -1; - - printf("%s\n", __FUNCTION__); - - utcb_pool_init(utcb_start, utcb_end); - - // Test-1 - for (int i = 0; i < 10; i++) - udesc[++idx] = utcb_new_desc(); - for (int j = 0; j < 20; ++j) - addr = utcb_new_slot(udesc[idx]); - - // Test 2 - for (int i = 0; i < 3; i++) - udesc[++idx] = utcb_new_desc(); - for (int j = 0; j < 10; ++j) - addr = utcb_new_slot(udesc[idx]); - for (int j = 0; j < 8; j++) { - utcb_delete_slot(udesc[idx], addr); - addr -= 0x100; - } - for (int j = 0; j < 2; ++j) - addr = utcb_new_slot(udesc[idx]); - for (int j = 0; j < 4; j++) { - utcb_delete_slot(udesc[idx], addr); - addr -= 0x100; - } - // Test 3 - for (int i = 0; i < 7; i++) { - utcb_delete_desc(udesc[idx]); - --idx; - } - for (int j = 0; j < 4; ++j) - addr = utcb_new_slot(udesc[idx]); - for (int j = 0; j < 2; j++) { - utcb_delete_slot(udesc[idx], addr); - addr -= 0x100; - } - for (int i = 0; i < 3; i++) - udesc[++idx] = utcb_new_desc(); - for (int i = 0; i < 7; i++) { - utcb_delete_desc(udesc[idx]); - --idx; - } -} From 55af5c83cb9b9c1e9c1cfbe13c111bcbf867fb5d Mon Sep 17 00:00:00 2001 From: Bora Sahin Date: Wed, 4 Nov 2009 16:16:19 +0200 Subject: [PATCH 7/7] The second step in creating a thread library. Utcb support has beed added. It has the same drawback as in the stack support: the area in questen has to be already mapped-in. There is some basic infrastructure for utcb to support mapping but it is far from being complete. MAPPING_ENABLE symbolic constant controls this behaviour. There are also some minor fixes for the stack support and the utcb common helper routines. --- conts/libl4thread/include/l4thread/addr.h | 5 +- conts/libl4thread/include/l4thread/thread.h | 2 + .../include/l4thread/utcb-common.h | 25 +++ conts/libl4thread/include/l4thread/utcb.h | 42 ++-- conts/libl4thread/src/addr.c | 6 +- conts/libl4thread/src/thread.c | 32 ++- conts/libl4thread/src/utcb-common.c | 89 ++++++++ conts/libl4thread/src/utcb.c | 196 ++++++++++++------ 8 files changed, 316 insertions(+), 81 deletions(-) create mode 100644 conts/libl4thread/include/l4thread/utcb-common.h create mode 100644 conts/libl4thread/src/utcb-common.c diff --git a/conts/libl4thread/include/l4thread/addr.h b/conts/libl4thread/include/l4thread/addr.h index 5bbc69d..e7b4519 100644 --- a/conts/libl4thread/include/l4thread/addr.h +++ b/conts/libl4thread/include/l4thread/addr.h @@ -18,8 +18,9 @@ struct address_pool { int address_pool_init_with_idpool(struct address_pool *pool, struct id_pool *idpool, unsigned long start, unsigned long end); -int address_pool_init(struct address_pool *pool, unsigned long start, - unsigned long end); +int address_pool_init(struct address_pool *pool, + unsigned long start, unsigned long end, + int size); void *address_new(struct address_pool *pool, int npages); int address_del(struct address_pool *, void *addr, int npages); diff --git a/conts/libl4thread/include/l4thread/thread.h b/conts/libl4thread/include/l4thread/thread.h index 658d17b..b84788d 100644 --- a/conts/libl4thread/include/l4thread/thread.h +++ b/conts/libl4thread/include/l4thread/thread.h @@ -6,6 +6,8 @@ #ifndef __LIB_THREAD_H__ #define __LIB_THREAD_H__ +#include "utcb.h" + #define STACK_TOP_ADDR(stack) ((unsigned long)(stack)) #define STACK_BOTTOM_ADDR(stack) \ ((unsigned long)((stack) + (sizeof(stack)))) diff --git a/conts/libl4thread/include/l4thread/utcb-common.h b/conts/libl4thread/include/l4thread/utcb-common.h new file mode 100644 index 0000000..e5f5fef --- /dev/null +++ b/conts/libl4thread/include/l4thread/utcb-common.h @@ -0,0 +1,25 @@ +/* + * UTCB handling common helper routines + * + * Copyright (C) 2009 B Labs Ltd. + */ +#ifndef __UTCB_COMMON_H__ +#define __UTCB_COMMON_H__ + +#include + +struct utcb_desc { + struct link list; + unsigned long utcb_base; + struct id_pool *slots; +}; + +int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end); + +unsigned long utcb_new_slot(struct utcb_desc *desc); +int utcb_delete_slot(struct utcb_desc *desc, unsigned long address); + +struct utcb_desc *utcb_new_desc(void); +int utcb_delete_desc(struct utcb_desc *desc); + +#endif /* __UTCB_COMMON_H__ */ diff --git a/conts/libl4thread/include/l4thread/utcb.h b/conts/libl4thread/include/l4thread/utcb.h index 464bd45..1876dea 100644 --- a/conts/libl4thread/include/l4thread/utcb.h +++ b/conts/libl4thread/include/l4thread/utcb.h @@ -3,23 +3,39 @@ * * Copyright (C) 2009 B Labs Ltd. */ -#ifndef __UTCB_H__ -#define __UTCB_H__ +#ifndef __LIB_UTCB_H__ +#define __LIB_UTCB_H__ -#include +#include "utcb-common.h" -struct utcb_desc { - struct link list; - unsigned long utcb_base; - struct id_pool *slots; +#define UTCB_START_ADDR(utcb) ((unsigned long)(utcb)) +#define UTCB_END_ADDR(utcb) \ + ((unsigned long)((utcb) + (sizeof(utcb)))) + +int set_utcb_params(unsigned long utcb_start_addr, + unsigned long utcb_end_addr); + +//#define MAPPING_ENABLE + +#if defined(MAPPING_ENABLE) + +#define IS_UTCB_SETUP() (utcb_table_ptr) + +struct utcb_entry *utcb_table_ptr; + +struct utcb_entry { + struct utcb_desc *udesc; + unsigned long utcb_phys_base; }; -int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end); +unsigned long get_utcb_addr(struct task_ids *parent_id, struct task_ids *child_id); +#else /* !MAPPING_ENABLE */ -unsigned long utcb_new_slot(struct utcb_desc *desc); -int utcb_delete_slot(struct utcb_desc *desc, unsigned long address); +#define IS_UTCB_SETUP() (udesc_ptr) -struct utcb_desc *utcb_new_desc(void); -int utcb_delete_desc(struct utcb_desc *desc); +struct utcb_desc *udesc_ptr; -#endif /* __UTCB_H__ */ +unsigned long get_utcb_addr(void); +#endif /* MAPPING_ENABLE */ + +#endif /* __LIB_UTCB_H__ */ diff --git a/conts/libl4thread/src/addr.c b/conts/libl4thread/src/addr.c index 10206bd..90c67dd 100644 --- a/conts/libl4thread/src/addr.c +++ b/conts/libl4thread/src/addr.c @@ -22,9 +22,11 @@ int address_pool_init_with_idpool(struct address_pool *pool, return 0; } -int address_pool_init(struct address_pool *pool, unsigned long start, unsigned long end) +int address_pool_init(struct address_pool *pool, + unsigned long start, unsigned long end, + int size) { - if ((pool->idpool = id_pool_new_init(__pfn(end - start))) < 0) + if ((pool->idpool = id_pool_new_init((end - start) / size)) < 0) return (int)pool->idpool; pool->start = start; pool->end = end; diff --git a/conts/libl4thread/src/thread.c b/conts/libl4thread/src/thread.c index e11572c..cfaaaca 100644 --- a/conts/libl4thread/src/thread.c +++ b/conts/libl4thread/src/thread.c @@ -8,6 +8,7 @@ #include #include #include +#include /* Symbolic constants and macros */ #define STACK_PTR(addr) align((addr - 1), 8) @@ -26,11 +27,18 @@ int set_stack_params(unsigned long stack_top_addr, unsigned long stack_bottom_addr, unsigned long stack_size) { + /* Ensure that arguments are valid. */ if (IS_STACK_SETUP()) { printf("libl4thread: You have already called: %s. Simply, " "this will have no effect!\n", __FUNCTION__); return -EPERM; } + if (!stack_top_addr || !stack_bottom_addr) { + printf("libl4thread: stack address range cannot contain " + "0x00000000 as a start and/or end address(es)!\n"); + return -EINVAL; + } + // FIXME: Aligning should be taken into account. /* * Stack grows downward so the top of the stack will have * the lowest numbered address. @@ -44,12 +52,15 @@ int set_stack_params(unsigned long stack_top_addr, printf("libl4thread: Stack size cannot be zero!\n"); return -EINVAL; } - /* stack_size at least must be equal to the difference */ + /* stack_size at least must be equal to the difference. */ if ((stack_bottom_addr - stack_top_addr) < stack_size) { printf("libl4thread: the given range size is lesser than " - "the stack size!\n"); + "the stack size(0x%x)!\n", stack_size); return -EINVAL; } + /* Arguments passed the validity tests. */ + + /* Initialize internal variables */ lib_stack_bot_addr = stack_bottom_addr; lib_stack_top_addr = stack_top_addr; lib_stack_size = stack_size; @@ -61,13 +72,15 @@ int thread_create(struct task_ids *ids, unsigned int flags, int (*func)(void *), void *arg) { struct exregs_data exregs; + unsigned long utcb_addr; int err; /* A few controls before granting access to thread creation */ - if (!IS_STACK_SETUP()) { - printf("libl4thread: Stack has not been set up. Before " - "calling thread_create, set_stack_params " - "has to be called!\n"); + if (!IS_STACK_SETUP() || !IS_UTCB_SETUP()) { + printf("libl4thread: Stack and/or utcb have not been set up. " + "Before calling thread_create, set_stack_params " + "and/or set_utcb_params have to be called with valid " + "arguments!\n"); return -EPERM; } @@ -85,6 +98,12 @@ int thread_create(struct task_ids *ids, unsigned int flags, return -EINVAL; } + /* Get a utcb addr for this thread */ + if (!(utcb_addr = get_utcb_addr())) { + printf("libl4thread: No utcb address left!\n"); + return -ENOMEM; + } + /* Get parent's ids */ l4_getid(ids); @@ -99,6 +118,7 @@ int thread_create(struct task_ids *ids, unsigned int flags, memset(&exregs, 0, sizeof(exregs)); exregs_set_stack(&exregs, STACK_PTR(lib_stack_bot_addr)); exregs_set_pc(&exregs, (unsigned long)setup_new_thread); + exregs_set_utcb(&exregs, (unsigned long)utcb_addr); if ((err = l4_exchange_registers(&exregs, ids->tid)) < 0) { printf("libl4thread: l4_exchange_registers failed with " diff --git a/conts/libl4thread/src/utcb-common.c b/conts/libl4thread/src/utcb-common.c new file mode 100644 index 0000000..38df843 --- /dev/null +++ b/conts/libl4thread/src/utcb-common.c @@ -0,0 +1,89 @@ +/* + * UTCB management in Codezero + * + * Copyright © 2009 B Labs Ltd + */ +#include +#include +#include +#include + +/* Globally disjoint utcb virtual region pool */ +static struct address_pool utcb_region_pool; + +int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end) +{ + int err; + + /* Initialise the global utcb virtual address pool */ + if ((err = address_pool_init(&utcb_region_pool, + utcb_start, utcb_end, + UTCB_SIZE) < 0)) { + printf("UTCB address pool initialisation failed.\n"); + return err; + } + + return 0; +} + +static inline void *utcb_new_address(int npages) +{ + return address_new(&utcb_region_pool, npages); +} + +static inline int utcb_delete_address(void *utcb_address, int npages) +{ + return address_del(&utcb_region_pool, utcb_address, npages); +} + +/* Return an empty utcb slot in this descriptor */ +unsigned long utcb_new_slot(struct utcb_desc *desc) +{ + int slot; + + if ((slot = id_new(desc->slots)) < 0) + return 0; + else + return desc->utcb_base + (unsigned long)slot * UTCB_SIZE; +} + +int utcb_delete_slot(struct utcb_desc *desc, unsigned long address) +{ + BUG_ON(id_del(desc->slots, (address - desc->utcb_base) + / UTCB_SIZE) < 0); + return 0; +} + +struct utcb_desc *utcb_new_desc(void) +{ + struct utcb_desc *d; + + /* Allocate a new descriptor */ + if (!(d = kzalloc(sizeof(*d)))) + return 0; + + link_init(&d->list); + + /* We currently assume UTCB is smaller than PAGE_SIZE */ + BUG_ON(UTCB_SIZE > PAGE_SIZE); + + /* Initialise utcb slots */ + d->slots = id_pool_new_init(PAGE_SIZE / UTCB_SIZE); + + /* Obtain a new and unique utcb base */ + /* FIXME: Use variable size than a page */ + d->utcb_base = (unsigned long)utcb_new_address(1); + + return d; +} + +int utcb_delete_desc(struct utcb_desc *desc) +{ + /* Return descriptor address */ + utcb_delete_address((void *)desc->utcb_base, 1); + + /* Free the descriptor */ + kfree(desc); + + return 0; +} diff --git a/conts/libl4thread/src/utcb.c b/conts/libl4thread/src/utcb.c index 9dcc187..b1666cc 100644 --- a/conts/libl4thread/src/utcb.c +++ b/conts/libl4thread/src/utcb.c @@ -1,88 +1,168 @@ -/* - * UTCB management in Codezero - * - * Copyright © 2009 B Labs Ltd - */ #include -#include -#include +#include +#include +#include #include +#include -/* Globally disjoint utcb virtual region pool */ -static struct address_pool utcb_region_pool; +static unsigned long utcb_end_max_addr; -int utcb_pool_init(unsigned long utcb_start, unsigned long utcb_end) +#if defined(MAPPING_ENABLE) +static int setup_utcb_table(unsigned long utcb_start_addr, + unsigned long utcb_end_addr) { + unsigned long utcb_range_size; + unsigned long utcb_table_size; + int total_entry; + + /* + * Establish the utcb_table. + * 1. Calculate the size of the table. + * 2. Calculate the number of entries. + * 3. Allocate it. + */ + utcb_range_size = utcb_end_addr - utcb_start_addr; + total_entry = utcb_range_size / UTCB_SIZE; + utcb_table_size = sizeof(struct utcb_entry) * total_entry; + if (!(utcb_table_ptr = kzalloc(utcb_table_size))) { + printf("libl4thread: There is not enough memory for the utcb " + "mapping table of size(%d)!\n", utcb_table_size); + return -ENOMEM; + } + return 0; +} +#endif + +static int set_utcb_addr(void) +{ + struct exregs_data exregs; + unsigned long utcb_addr; + struct task_ids ids; int err; - /* Initialise the global utcb virtual address pool */ - if ((err = address_pool_init(&utcb_region_pool, - utcb_start, utcb_end) < 0)) { - printf("UTCB address pool initialisation failed.\n"); + l4_getid(&ids); + // FIXME: its tid must be 0. +#if !defined(MAPPING_ENABLE) + udesc_ptr = utcb_new_desc(); + utcb_addr = get_utcb_addr(); +#else + { + struct utcb_desc *udesc; + udesc = utcb_new_desc(); + utcb_table_ptr[ids.tid].udesc = udesc; + utcb_addr = get_utcb_addr(&ids, &ids); + } +#endif + memset(&exregs, 0, sizeof(exregs)); + exregs_set_utcb(&exregs, (unsigned long)utcb_addr); + + if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0) { + printf("libl4thread: l4_exchange_registers failed with " + "(%d)!\n", err); return err; } return 0; } -static inline void *utcb_new_address(int npages) +int set_utcb_params(unsigned long utcb_start_addr, + unsigned long utcb_end_addr) { - return address_new(&utcb_region_pool, npages); -} + int err; -static inline int utcb_delete_address(void *utcb_address, int npages) -{ - return address_del(&utcb_region_pool, utcb_address, npages); -} + /* Ensure that arguments are valid. */ + if (IS_UTCB_SETUP()) { + printf("libl4thread: You have already called: %s. Simply, " + "this will have no effect!\n", __FUNCTION__); + return -EPERM; + } + if (!utcb_start_addr || !utcb_end_addr) { + printf("libl4thread: utcb address range cannot contain " + "0x00000000 as a start and/or end address(es)!\n"); + return -EINVAL; + } + /* Check if the start address is aligned on UTCB_SIZE. */ + if (utcb_start_addr & !UTCB_SIZE) { + printf("libl4thread: utcb start address must be aligned " + "on UTCB_SIZE(0x%x)\n", UTCB_SIZE); + return -EINVAL; + } + /* The range must be a valid one. */ + if (utcb_start_addr >= utcb_end_addr) { + printf("libl4thread: utcb end address must be bigger " + "than utcb start address!\n"); + return -EINVAL; + } + /* + * This check guarantees two things: + * 1. The range must be multiple of UTCB_SIZE, at least one item. + * 2. utcb_end_addr is aligned on UTCB_SIZE + */ + if ((utcb_end_addr - utcb_start_addr) % UTCB_SIZE) { + printf("libl4thread: the given range size must be multiple " + "of the utcb size(%d)!\n", UTCB_SIZE); + return -EINVAL; + } + /* Arguments passed the validity tests. */ -/* Return an empty utcb slot in this descriptor */ -unsigned long utcb_new_slot(struct utcb_desc *desc) -{ - int slot; + /* Init utcb virtual address pool */ + utcb_pool_init(utcb_start_addr, utcb_end_addr); - if ((slot = id_new(desc->slots)) < 0) - return 0; - else - return desc->utcb_base + (unsigned long)slot * UTCB_SIZE; -} +#if defined(MAPPING_ENABLE) + setup_utcb_table(utcb_start_addr, utcb_end_addr); +#endif + utcb_end_max_addr = utcb_end_addr; + + /* The very first thread's utcb address is assigned. */ + if ((err = set_utcb_addr()) < 0) + return err; -int utcb_delete_slot(struct utcb_desc *desc, unsigned long address) -{ - BUG_ON(id_del(desc->slots, (address - desc->utcb_base) - / UTCB_SIZE) < 0); return 0; } -struct utcb_desc *utcb_new_desc(void) +#if !defined(MAPPING_ENABLE) +unsigned long get_utcb_addr(void) { - struct utcb_desc *d; + unsigned long utcb_addr; - /* Allocate a new descriptor */ - if (!(d = kzalloc(sizeof(*d)))) + if (!(utcb_addr = utcb_new_slot(udesc_ptr))) { + udesc_ptr = utcb_new_desc(); + utcb_addr = utcb_new_slot(udesc_ptr); + } + + if (utcb_addr >= utcb_end_max_addr) return 0; - link_init(&d->list); - - /* We currently assume UTCB is smaller than PAGE_SIZE */ - BUG_ON(UTCB_SIZE > PAGE_SIZE); - - /* Initialise utcb slots */ - d->slots = id_pool_new_init(PAGE_SIZE / UTCB_SIZE); - - /* Obtain a new and unique utcb base */ - /* FIXME: Use variable size than a page */ - d->utcb_base = (unsigned long)utcb_new_address(1); - - return d; + return utcb_addr; } - -int utcb_delete_desc(struct utcb_desc *desc) +#else +unsigned long get_utcb_addr(struct task_ids *parent_id, + struct task_ids *child_id) { - /* Return descriptor address */ - utcb_delete_address((void *)desc->utcb_base, 1); + struct utcb_entry uentry; + unsigned long utcb_addr; - /* Free the descriptor */ - kfree(desc); + /* Get the entry for this thread. */ + uentry = utcb_table_ptr[parent_id->tid]; - return 0; + /* Get a new utcb virtual address. */ + if (!(utcb_addr = utcb_new_slot(uentry.udesc))) { + /* No slot for this desc, get a new desc. */ + struct utcb_desc *udesc; + udesc = utcb_new_desc(); + utcb_addr = utcb_new_slot(udesc); + uentry.udesc = udesc; + } + /* Place the entry into the utcb_table. */ + utcb_table_ptr[child_id->tid].udesc = uentry.udesc; + utcb_table_ptr[parent_id->tid].udesc = uentry.udesc; + + if (utcb_addr >= utcb_end_max_addr) + return 0; + + return utcb_addr; } +#endif + +/*void destroy_utcb(void) {}*/ +