From ebc73f66df79dc7142964ccc0eea5c606808ea47 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 20 Feb 2013 13:17:39 +0100 Subject: [PATCH] Remove base-mb platform This base platform is no longer maintained. For supporting the Microblaze CPU in the future, we might consider integrating support for this architecture into base-hw. Currently though, there does not seem to be any demand for it. --- README | 18 +- base-mb/README | 11 - base-mb/doc/getting_started.txt | 249 ------ base-mb/doc/microblaze.txt | 124 --- base-mb/etc/specs.conf | 1 - base-mb/etc/tools.conf | 14 - base-mb/include/base/ipc_msgbuf.h | 62 -- base-mb/include/base/ipc_pager.h | 207 ----- base-mb/include/base/native_types.h | 70 -- base-mb/include/cpu/atomic.h | 71 -- base-mb/include/cpu/config.h | 116 --- base-mb/include/cpu/cpu_state.h | 36 - base-mb/include/cpu/string.h | 54 -- base-mb/include/kernel/config.h | 79 -- base-mb/include/kernel/syscalls.h | 568 -------------- base-mb/include/kernel/types.h | 329 -------- base-mb/include/xilinx/xps_intc.h | 226 ------ base-mb/include/xilinx/xps_timer.h | 399 ---------- base-mb/include/xilinx/xps_uartl.h | 111 --- base-mb/lib/mk/cxx.mk | 87 --- base-mb/lib/mk/ipc.mk | 7 - base-mb/lib/mk/kernel.inc | 41 - base-mb/lib/mk/kernel_core.mk | 13 - base-mb/lib/mk/kernel_test.inc | 7 - base-mb/lib/mk/lock.mk | 6 - base-mb/lib/mk/pager.mk | 4 - ...logix_s3adsp1800_mmu__atomic_operations.mk | 6 - ...talogix_s3adsp1800_mmu__kernel_support.inc | 29 - base-mb/lib/mk/printf_microblaze.mk | 5 - base-mb/lib/mk/startup.mk | 13 - base-mb/lib/mk/test_env.mk | 6 - base-mb/lib/mk/thread.mk | 8 - base-mb/lib/mk/thread_context.mk | 5 - base-mb/mk/spec-mb_ml507.mk | 7 - base-mb/mk/spec-mb_s3a_starter_kit.mk | 7 - base-mb/platform/mb_s3a_starter_kit/Makefile | 22 - .../platform/mb_s3a_starter_kit/system.bit | Bin 341653 -> 0 bytes base-mb/platform/mk/microblaze.mk | 19 - base-mb/platform/mk/ml507.mk | 19 - base-mb/platform/mk/s3a_starter_kit.mk | 22 - base-mb/platform/mk/xilinx.mk | 24 - base-mb/run/env | 211 ----- base-mb/run/hello.run | 15 - base-mb/run/nested_init.run | 34 - .../src/base/console/microblaze_console.cc | 64 -- base-mb/src/base/cxx/atexit.cc | 19 - base-mb/src/base/ipc/ipc.cc | 201 ----- base-mb/src/base/ipc/pager.cc | 74 -- base-mb/src/base/lock/lock_helper.h | 57 -- base-mb/src/base/pager/pager.cc | 122 --- base-mb/src/base/thread/thread.cc | 215 ------ base-mb/src/base/thread/thread_bootstrap.cc | 22 - base-mb/src/base/thread/thread_context.cc | 57 -- base-mb/src/base/thread/thread_start.cc | 75 -- base-mb/src/core/context_area.cc | 148 ---- base-mb/src/core/core_rm_session.cc | 37 - base-mb/src/core/cpu_session_support.cc | 27 - base-mb/src/core/include/core_rm_session.h | 53 -- base-mb/src/core/include/cpu/prints.h | 67 -- .../src/core/include/irq_session_component.h | 73 -- base-mb/src/core/include/kernel/print.h | 98 --- base-mb/src/core/include/map_local.h | 49 -- base-mb/src/core/include/platform.h | 118 --- base-mb/src/core/include/platform_pd.h | 267 ------- base-mb/src/core/include/platform_thread.h | 166 ---- base-mb/src/core/include/util.h | 55 -- base-mb/src/core/include/util/array.h | 21 - base-mb/src/core/include/util/debug.h | 62 -- base-mb/src/core/include/util/id_allocator.h | 122 --- base-mb/src/core/include/util/math.h | 40 - base-mb/src/core/include/util/queue.h | 145 ---- base-mb/src/core/include/xilinx/microblaze.h | 403 ---------- base-mb/src/core/io_mem_session_support.cc | 28 - base-mb/src/core/irq_session_component.cc | 68 -- base-mb/src/core/platform.cc | 312 -------- base-mb/src/core/platform_thread.cc | 191 ----- base-mb/src/core/ram_session_support.cc | 45 -- base-mb/src/core/rm_session_support.cc | 38 - base-mb/src/core/target.inc | 54 -- base-mb/src/core/target.mk | 10 - base-mb/src/core/thread_roottask.cc | 111 --- base-mb/src/kernel/generic/blocking.cc | 268 ------- .../src/kernel/generic/include/exception.h | 82 -- .../src/kernel/generic/include/interrupt.h | 50 -- base-mb/src/kernel/generic/include/thread.h | 360 --------- base-mb/src/kernel/generic/kernel.cc | 189 ----- base-mb/src/kernel/generic/scheduler.cc | 130 ---- base-mb/src/kernel/generic/syscall_events.cc | 187 ----- base-mb/src/kernel/generic/thread.cc | 117 --- base-mb/src/kernel/include/generic/blocking.h | 417 ---------- base-mb/src/kernel/include/generic/event.h | 103 --- base-mb/src/kernel/include/generic/ipc.h | 323 -------- .../kernel/include/generic/irq_controller.h | 153 ---- base-mb/src/kernel/include/generic/printf.h | 21 - .../src/kernel/include/generic/scheduler.h | 372 --------- .../kernel/include/generic/syscall_events.h | 190 ----- base-mb/src/kernel/include/generic/timer.h | 197 ----- base-mb/src/kernel/include/generic/tlb.h | 152 ---- base-mb/src/kernel/include/generic/verbose.h | 107 --- .../platform/platform.h | 729 ------------------ .../petalogix_s3adsp1800_mmu/atomic.s | 93 --- .../platforms/petalogix_s3adsp1800_mmu/crt0.s | 47 -- .../petalogix_s3adsp1800_mmu/crt0_kernel.s | 94 --- .../petalogix_s3adsp1800_mmu/kernel_entry.s | 260 ------- .../petalogix_s3adsp1800_mmu/platform.cc | 205 ----- .../petalogix_s3adsp1800_mmu/userland_entry.s | 280 ------- base-mb/src/platform/_main_helper.h | 54 -- base-mb/src/platform/genode.ld | 115 --- base-mb/src/test/hello/main.cc | 23 - base-mb/src/test/hello/target.mk | 3 - base/include/base/thread.h | 3 - base/mk/global.mk | 4 +- doc/challenges.txt | 9 - tool/builddir/etc/build.conf.mb_ml507 | 2 - .../etc/build.conf.mb_s3a_starter_kit | 2 - tool/create_builddir | 7 - 116 files changed, 9 insertions(+), 12415 deletions(-) delete mode 100644 base-mb/README delete mode 100644 base-mb/doc/getting_started.txt delete mode 100644 base-mb/doc/microblaze.txt delete mode 100755 base-mb/etc/specs.conf delete mode 100755 base-mb/etc/tools.conf delete mode 100755 base-mb/include/base/ipc_msgbuf.h delete mode 100755 base-mb/include/base/ipc_pager.h delete mode 100755 base-mb/include/base/native_types.h delete mode 100755 base-mb/include/cpu/atomic.h delete mode 100755 base-mb/include/cpu/config.h delete mode 100644 base-mb/include/cpu/cpu_state.h delete mode 100644 base-mb/include/cpu/string.h delete mode 100755 base-mb/include/kernel/config.h delete mode 100755 base-mb/include/kernel/syscalls.h delete mode 100755 base-mb/include/kernel/types.h delete mode 100644 base-mb/include/xilinx/xps_intc.h delete mode 100644 base-mb/include/xilinx/xps_timer.h delete mode 100644 base-mb/include/xilinx/xps_uartl.h delete mode 100755 base-mb/lib/mk/cxx.mk delete mode 100755 base-mb/lib/mk/ipc.mk delete mode 100755 base-mb/lib/mk/kernel.inc delete mode 100755 base-mb/lib/mk/kernel_core.mk delete mode 100755 base-mb/lib/mk/kernel_test.inc delete mode 100755 base-mb/lib/mk/lock.mk delete mode 100755 base-mb/lib/mk/pager.mk delete mode 100644 base-mb/lib/mk/petalogix_s3adsp1800_mmu__atomic_operations.mk delete mode 100755 base-mb/lib/mk/petalogix_s3adsp1800_mmu__kernel_support.inc delete mode 100755 base-mb/lib/mk/printf_microblaze.mk delete mode 100755 base-mb/lib/mk/startup.mk delete mode 100755 base-mb/lib/mk/test_env.mk delete mode 100644 base-mb/lib/mk/thread.mk delete mode 100755 base-mb/lib/mk/thread_context.mk delete mode 100644 base-mb/mk/spec-mb_ml507.mk delete mode 100644 base-mb/mk/spec-mb_s3a_starter_kit.mk delete mode 100644 base-mb/platform/mb_s3a_starter_kit/Makefile delete mode 100644 base-mb/platform/mb_s3a_starter_kit/system.bit delete mode 100644 base-mb/platform/mk/microblaze.mk delete mode 100644 base-mb/platform/mk/ml507.mk delete mode 100644 base-mb/platform/mk/s3a_starter_kit.mk delete mode 100644 base-mb/platform/mk/xilinx.mk delete mode 100755 base-mb/run/env delete mode 100755 base-mb/run/hello.run delete mode 100755 base-mb/run/nested_init.run delete mode 100755 base-mb/src/base/console/microblaze_console.cc delete mode 100755 base-mb/src/base/cxx/atexit.cc delete mode 100755 base-mb/src/base/ipc/ipc.cc delete mode 100755 base-mb/src/base/ipc/pager.cc delete mode 100755 base-mb/src/base/lock/lock_helper.h delete mode 100644 base-mb/src/base/pager/pager.cc delete mode 100644 base-mb/src/base/thread/thread.cc delete mode 100755 base-mb/src/base/thread/thread_bootstrap.cc delete mode 100755 base-mb/src/base/thread/thread_context.cc delete mode 100644 base-mb/src/base/thread/thread_start.cc delete mode 100644 base-mb/src/core/context_area.cc delete mode 100644 base-mb/src/core/core_rm_session.cc delete mode 100644 base-mb/src/core/cpu_session_support.cc delete mode 100644 base-mb/src/core/include/core_rm_session.h delete mode 100644 base-mb/src/core/include/cpu/prints.h delete mode 100644 base-mb/src/core/include/irq_session_component.h delete mode 100644 base-mb/src/core/include/kernel/print.h delete mode 100755 base-mb/src/core/include/map_local.h delete mode 100755 base-mb/src/core/include/platform.h delete mode 100755 base-mb/src/core/include/platform_pd.h delete mode 100755 base-mb/src/core/include/platform_thread.h delete mode 100755 base-mb/src/core/include/util.h delete mode 100644 base-mb/src/core/include/util/array.h delete mode 100644 base-mb/src/core/include/util/debug.h delete mode 100644 base-mb/src/core/include/util/id_allocator.h delete mode 100644 base-mb/src/core/include/util/math.h delete mode 100644 base-mb/src/core/include/util/queue.h delete mode 100644 base-mb/src/core/include/xilinx/microblaze.h delete mode 100755 base-mb/src/core/io_mem_session_support.cc delete mode 100644 base-mb/src/core/irq_session_component.cc delete mode 100644 base-mb/src/core/platform.cc delete mode 100755 base-mb/src/core/platform_thread.cc delete mode 100755 base-mb/src/core/ram_session_support.cc delete mode 100755 base-mb/src/core/rm_session_support.cc delete mode 100755 base-mb/src/core/target.inc delete mode 100755 base-mb/src/core/target.mk delete mode 100755 base-mb/src/core/thread_roottask.cc delete mode 100755 base-mb/src/kernel/generic/blocking.cc delete mode 100755 base-mb/src/kernel/generic/include/exception.h delete mode 100755 base-mb/src/kernel/generic/include/interrupt.h delete mode 100755 base-mb/src/kernel/generic/include/thread.h delete mode 100755 base-mb/src/kernel/generic/kernel.cc delete mode 100755 base-mb/src/kernel/generic/scheduler.cc delete mode 100755 base-mb/src/kernel/generic/syscall_events.cc delete mode 100755 base-mb/src/kernel/generic/thread.cc delete mode 100755 base-mb/src/kernel/include/generic/blocking.h delete mode 100755 base-mb/src/kernel/include/generic/event.h delete mode 100755 base-mb/src/kernel/include/generic/ipc.h delete mode 100755 base-mb/src/kernel/include/generic/irq_controller.h delete mode 100755 base-mb/src/kernel/include/generic/printf.h delete mode 100755 base-mb/src/kernel/include/generic/scheduler.h delete mode 100755 base-mb/src/kernel/include/generic/syscall_events.h delete mode 100755 base-mb/src/kernel/include/generic/timer.h delete mode 100755 base-mb/src/kernel/include/generic/tlb.h delete mode 100755 base-mb/src/kernel/include/generic/verbose.h delete mode 100755 base-mb/src/kernel/include/petalogix_s3adsp1800_mmu/platform/platform.h delete mode 100755 base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/atomic.s delete mode 100755 base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/crt0.s delete mode 100755 base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/crt0_kernel.s delete mode 100755 base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/kernel_entry.s delete mode 100644 base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/platform.cc delete mode 100755 base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/userland_entry.s delete mode 100644 base-mb/src/platform/_main_helper.h delete mode 100755 base-mb/src/platform/genode.ld delete mode 100644 base-mb/src/test/hello/main.cc delete mode 100644 base-mb/src/test/hello/target.mk delete mode 100644 tool/builddir/etc/build.conf.mb_ml507 delete mode 100644 tool/builddir/etc/build.conf.mb_s3a_starter_kit diff --git a/README b/README index e67211649..affb273fc 100644 --- a/README +++ b/README @@ -14,13 +14,13 @@ the project's official website: The current implementation can be compiled for 8 different kernels: Linux, L4ka::Pistachio, L4/Fiasco, OKL4, NOVA, Fiasco.OC, Codezero, and a custom -kernel for the MicroBlaze architecture. Whereas the Linux version serves us as -development vehicle and enables us to rapidly develop the generic parts of the -system, the actual target platforms of the framework are microkernels. There -is no "perfect" microkernel - and neither should there be one. If a microkernel -pretended to be fit for all use cases, it wouldn't be "micro". Hence, all -microkernels differ in terms of their respective features, complexity, and -supported hardware architectures. +kernel for running Genode directly on ARM-based hardware. Whereas the Linux +version serves us as development vehicle and enables us to rapidly develop the +generic parts of the system, the actual target platforms of the framework are +microkernels. There is no "perfect" microkernel - and neither should there be +one. If a microkernel pretended to be fit for all use cases, it wouldn't be +"micro". Hence, all microkernels differ in terms of their respective features, +complexity, and supported hardware architectures. Genode allows the use of each of the kernels listed above with a rich set of device drivers, protocol stacks, libraries, and applications in a uniform way. @@ -106,10 +106,6 @@ The Genode source tree is composed of the following subdirectories: Codezero microkernel developed by B-Labs See [http://genode.org/documentation/platforms/codezero] - :'mb': - Support for running Genode natively on the MicroBlaze softcore CPU. - See [http://genode.org/documentation/platforms/microblaze] - :'host': Pseudo platform documenting the interface between the generic and platform-specific parts of the base framework. This is not a functional diff --git a/base-mb/README b/base-mb/README deleted file mode 100644 index 730ff1f63..000000000 --- a/base-mb/README +++ /dev/null @@ -1,11 +0,0 @@ -This repository contains the port of Genode for Xilinx MicroBlaze-based -platforms. It is based on an custom microkernel implementation, which is also -part of this repository. To get an overview on the this platform and the -underlying microkernel please refer to the introduction located at: - -! /base-mb/doc/microblaze.txt - -To get a quick overview about how to work with this platform, you may read the -getting-started guide located at: - -! /base-mb/doc/getting_started.txt diff --git a/base-mb/doc/getting_started.txt b/base-mb/doc/getting_started.txt deleted file mode 100644 index efdac7643..000000000 --- a/base-mb/doc/getting_started.txt +++ /dev/null @@ -1,249 +0,0 @@ - - ========================================================= - Getting started with Genode on MicroBlaze based platforms - ========================================================= - - - Martin Stein - - -This file describes in a practical manner how to work with Genode on platforms -which are based on the Xilinx MicroBlaze. It approaches the following aspects: - -* Build Genode with an existing static scenario of programs which are interacting - on with each other and printing information about it to the serial port. -* Run this Genode scenario on Qemu and on the Xilinx Spartan 3A Starter Kit -* Implement basic support aspects for new MicroBlaze-based platforms - -If you're not familar with the Genode OS framework, you can read the online -documentation: - - [http://genode.org/documentation/] - -If you need further information about the Xilinx MicroBlaze, you can read an -introduction written by the Genode developers inside your Genode directory: - - 'base-mb/doc/microblaze.txt' - -It also covers general issues and limitations respecting the status quo of the -Genode porting for MicroBlaze-based platforms. To go in detail about the Xilinx -MicroBlaze, you may refer to the Xilinx documentation: - - [http://www.xilinx.com/tools/microblaze.htm] - -Prerequisites -============= - -The MicroBlaze tool chain -~~~~~~~~~~~~~~~~~~~~~~~~~ - -To build Genode for MicroBlaze, it is recommended to use the following -GCC/binutils-compliant tools: - -* mb-g++ (GCC) 4.1.1 20060524 (Xilinx 11.2 Build EDK_LS2.2 20 Apr 2009 Xilinx - 11.2 Build EDK_LS2.2 23 Apr 2009) -* GNU ld version 2.16 Xilinx 11.2 Build EDK_LS2.2 23 Apr 2009 -* GNU assembler 2.16 Xilinx 11.2 Build EDK_LS2.2 23 Apr 2009 - -These tools come with the Xilinx Embedded Development Kit (EDK). - -Expect -~~~~~~ - -To run the given test scenarios on Genode, you have to install the Tcl-based -testing-tool Expect, for example using 'apt-get' on Debian-based Linux -distributions: - -! sudo apt-get install expect - -Qemu -~~~~ - -To run Genode's MicroBlaze port on Qemu, the following Qemu-version is recommended: - - QEMU emulator version 0.14.50, Copyright (c) 2003-2008 Fabrice Bellard - -You can get the source code of the latest version via GIT as follows: - -! git clone git://git.qemu.org/qemu.git - -For the scenarios described in here, you have to compile qemu via: - -! configure --target-list=microblaze-softmmu -! make - -Hardware -~~~~~~~~ - -The tutorial that runs Genode on hardware uses the Xilinx Spartan 3A Starter Kit -Revision D board with the FPGA 'xc3s700a', package 'fg484' on speed grade '-4'. -It has to be connected to your machine via USB and a serial port RS-232. - -Tutorial: Build and run Genode's MicroBlaze port -================================================ - -Initially go to your Genode directory and ensure that the value of the 'QEMU' variable -within 'tool/builddir/etc/build.conf.mb-s3a_starter_kit' conforms to the path -of your 'qemu-system-microblaze' command. Now build a build directory with the -following shell commands: - -! ./tool/create_builddir mb-s3a_starter_kit \ -! BUILD_DIR=build.mb-s3a_starter_kit \ - -On Qemu -~~~~~~~ - -Change to '/build.mb-s3a_starter_kit'. In this directory, -build and run the Genode scenario 'nested_init' for Qemu as follows: - -! make run/nested_init - -This instructs the Genode build system to act according to the run-script -'/base-mb/run/nested_init.run'. This script initiates the build of -the Genode's core, the program 'init', and a configuration that describes the -scenario init start. Then it constructs a bootable image of these 3 files and -finally starts Qemu to boot the image virtually. Genode then starts 2 nested -'init' programs, each 'init' instance prints some information about its -capabilities. - - -On Hardware -~~~~~~~~~~~ - -Ensure that the Xilinx Spartan 3A Starter Kit jumpers are set as described for -the board-intern demo. Connect the board via USB to your machine and turn it -on. Wait till the LED next to the USB connector on board lights up, then list -all connected USB devices: - -! lsusb - -This should print, among others, one line like this 'Bus XXX Device XXX: ID XXXX:0008 -Xilinx, Inc.' (any X is a wildcard for a number 0-9). Now connect the Serial port that -is labeled on board with 'J27' with your computer, this allows us to track debugging -output from Genode later. Go to '/build.mb-s3a_starter_kit'. -First we have to configure the Spartan 3A with an appropriate MicroBlaze SoC as follows: - -! make -C ../base-mb/platform/mb-s3a_starter_kit - -If it has finished successfully, we can build and run the 'nested_init' scenario by -typing the following command from within the build directory: - -! RUN_OPT="--target jtag" make run/nested_init - -After this, the build chain leaves an XMD command prompt to you, which is connected -to the SoC on the FPGA via JTAG, so you can steer it as you wish. Genode isn't started -already, you can now run a program like 'gtkterm' which intercepts the serial port that -Genode will print to. The parameters of the serial port according to 'gtkterm' are: - -* Speed = 9600 -* Parity = none -* Bits = 8 -* Stopbits = 1 -* Flowcontrol = none - -To start the execution of the 'nested_init' scenario type - -! run - -to the open XMD prompt. The serial port interception should show output similar -to that of the Qemu-run. You should avoid uploading multiple times to a once -configured platform, it can lead to memory inconsistency. In contrast when -configuring the FPGA in between the RAM gets reset. - -Other scenarios -~~~~~~~~~~~~~~~ - -You can also find a simple hello-world program at 'base-mb/src/test/hello'. -An appropriate 'run' script also exists and can be build from within a build -directory via: - -! RUN_OPT="--target " make run/hello - -Hints: How to add support for other MicroBlaze-based platforms -============================================================== - -The steps described in here don't claim to be complete. They solely should -cover the basic of aspects to be considered when implementing support for new -platforms and reflect main conventions Genode's MicroBlaze port relies to. - -New MicroBlaze-based platforms have to fulfill several considerations for now -to be compliant to the Genode port. The core expects: - -* A MicroBlaze SoC with software-loaded MMU that has 64 entries, - RAM accessibility and no instruction- and data- caches -* The RAM address space to be mapped to 0x90000000 -* The CPUs IRQ controller to be an XPS interrupt controller, - mapped to 0x81800000 -* An XPS Timer mapped to 0x83c00000 with IRQ 0 -* An XPS UART Lite mapped to 0x84000000 - -Basics -~~~~~~ - -Add a file 'base-mb/mk/spec-.mk' with the content - -! SPECS += -! STARTUP_LIB ?= startup -! PRG_LIBS += $(STARTUP_LIB) - -This file contains aspects to be integrated if 'PLATFORM' occurs in the -make-variable 'SPECS' during the build process. It also can add 'SPECS' by -itself to provide further details to the build system. For example, -the word-width of the CPU like '32bit'. Any other program or library -can depend on 'PLATFORM' later by adding it to its 'SPECS'. The second and third -lines specify a library that all userland-programs on Genode use to start on -'PLATFORM'. The denoted one is the default '/base-mb/lib/mk/startup.mk' -used by the currently supported platforms. - -You can influence the build-process for 'PLATFORM' furthermore by adding additional -lines to this file, for according documentation please refer to: - - [http://genode.org/documentation/] - -FPGA Configuration and support by the tool 'run' -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To automate testing via the 'run' tool, you have to create a Makefile -'/base-mb/platform//Makefile' that provides a target -'upload'. This target should upload an ELF-image, whose absolute path is -given by the make argument 'IMAGE', to the according hardware. -The above mentioned Makefile should also provide by convention a target -'configure' which prepares the according hardware for the upload of -boot images. Typically it configures the FPGA with an appropriate -SoC. Therefore, whose source should also be located within -'/base-mb/platform//'. - -Finally you have to edit '/base-mb/run/env' to hint 'run' to -your platform. Add inside the function definition 'proc hardware { } {' -an additional: - -! if { [have_spec {}] } { -! set _hardware -! return $_hardware -! } - -'run' then calls 'upload' on '/base-mb/platform//Makefile' -and gives the boot image when 'run_genode_until' is called by the according -'run'-script. But first you should create an according build directory as described -next. - -Support for the tool 'create_builddir' -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Add a file 'tool/builddir/etc/build.conf.' with at least the content - -! REPOSITORIES = base-mb -! QEMU = - -Where 'QEMU' denotes your Qemu command to emulate 'PLATFORM' for Genode -Now add a make-target '::' to 'tool/create_builddir' that should -describe additional things to do for your build directory. A good point to -start is to overwrite the default specifications the build process should take -into account when selecting and build targets and libraries. - -! @echo "SPECS = genode " > $(BUILD_DIR)/etc/specs.conf - -This adds the specifics for basic Genode settings, libraries and programs as -well as to the contents of your previously created -'base-mb/mk/spec-.mk'. - diff --git a/base-mb/doc/microblaze.txt b/base-mb/doc/microblaze.txt deleted file mode 100644 index 1d5831fb2..000000000 --- a/base-mb/doc/microblaze.txt +++ /dev/null @@ -1,124 +0,0 @@ - - ========================================================== - Introduction into the Genode porting for Xilinx MicroBlaze - ========================================================== - - - Norman Feske - Martin Stein - -This file gives an overview to the Genode porting for MicroBlaze-based -platforms. To get a quick introduction in how to build and run Genode on -such platforms, please refer to: - -! - -Xilinx MicroBlaze is a so-called softcore CPU, which is commonly used as part -of FPGA-based System-on-Chip designs. At Genode Labs, we are regularly using -this IP core, in particular for our Genode FPGA Graphics Project, which is a -GUI software stack and a set of IP cores for implementing fully-fledged -windowed GUIs on FPGAs: - -:Website of the Genode FPGA Graphics Project: - - [http://genode-labs.com/products/fpga-graphics] - -Ever since we first released the Genode FPGA project, we envisioned to combine -it with the Genode OS Framework. In Spring 2010, Martin Stein joined our team -at Genode Labs and accepted the challenge to bring the Genode OS Framework to -the realms of FPGA-based SoCs. Technically, this implies porting the framework -to the MicroBlaze CPU architecture. In contrast to most softcore CPUs such as -the popular Lattice Mico32, the MicroBlaze features a MMU, which is a fundamental -requirement for implementing a microkernel-based system. Architecturally-wise -MicroBlaze is a RISC CPU similar to MIPS. Many system parameters of the CPU -(caches, certain arithmetic and shift instructions) can be parametrized at -synthesizing time of the SoC. We found that the relatively simple architecture -of this CPU provides a perfect playground for pursuing some of our ideas about -kernel design that go beyond the scope of current microkernels. So instead of -adding MicroBlaze support into one of the existing microkernels already -supported by Genode, we went for a new kernel design. Deviating from the typical -microkernel, which is a self-sufficient program running in kernel mode that -executes user-level processes on top, our design regards the kernel as a part of -Genode's core. It is not a separate program but a library that implements the -glue between user-level core and the raw CPU. Specifically, it provides the -entrypoint for hardware exceptions, a thread scheduler, an IPC mechanism, and -functions to manipulate virtual address spaces (loading and flushing entries -from the CPU's software-loaded TLB). It does not manage any physical memory -resources or the relationship between processes. This is the job of core. -From the kernel-developer's point of view, the kernel part can be summarized as -follows: - -* The kernel provides user-level threads that are scheduled in a round-robin - fashion. -* Threads can communicate via synchronous IPC. -* There is a mechanism for blocking and waking up threads. This mechanism - can be used by Genode to implement locking as well as asynchronous - inter-process communication. -* There is a single kernel thread, which never blocks in the kernel code paths. - So the kernel acts as a state machine. Naturally, there is no concurrency in the - execution paths traversed in kernel mode, vastly simplifying these code parts. - However, all code paths are extremely short and bounded with regard to - execution time. Hence, we expect the interference with interrupt latencies - to be low. -* The IPC operation transfers payload between UTCBs only. Each thread has a - so-called user-level thread control block which is mapped transparently by - the kernel. Because of this mapping, user-level page faults cannot occur - during IPC transfers. -* There is no mapping database. Virtual address spaces are manipulated by - loading and flushing physical TLB entries. There is no caching of mappings - done in the kernel. All higher-level information about the interrelationship - of memory and processes is managed by the user-level core. -* Core runs in user mode, mapped 1-to-1 from the physical address space - except for its virtual thread-context area. -* The kernel paths are executed in physical address space (MicroBlaze). - Because both kernel code and user-level core code are observing the same - address-space layout, both worlds appear to run within a single address - space. -* User processes can use the entire virtual address space (4G) except for a - helper page for invoking syscalls and a page containing atomic operations. - There is no reservation used for the kernel. -* The MicroBlaze architecture lacks an atomic compare-and-swap instruction. On - user-level, this functionality is emulated via delayed preemption. A kernel- - provided page holds the sequence of operations to be executed atomically and - prevents (actually delays) the preemption of a thread that is currently - executing instructions at that page. -* The MicroBlaze MMU supports several different page sizes (1K up to 16MB). - Genode fully supports this feature for page sizes >= 4K. This way, the TLB - footprint can be minimized by choosing sensible alignments of memory - objects. - -Current state -############# - -The MicroBlaze platform support resides in the 'base-mb' repository. At the -current stage, core is able to successfully start multiple nested instances of -the init process. Most of the critical kernel functionality is working. This -includes inter-process communication, address-space creation, multi-threading, -thread synchronization, page-fault handling, and TLB eviction. - -The nested init scenario runs on Qemu, emulating the Petalogix Spartan 3A -DSP1800 design, as well as on real hardware, tested with the Xilinx Spartan -3A Starter Kit configured with an appropriate Microblaze SoC. - -This simple scenario already illustrates the vast advantage of -using different page sizes supported by the MicroBlaze CPU. If using -4KB pages only, a scenario with three nested init processes produces more than -300.000 page faults. There is an extremely high pressure on the TLB, which -only contains 64 entries. Those entries are constantly evicted so that -threshing effects are likely to occur. By making use of flexible page -sizes (4K, 16K, 64K, 256K, 1M, 4M, 16M), the number of page faults gets -slashed to only 1.800, speeding up the boot time by factor 10. - -On hardware the capability remains to increase execution speed significantly -by turning on instruction- and data-caches. However this feature has not been -tested for now. - -The kernel provides, beyond the requirements of the nested init scenario, -allocation, handling and deallocation of IRQs to the userland to enable -core to offer IRQ and IO Memory session services. This allows -custom device-driver implementations within the userland. - -Currently, there is no restriction of IPC communication rights. Threads are -addressed using their global thread IDs (in fact, using their respective -indices in the KTCB array). For the future, we are planning to add -capabilty-based delegation of communication rights. diff --git a/base-mb/etc/specs.conf b/base-mb/etc/specs.conf deleted file mode 100755 index a3b84ce6d..000000000 --- a/base-mb/etc/specs.conf +++ /dev/null @@ -1 +0,0 @@ -SPECS ?= genode mb-s3a_starter_kit diff --git a/base-mb/etc/tools.conf b/base-mb/etc/tools.conf deleted file mode 100755 index dc0d02af9..000000000 --- a/base-mb/etc/tools.conf +++ /dev/null @@ -1,14 +0,0 @@ - -# Microblaze toolchain command prefix -CROSS_DEV_PREFIX ?= mb- - -# GCC code optimization level -CC_OLEVEL = -O2 - -# Disable garbage collection of sections by LD because the MicroBlaze toolchain -# would produce corrupted code with this option enabled. -LD_OPT_GC_SECTIONS = - -# Microblaze toolchain doesn't support #pragma GCC diagnostic, -# so avoid correspondig warnings. -CC_WARN += -Wno-pragmas diff --git a/base-mb/include/base/ipc_msgbuf.h b/base-mb/include/base/ipc_msgbuf.h deleted file mode 100755 index 456fc370a..000000000 --- a/base-mb/include/base/ipc_msgbuf.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * \brief Dummy IPC message buffer - * \author Norman Feske - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_ -#define _INCLUDE__BASE__IPC_MSGBUF_H_ - -namespace Genode { - - /** - * IPC message buffer layout - */ - class Msgbuf_base - { - protected: - - size_t _size; - char _msg_start[]; /* symbol marks start of message */ - - public: - - /* - * Begin of actual message buffer - */ - char buf[]; - - /** - * Return size of message buffer - */ - inline size_t size() const { return _size; } - - /** - * Return address of message buffer - */ - inline void *addr() { return &_msg_start[0]; } - }; - - - /** - * Instance of IPC message buffer with specified buffer size - */ - template - class Msgbuf : public Msgbuf_base - { - public: - - char buf[BUF_SIZE]; - - Msgbuf() { _size = BUF_SIZE; } - }; -} - -#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */ diff --git a/base-mb/include/base/ipc_pager.h b/base-mb/include/base/ipc_pager.h deleted file mode 100755 index fda01f994..000000000 --- a/base-mb/include/base/ipc_pager.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * \brief Dummy pager support for Genode - * \author Norman Feske, - * Martin Stein - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__BASE__IPC_PAGER_H_ -#define _INCLUDE__BASE__IPC_PAGER_H_ - -/* Genode includes */ -#include -#include -#include -#include - -/* Kernel includes */ -#include -#include - - -namespace Genode { - - namespace Paging { - - typedef Kernel::Paging::Resolution Native_resolution; - - /** - * Used by Genode's IPC Pager and RM Session Component - */ - class Resolution : public Native_resolution{ - - public: - - typedef Kernel::Paging::Physical_page Physical_page; - typedef Kernel::Paging::Virtual_page Virtual_page; - - private: - - enum { - INVALID_SIZE = Physical_page::INVALID_SIZE, - NO_PROTECTION_ID = 0, - DEFAULT_SIZE_LOG2 = Kernel::DEFAULT_PAGE_SIZE_LOG2, - DEFAULT_WRITEABLE = true, - DEFAULT_EXECUTABLE = true - }; - - bool _valid; - - public: - - ::Genode::Native_page_size _native_size(unsigned const size_log2) - { - using namespace Kernel; - using namespace Kernel::Paging; - - Physical_page::size_t s; - return Physical_page::size_by_size_log2(s, size_log2) ? - Physical_page::INVALID_SIZE : s; - } - - Native_page_permission _native_permission(bool const writeable, - bool const executable) - { - typedef Kernel::Paging::Physical_page Physical_page; - - if (writeable){ - if (executable) return Physical_page::RWX; - else return Physical_page::RW;} - else{ - if (executable) return Physical_page::RX; - else return Physical_page::R;} - } - - Resolution(addr_t virtual_page_address, - addr_t physical_page_address, - bool write_combined, bool io_mem, - unsigned size_log2 = DEFAULT_SIZE_LOG2, - bool writeable = DEFAULT_WRITEABLE) - : _valid(true) - { - virtual_page = Virtual_page(virtual_page_address, - NO_PROTECTION_ID); - - physical_page = Physical_page(physical_page_address, - _native_size(size_log2), - _native_permission(writeable, - DEFAULT_EXECUTABLE)); - } - - Resolution() : _valid(false) { } - - void prepare_map_operation() { } - - inline bool valid() { return _valid; } - }; - } - - typedef Paging::Resolution Mapping; - - /** - * Special paging server class - */ - class Ipc_pager : public Native_capability - { - typedef Kernel::Paging::Request Request; - - Mapping _mapping; - Request _request; - - public: - - /** - * Constructor - */ - Ipc_pager() - : Native_capability(Genode::my_thread_id(), 0) - { - _request.source.tid = 0; - } - - /** - * Wait for a new fault received as short message IPC - */ - void wait_for_fault(); - - /** - * Reply current fault and wait for a new one - * - * Send short flex page and wait for next short-message (register) - * IPC -- pagefault - */ - void reply_and_wait_for_fault(); - - bool resolved(); - - /** - * Request instruction pointer of current fault - */ - addr_t fault_ip() { return _request.source.ip; } - - /** - * Request fault address of current page fault - */ - addr_t fault_addr() { return _request.virtual_page.address(); } - - /** - * Set parameters for next reply - */ - inline void set_reply_mapping(Mapping m) { _mapping=m; } - - /** - * Set destination for next reply - */ - inline void set_reply_dst(Native_capability pager_object) { } - - /** - * Answer call without sending a flex-page mapping - * - * This function is used to acknowledge local calls from one of - * core's region-manager sessions. - */ - inline void acknowledge_wakeup() - { - Kernel::thread_wake(_request.source.tid); - } - - /** - * Return thread ID of last faulter - */ - inline Native_thread_id last() const { return _request.source.tid; } - - /** - * Return badge for faulting thread - */ - inline unsigned long badge() const { return _request.source.tid; } - - /** - * Was last fault a write fault? - */ - bool is_write_fault() const - { - return _request.access==Kernel::Paging::Request::RW || - _request.access==Kernel::Paging::Request::RWX; - } - - /** - * Return true if last fault was an exception - */ - bool is_exception() const - { - /* - * Reflection of exceptions is not supported on this platform. - */ - return false; - } - }; -} - -#endif /* _INCLUDE__BASE__IPC_PAGER_H_ */ diff --git a/base-mb/include/base/native_types.h b/base-mb/include/base/native_types.h deleted file mode 100755 index aaf1b30f8..000000000 --- a/base-mb/include/base/native_types.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * \brief Dummy definitions for native types used for compiling unit tests - * \author Norman Feske - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__BASE__NATIVE_TYPES_H_ -#define _INCLUDE__BASE__NATIVE_TYPES_H_ - -#include -#include -#include - -namespace Genode { - - typedef Kernel::Thread_id Native_thread_id; - typedef Native_thread_id Native_thread; - - typedef Kernel::Protection_id Native_process_id; - - typedef Kernel::Utcb_unaligned Native_utcb; - typedef Kernel::Paging::Physical_page::Permissions Native_page_permission; - typedef Kernel::Paging::Physical_page::size_t Native_page_size; - - Native_thread_id my_thread_id(); - - struct Cap_dst_policy - { - typedef Kernel::Thread_id Dst; - static bool valid(Dst tid) { - return tid != Kernel::INVALID_THREAD_ID; } - static Dst invalid() - { return Kernel::INVALID_THREAD_ID; } - static void copy(void* dst, Native_capability_tpl* src); - }; - - typedef Native_capability_tpl Native_capability; - typedef int Native_connection_state; - - struct Native_config - { - enum { - CONTEXT_AREA_VIRTUAL_BASE = 0x40000000, - CONTEXT_AREA_VIRTUAL_SIZE = 0x10000000, - CONTEXT_VIRTUAL_SIZE = 0x00100000, - }; - - /** - * Thread-context area configuration. - */ - static addr_t context_area_virtual_base() { return CONTEXT_AREA_VIRTUAL_BASE; } - static addr_t context_area_virtual_size() { return CONTEXT_AREA_VIRTUAL_SIZE; } - - /** - * Size of virtual address region holding the context of one thread - */ - static addr_t context_virtual_size() { return CONTEXT_VIRTUAL_SIZE; } - }; - - struct Native_pd_args { }; -} - -#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base-mb/include/cpu/atomic.h b/base-mb/include/cpu/atomic.h deleted file mode 100755 index 814041683..000000000 --- a/base-mb/include/cpu/atomic.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * \brief Atomic Userland operations for Microblaze - * \author Norman Feske - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__CPU__ATOMIC_H_ -#define _INCLUDE__CPU__ATOMIC_H_ - -#include - -namespace Genode { - - extern void* const _atomic_cmpxchg; - - - /** - * Executes compare and exchange as atomic operation - * - * This function compares the value at dest with cmp_val. - * If both values are equal, dest is set to new_val. If - * both values are different, the value at dest remains - * unchanged. - * - * \return 1 if the value was successfully changed to new_val, - * 0 if cmp_val and the value at dest differ. - */ - inline int cmpxchg(volatile int *dest, - unsigned int cmp_val, - unsigned int new_val) - { - int result = 0; - unsigned int r15_buf = 0; - - /** - * r27-r30 are arguments/return-values - * for _atomic_cmpxchg in r31 kernel denotes if - * interrupt has occured while executing atomic code - */ - asm volatile ("lwi r30, %[dest] \n" - "lwi r29, %[cmp_val] \n" - "lwi r28, %[new_val] \n" - "lwi r27, %[dest_val] \n" - "or r31, r0, r0 \n" - "swi r15, %[r15_buf] \n" - "bralid r15, _atomic_cmpxchg \n" - "or r0, r0, r0 \n" - "lwi r15, %[r15_buf] \n" - "swi r28, %[result] " - : - [result] "=m" (result), - [r15_buf] "+m" (r15_buf), - [dest] "+m" (dest), - [cmp_val] "+m" (cmp_val), - [new_val] "+m" (new_val), - [dest_val] "+m" (*dest) - :: "r31", "r30", "r29", "r28", "r27", "memory"); - - return result; - } -} - - -#endif /* _INCLUDE__CPU__ATOMIC_H_ */ diff --git a/base-mb/include/cpu/config.h b/base-mb/include/cpu/config.h deleted file mode 100755 index 145c254d0..000000000 --- a/base-mb/include/cpu/config.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * \brief Configuration of underlying hardware - * \author Martin stein - * \date 07-05-2010 - */ - -/* - * Copyright (C) 07-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__CPU__CONFIG_H_ -#define _INCLUDE__CPU__CONFIG_H_ - -#define ALWAYS_INLINE __attribute__((always_inline)) - -#define BITFIELD_ENUMS(name, bit_significancy_offset, bit_width) \ - name ## _LSH = bit_significancy_offset, \ - name ## _WID = bit_width, \ - name ## _MSK = ~((~0) << bit_width) << bit_significancy_offset, - -namespace Cpu { - - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - - typedef uint8_t byte_t; - typedef uint32_t word_t; - - typedef unsigned long addr_t; - typedef __SIZE_TYPE__ size_t; - - enum { - BYTE_WIDTH_LOG2 = 3, - WORD_WIDTH_LOG2 = 5, - BYTE_WIDTH = 1 << BYTE_WIDTH_LOG2, - WORD_WIDTH = 1 << WORD_WIDTH_LOG2, - BYTE_SIZE = sizeof(byte_t), - WORD_SIZE = sizeof(word_t), - - _16B_SIZE_LOG2 = 1*WORD_SIZE, - _256B_SIZE_LOG2 = 2*WORD_SIZE, - _4KB_SIZE_LOG2 = 3*WORD_SIZE, - _64KB_SIZE_LOG2 = 4*WORD_SIZE, - _1MB_SIZE_LOG2 = 5*WORD_SIZE, - _16MB_SIZE_LOG2 = 6*WORD_SIZE, - _256MB_SIZE_LOG2 = 7*WORD_SIZE, - - _16B_SIZE = 1 << _16B_SIZE_LOG2, - _256B_SIZE = 1 << _256B_SIZE_LOG2, - _4KB_SIZE = 1 << _4KB_SIZE_LOG2, - _64KB_SIZE = 1 << _64KB_SIZE_LOG2, - _1MB_SIZE = 1 << _1MB_SIZE_LOG2, - _16MB_SIZE = 1 << _16MB_SIZE_LOG2, - _256MB_SIZE = 1 << _256MB_SIZE_LOG2, - }; - - enum { - RAM_BASE = 0x90000000, - RAM_SIZE = 0x06000000, - - XPS_INTC_BASE = 0x81800000, - - XPS_TIMER_0_BASE = 0x83c00000, - XPS_TIMER_0_IRQ = 0, - - XPS_ETHERNETLITE_BASE = 0x81000000, - XPS_ETHERNETLITE_IRQ = 1, - - XPS_UARTLITE_BASE = 0x84000000, - XPS_UARTLITE_IRQ = 3, - - XPS_TIMER_1_BASE = 0x70000000, - XPS_TIMER_1_IRQ = 4, - }; - - typedef uint8_t Irq_id; - typedef uint8_t Exception_id; - - enum { - FAST_SIMPLEX_LINK = 0, - UNALIGNED = 1, - ILLEGAL_OPCODE = 2, - INSTRUCTION_BUS = 3, - DATA_BUS = 4, - DIV_BY_ZERO_EXCEPTON = 5, - FPU = 6, - PRIVILEGED_INSTRUCTION = 7, - - INTERRUPT = 10, - EXTERNAL_NON_MASKABLE_BREAK = 11, - EXTERNAL_MASKABLE_BREAK = 12, - - DATA_STORAGE = 16, - INSTRUCTION_STORAGE = 17, - DATA_TLB_MISS = 18, - INSTRUCTION_TLB_MISS = 19, - - MIN_EXCEPTION_ID = 0, - MAX_EXCEPTION_ID = 19, - - INVALID_EXCEPTION_ID = 20 - }; - - enum { - MIN_IRQ_ID = 0, - MAX_IRQ_ID = 31, - - INVALID_IRQ_ID = 32, - }; -} - -#endif /* _INCLUDE__CPU__CONFIG_H_ */ diff --git a/base-mb/include/cpu/cpu_state.h b/base-mb/include/cpu/cpu_state.h deleted file mode 100644 index f3586cec7..000000000 --- a/base-mb/include/cpu/cpu_state.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * \brief CPU state - * \author Martin Stein - * \date 2012-11-26 - */ - -/* - * Copyright (C) 2012-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _BASE_MB__INCLUDE__CPU__CPU_STATE_H_ -#define _BASE_MB__INCLUDE__CPU__CPU_STATE_H_ - -/* Genode includes */ -#include - -namespace Genode { - - /** - * Basic CPU state - */ - struct Cpu_state - { - /** - * Registers - */ - addr_t sp; /* stack pointer */ - addr_t ip; /* instruction pointer */ - }; -} - -#endif /* _BASE_MB__INCLUDE__CPU__CPU_STATE_H_ */ - diff --git a/base-mb/include/cpu/string.h b/base-mb/include/cpu/string.h deleted file mode 100644 index 7d5286fd5..000000000 --- a/base-mb/include/cpu/string.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * \brief Cpu specifi memcpy - * \author Martin Stein - * \date 2012-11-27 - */ - -/* - * Copyright (C) 2012-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _BASE_MB__INCLUDE__CPU__STRING_H_ -#define _BASE_MB__INCLUDE__CPU__STRING_H_ - -#include - -namespace Genode -{ - /** - * Copy memory block - * - * \param dst destination memory block - * \param src source memory block - * \param size number of bytes to copy - * - * \return Number of bytes not copied - */ - inline size_t memcpy_cpu(void *dst, const void *src, size_t size) - { - unsigned char *d = (unsigned char *)dst, *s = (unsigned char *)src; - - /* check 4 byte; alignment */ - size_t d_align = (size_t)d & 0x3; - size_t s_align = (size_t)s & 0x3; - - /* at least 32 bytes, 4 byte aligned, same alignment */ - if (size < 32 || (d_align ^ s_align)) - return size; - - /* copy to 4 byte alignment */ - for (size_t i = 0; i < s_align; i++, *d++ = *s++, size--); - - /* copy words */ - uint32_t * dw = (uint32_t *)d; - uint32_t * sw = (uint32_t *)s; - for (; size >= 4; size -= 4, dw++, sw++) *dw = *sw; - - return size; - } -} - -#endif /* _BASE_MB__INCLUDE__CPU__STRING_H_ */ diff --git a/base-mb/include/kernel/config.h b/base-mb/include/kernel/config.h deleted file mode 100755 index 15473f7d7..000000000 --- a/base-mb/include/kernel/config.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * \brief Configuration of kernel features - * \author Martin stein - * \date 24-06-2010 - */ - -/* - * Copyright (C) 24-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__KERNEL__CONFIG_H_ -#define _INCLUDE__KERNEL__CONFIG_H_ - -#include - -namespace Kernel -{ - enum { - SCHEDULING_MS_INTERVAL = 10, - SCHEDULING_TIMER_BASE = Cpu::XPS_TIMER_0_BASE, - SCHEDULING_TIMER_IRQ = Cpu::XPS_TIMER_0_IRQ, - - DEFAULT_PAGE_SIZE_LOG2 = Cpu::_4KB_SIZE_LOG2, - }; - - typedef Cpu::uint8_t Thread_id; - typedef Cpu::uint8_t Protection_id; - - enum{ - MIN_THREAD_ID = 1, - MAX_THREAD_ID = 64, - - MIN_PROTECTION_ID = 1, - MAX_PROTECTION_ID = 64, - - INVALID_THREAD_ID = 0, - INVALID_PROTECTION_ID = 0 }; -} - -namespace Roottask -{ - enum { - MAIN_STACK_SIZE = 1024*1024*Cpu::WORD_SIZE, - MAIN_THREAD_ID = 2, - - PROTECTION_ID = 1, - }; -} - -namespace User -{ - enum { - UART_BASE = Cpu::XPS_UARTLITE_BASE, - UART_IRQ = Cpu::XPS_UARTLITE_IRQ, - - IO_MEM_BASE = 0x70000000, - IO_MEM_SIZE = 0x10000000, - - XPS_TIMER_0_BASE = 0x70000000, - XPS_TIMER_0_IRQ = 4, - - MIN_IRQ = 4, - MAX_IRQ = 31, - - MIN_PROTECTION_ID = Roottask::PROTECTION_ID+1, - MAX_PROTECTION_ID = Kernel::MAX_PROTECTION_ID, - - MIN_THREAD_ID = Roottask::MAIN_THREAD_ID+1, - MAX_THREAD_ID = Kernel::MAX_THREAD_ID, - - VADDR_BASE = 0 + 1*(1< -#include - -/** - * Inline assembly clobber lists for syscalls with no arguments - */ -#define SYSCALL_7_ASM_CLOBBER "r24", SYSCALL_6_ASM_CLOBBER -#define SYSCALL_6_ASM_CLOBBER "r25", SYSCALL_5_ASM_CLOBBER -#define SYSCALL_5_ASM_CLOBBER "r26", SYSCALL_4_ASM_CLOBBER -#define SYSCALL_4_ASM_CLOBBER "r27", SYSCALL_3_ASM_CLOBBER -#define SYSCALL_3_ASM_CLOBBER "r28", SYSCALL_2_ASM_CLOBBER -#define SYSCALL_2_ASM_CLOBBER "r29", SYSCALL_1_ASM_CLOBBER -#define SYSCALL_1_ASM_CLOBBER SYSCALL_0_ASM_CLOBBER -#define SYSCALL_0_ASM_CLOBBER "r31", "r30" - -/** - * Inline assembly list for write access during syscalls with no arguments - */ -#define SYSCALL_0_ASM_WRITE \ - [result] "=m" (result), \ - [r15_buf] "+m" (r15_buf), \ - [opcode] "+m" (opcode) - - -/** - * Inline assembly lists for write access during syscalls with arguments - */ -#define SYSCALL_1_ASM_WRITE [arg_0] "+m" (arg_0), SYSCALL_0_ASM_WRITE -#define SYSCALL_2_ASM_WRITE [arg_1] "+m" (arg_1), SYSCALL_1_ASM_WRITE -#define SYSCALL_3_ASM_WRITE [arg_2] "+m" (arg_2), SYSCALL_2_ASM_WRITE -#define SYSCALL_4_ASM_WRITE [arg_3] "+m" (arg_3), SYSCALL_3_ASM_WRITE -#define SYSCALL_5_ASM_WRITE [arg_4] "+m" (arg_4), SYSCALL_4_ASM_WRITE -#define SYSCALL_6_ASM_WRITE [arg_5] "+m" (arg_5), SYSCALL_5_ASM_WRITE -#define SYSCALL_7_ASM_WRITE [arg_6] "+m" (arg_6), SYSCALL_6_ASM_WRITE - -/** - * Inline assembly ops for syscalls with no arguments - * - r19-r31 are save when occuring in the clobber list - * r15 is a 'dedicated' register and so we have to save it manually - */ -#define SYSCALL_0_ASM_OPS \ - "lwi r31, %[opcode] \n" \ - "swi r15, %[r15_buf] \n" \ - "brki r15, 0x8 \n" \ - "or r0, r0, r0 \n" \ - "lwi r15, %[r15_buf] \n" \ - "swi r30, %[result] " - -/** - * Inline assembly ops for syscalls with arguments - */ -#define SYSCALL_1_ASM_OPS "lwi r30, %[arg_0]\n" SYSCALL_0_ASM_OPS -#define SYSCALL_2_ASM_OPS "lwi r29, %[arg_1]\n" SYSCALL_1_ASM_OPS -#define SYSCALL_3_ASM_OPS "lwi r28, %[arg_2]\n" SYSCALL_2_ASM_OPS -#define SYSCALL_4_ASM_OPS "lwi r27, %[arg_3]\n" SYSCALL_3_ASM_OPS -#define SYSCALL_5_ASM_OPS "lwi r26, %[arg_4]\n" SYSCALL_4_ASM_OPS -#define SYSCALL_6_ASM_OPS "lwi r25, %[arg_5]\n" SYSCALL_5_ASM_OPS -#define SYSCALL_7_ASM_OPS "lwi r24, %[arg_6]\n" SYSCALL_6_ASM_OPS - -/** - * Inline assembly lists for read access during syscalls with arguments - */ -#define SYSCALL_0_ASM_READ -#define SYSCALL_1_ASM_READ SYSCALL_0_ASM_READ -#define SYSCALL_2_ASM_READ SYSCALL_1_ASM_READ -#define SYSCALL_3_ASM_READ SYSCALL_2_ASM_READ -#define SYSCALL_4_ASM_READ SYSCALL_3_ASM_READ -#define SYSCALL_5_ASM_READ SYSCALL_4_ASM_READ -#define SYSCALL_6_ASM_READ SYSCALL_5_ASM_READ -#define SYSCALL_7_ASM_READ SYSCALL_6_ASM_READ - - -namespace Kernel { - - using namespace Cpu; - - typedef unsigned int Syscall_arg; - - /** - * Syscall with 1 Argument - */ - ALWAYS_INLINE inline int syscall(Syscall_id opcode); - - - /** - * Syscall with 2 Arguments - */ - ALWAYS_INLINE inline int syscall(Syscall_id opcode, - Syscall_arg arg_0); - - /** - * Syscall with 3 Arguments - */ - ALWAYS_INLINE inline int syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1); - - /** - * Syscall with 4 Arguments - */ - ALWAYS_INLINE inline int syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2); - - /** - * Syscall with 5 Arguments - */ - ALWAYS_INLINE inline int syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2, - Syscall_arg arg_3); - - /** - * Syscall with 6 Arguments - */ - ALWAYS_INLINE inline int syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2, - Syscall_arg arg_3, - Syscall_arg arg_4); - - /** - * Syscall with 7 Arguments - */ - ALWAYS_INLINE inline int syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2, - Syscall_arg arg_3, - Syscall_arg arg_4, - Syscall_arg arg_5); - - /** - * Syscall with 8 Arguments - */ - ALWAYS_INLINE inline int syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2, - Syscall_arg arg_3, - Syscall_arg arg_4, - Syscall_arg arg_5, - Syscall_arg arg_6); - - /** - * Yield thread execution and coninue with next - */ - inline void thread_yield(); - - /** - * Block thread that calls this - */ - inline void thread_sleep(); - - /** - * Create and start threads - * - * \param tid ident that thread should get - * \param pid threads protection domain - * \param pager_id threads page fault handler thread - * \param utcb_p virtual address of utcb - * \param vip initial virtual ip - * \param vsp initial virtual sp - * \param param scheduling parameters, not used by now - * \return 0 if new thread was created - * n > 0 if any error has occured (errorcodes planned) - */ - inline int thread_create(Thread_id tid, - Protection_id pid, - Thread_id pager_tid, - Utcb* utcb_p, - Cpu::addr_t vip, - Cpu::addr_t vsp, - unsigned int params); - - /** - * Kill thread - only with root rights - * - * \param tid ident of thread - * \return 0 if thread is awake after syscall - * n > 0 if any error has occured (errorcodes planned) - */ - inline int thread_kill(Thread_id tid); - - /** - * Unblock denoted thread - * - * \param tid ident of thread thats blocked - * \detail works only if destination has same protection - * domain or caller has rootrights - * \return 0 if thread is awake after syscall - * n > 0 if any error has occured (errorcodes planned) - */ - inline int thread_wake(Thread_id tid); - - /** - * Re-set pager of another thread - * - * \param dst_tid thread whose pager shall be changed - * \param pager_tid ident of pager thread - * \detail works only if caller has rootrights - * \return 0 if new pager of thread is successfully set - * n > 0 if any error has occured (errorcodes planned) - */ - inline int thread_pager(Thread_id dst_tid, - Thread_id pager_tid); - - /** - * Reply last and wait for new ipc request - * - * \param msg_length length of reply message - * \return length of received message - */ - inline int ipc_serve(unsigned int reply_size); - - /** - * Send ipc request denoted in utcb to specific thread - * - * \param dest_id ident of destination thread - * \param msg_length number of request-message words - * \return number of reply-message words, or - * zero if request was not successfull - */ - inline int ipc_request(Thread_id dest_tid, unsigned int msg_size); - - /** - * Load pageresolution to memory managment unit - * - * \param p_addr physical page address - * \param v_addr virtual page address - * \param pid protection domain ident - * \param size size of page - * \param permissions permission flags for page - * \return 0 if thread is awake after syscall - * n > 0 if any error has occured (errorcodes planned) - */ - inline int tlb_load(Cpu::addr_t p_address, - Cpu::addr_t v_address, - Protection_id pid, - Paging::Physical_page::size_t size, - Paging::Physical_page::Permissions permissions); - - /** - * Flush page resolution area from tlb - * - * \param pid protection domain id - * \param start startaddress of area - * \param size_kbyte size of area in 1KB units - * \return 0 if new thread was created - * n > 0 if any error has occured (errorcodes planned) - */ - inline int tlb_flush(Protection_id pid, - Cpu::addr_t start, - unsigned size); - - /** - * Print char to serial ouput - * - * \param c char to print - */ - inline void print_char(char c); - - /** - * Print various informations about a specific thread - * \param i Unique ID of the thread, if it remains 0 take our own ID - */ - inline void print_info(Thread_id const & i = 0); - - /** - * Allocate an IRQ to the calling thread if the IRQ is - * not allocated yet to another thread - * - * \param i Unique ID of the IRQ - * \return 0 If the IRQ is allocated to this thread now - * n != 0 If the IRQ is not allocated to this thread already - * (code of the error that has occured) - */ - inline int irq_allocate(Irq_id i); - - /** - * Free an IRQ from allocation if it is allocated by the - * calling thread - * - * \param i Unique ID of the IRQ - * \return 0 If the IRQ is free now - * n != 0 If the IRQ is allocated already - * (code of the error that has occured) - */ - inline int irq_free(Irq_id i); - - /** - * Sleep till the 'Irq_message'-queue of this thread is not - * empty. For any IRQ that is allocated by this thread and occures - * between the kernel-entrance inside 'irq_wait' and the next time this - * thread wakes up, an 'Irq_message' with metadata about the according - * IRQ is added to the threads 'Irq_message'-queue. - * When returning from 'irq_wait' the first message from the threads - * 'Irq_message'-queue is dequeued and written to the threads UTCB-base. - */ - inline void irq_wait(); -} - - -void Kernel::print_info(Thread_id const & i) -{ - syscall(PRINT_INFO, (Syscall_arg) i); -} - - -void Kernel::irq_wait() { syscall(IRQ_WAIT); } - - -int Kernel::irq_allocate(Irq_id i) -{ - return syscall(IRQ_ALLOCATE, (Syscall_arg) i); -} - - -int Kernel::irq_free(Irq_id i) { return syscall(IRQ_FREE, (Syscall_arg) i); } - - -void Kernel::thread_yield() { syscall(THREAD_YIELD); } - - -void Kernel::thread_sleep() { syscall(THREAD_SLEEP); } - - -int Kernel::thread_create(Thread_id tid, - Protection_id pid, - Thread_id pager_tid, - Utcb* utcb_p, - Cpu::addr_t vip, - Cpu::addr_t vsp, - unsigned int params) -{ - return syscall(THREAD_CREATE, - (Syscall_arg) tid, - (Syscall_arg) pid, - (Syscall_arg) pager_tid, - (Syscall_arg) utcb_p, - (Syscall_arg) vip, - (Syscall_arg) vsp, - (Syscall_arg) params); -} - - -int Kernel::thread_kill(Thread_id tid) -{ - return syscall(THREAD_KILL, (Syscall_arg) tid); -} - - -int Kernel::thread_wake(Thread_id tid) -{ - return syscall(THREAD_WAKE, (Syscall_arg) tid); -} - - -int Kernel::thread_pager(Thread_id dst_tid, - Thread_id pager_tid) -{ - return syscall( - THREAD_PAGER, - (Syscall_arg) dst_tid, - (Syscall_arg) pager_tid); -} - - -int Kernel::ipc_serve(unsigned int reply_size) -{ - return syscall(IPC_SERVE, (Syscall_arg) reply_size); -} - - -int Kernel::ipc_request(Thread_id dest_tid, - unsigned int msg_size) -{ - return syscall( - IPC_REQUEST, - (Syscall_arg) dest_tid, - (Syscall_arg) msg_size); -} - - -int Kernel::tlb_load(Cpu::addr_t p_address, - Cpu::addr_t v_address, - Protection_id pid, - Paging::Physical_page::size_t size, - Paging::Physical_page::Permissions permissions) -{ - return syscall( - TLB_LOAD, - (Syscall_arg) p_address, - (Syscall_arg) v_address, - (Syscall_arg) pid, - (Syscall_arg) size, - (Syscall_arg) permissions); -} - - -int Kernel::tlb_flush(Protection_id pid, - Cpu::addr_t start, - unsigned size) -{ - return syscall( - TLB_FLUSH, - (Syscall_arg) pid, - (Syscall_arg) start, - (Syscall_arg) size); -} - - -void Kernel::print_char(char c) { syscall(PRINT_CHAR, (Syscall_arg) c); } - - -int Kernel::syscall(Syscall_id opcode) -{ - int result; - unsigned int r15_buf; - - asm volatile(SYSCALL_0_ASM_OPS - : SYSCALL_0_ASM_WRITE - : SYSCALL_0_ASM_READ - : SYSCALL_0_ASM_CLOBBER); - - return result; -} - - -int Kernel::syscall(Syscall_id opcode, Syscall_arg arg_0) -{ - int result; - unsigned int r15_buf; - - asm volatile(SYSCALL_1_ASM_OPS - : SYSCALL_1_ASM_WRITE - : SYSCALL_1_ASM_READ - : SYSCALL_1_ASM_CLOBBER); - - return result; -} - - -int Kernel::syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1) -{ - int result; - unsigned int r15_buf; - - asm volatile(SYSCALL_2_ASM_OPS - : SYSCALL_2_ASM_WRITE - : SYSCALL_2_ASM_READ - : SYSCALL_2_ASM_CLOBBER); - - return result; -} - - -int Kernel::syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2) -{ - int result; - unsigned int r15_buf; - - asm volatile(SYSCALL_3_ASM_OPS - : SYSCALL_3_ASM_WRITE - : SYSCALL_3_ASM_READ - : SYSCALL_3_ASM_CLOBBER); - - return result; -} - - -int Kernel::syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2, - Syscall_arg arg_3) -{ - int result; - unsigned int r15_buf; - - asm volatile(SYSCALL_4_ASM_OPS - : SYSCALL_4_ASM_WRITE - : SYSCALL_4_ASM_READ - : SYSCALL_4_ASM_CLOBBER); - - return result; -} - - -int Kernel::syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2, - Syscall_arg arg_3, - Syscall_arg arg_4) -{ - int result; - unsigned int r15_buf; - - asm volatile(SYSCALL_5_ASM_OPS - : SYSCALL_5_ASM_WRITE - : SYSCALL_5_ASM_READ - : SYSCALL_5_ASM_CLOBBER); - - return result; -} - - -int Kernel::syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2, - Syscall_arg arg_3, - Syscall_arg arg_4, - Syscall_arg arg_5) -{ - int result; - unsigned int r15_buf; - - asm volatile(SYSCALL_6_ASM_OPS - : SYSCALL_6_ASM_WRITE - : SYSCALL_6_ASM_READ - : SYSCALL_6_ASM_CLOBBER); - - return result; -} - - -int Kernel::syscall(Syscall_id opcode, - Syscall_arg arg_0, - Syscall_arg arg_1, - Syscall_arg arg_2, - Syscall_arg arg_3, - Syscall_arg arg_4, - Syscall_arg arg_5, - Syscall_arg arg_6) -{ - int result; - unsigned int r15_buf; - - asm volatile(SYSCALL_7_ASM_OPS - : SYSCALL_7_ASM_WRITE - : SYSCALL_7_ASM_READ - : SYSCALL_7_ASM_CLOBBER); - - return result; -} - - -#endif /* _INCLUDE__KERNEL__SYSCALLS_H_ */ diff --git a/base-mb/include/kernel/types.h b/base-mb/include/kernel/types.h deleted file mode 100755 index 7271ee933..000000000 --- a/base-mb/include/kernel/types.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * \brief Kernel specific data types - * \author Martin stein - * \date 2010-10-01 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__KERNEL__TYPES_H_ -#define _INCLUDE__KERNEL__TYPES_H_ - -#include -#include -#include - -namespace Kernel { - - using namespace Cpu; - - enum {THREAD_CREATE_PARAMS_ROOTRIGHT_LSHIFT=0}; - - - struct Utcb_unaligned - { - enum { - ALIGNMENT_LOG2 = 0, - SIZE_LOG2 = Cpu::_4KB_SIZE_LOG2, - }; - - union - { - volatile Cpu::byte_t byte[1<= sizeof(size_by_size_log2) / sizeof(size_by_size_log2[0])) - return -2; - - if (size_by_size_log2[size_log2] == INVALID_SIZE) - return -3; - - s = size_by_size_log2[(unsigned)size_log2]; - return 0; -} - - -Cpu::size_t Kernel::Utcb_unaligned::size() -{ - return (Cpu::size_t)1< - -namespace Xilinx { - - /** - * Driver for the Xilinx LogiCORE IP XPS Interrupt Controller 2.01 - */ - class Xps_intc - { - public: - - typedef Cpu::uint32_t Register; - typedef Cpu::uint8_t Irq; - - enum { - REGISTER_WIDTH = sizeof(Register)*Cpu::BYTE_WIDTH, - MIN_IRQ = Cpu::MIN_IRQ_ID, - MAX_IRQ = Cpu::MAX_IRQ_ID, - INVALID_IRQ = Cpu::INVALID_IRQ_ID, - }; - - /** - * Constructor argument - */ - struct Constr_arg - { - Cpu::addr_t base; - - Constr_arg(Cpu::addr_t const & b) : base(b) { } - }; - - /** - * Probe if IRQ ID is valid at this controller - */ - inline bool valid(Irq const & i); - - /** - * Enable propagation of all IRQ inputs - */ - inline void unmask(); - - /** - * Enable propagation of all IRQ inputs - */ - inline void unmask(Irq const & i); - - /** - * Disable propagation of all IRQ inputs - * (anyhow the occurency of IRQ's gets noticed in ISR) - */ - inline void mask(); - - /** - * Disable propagation of an IRQ input - * (anyhow the occurency of the IRQ's gets noticed in ISR) - */ - inline void mask(Irq const & i); - - /** - * Constructor - * All IRQ's are masked initially - */ - inline Xps_intc(Constr_arg const & ca); - - /** - * Destructor - * All IRQ's are left masked - */ - inline ~Xps_intc(); - - /** - * Get the pending IRQ with - * the highest priority (that one with the lowest IRQ ID) - */ - inline Irq next_irq(); - - /** - * Release IRQ input so it can occure again - * (in general IRQ source gets acknowledged thereby) - */ - inline void release(Irq const & i); - - /** - * Probe if IRQ is pending (unmasked and active) - */ - inline bool pending(Irq const & i); - - private: - - /** - * Register mapping offsets relative to the device base address - */ - enum { - RISR_OFFSET = 0 * Cpu::WORD_SIZE, - RIPR_OFFSET = 1 * Cpu::WORD_SIZE, - RIER_OFFSET = 2 * Cpu::WORD_SIZE, - RIAR_OFFSET = 3 * Cpu::WORD_SIZE, - RSIE_OFFSET = 4 * Cpu::WORD_SIZE, - RCIE_OFFSET = 5 * Cpu::WORD_SIZE, - RIVR_OFFSET = 6 * Cpu::WORD_SIZE, - RMER_OFFSET = 7 * Cpu::WORD_SIZE, - RMAX_OFFSET = 8 * Cpu::WORD_SIZE, - - RMER_ME_LSHIFT = 0, - RMER_HIE_LSHIFT = 1 - }; - - /** - * Short register description (no optional registers) - * - * ISR IRQ status register, a bit in here is '1' as long as the - * according IRQ-input is '1', IRQ/bit correlation: [MAX_IRQ,...,1,0] - * IER IRQ unmask register, as long as a bit is '1' in IER the controller - * output equals the according bit in ISR as long as MER[ME] is '1' - * IAR IRQ acknowledge register, writing a '1' to a bit in IAR writes - * '0' to the according bit in ISR and '0' to bit in IAR - * SIE Set IRQ unmask register, writing a '1' to a bit in SIE sets the - * according bit in IER to '1' and writes '0' to the bit in SIE - * CIE Clear IRQ unmask register, writing a '1' to a bit in SIE sets the - * according bit in IER to '0' and writes '0' to the bit in CIE - * MER Master unmask register, structure: [0,...,0,HIE,ME], controller - * output is '0' as long as ME is '0', HIE is '0' initally so - * software IRQ mode is active writing '1' to HIE switches to - * hardware IRQ mode and masks writing to HIE - */ - volatile Register* const _risr; - volatile Register* const _rier; - volatile Register* const _riar; - volatile Register* const _rsie; - volatile Register* const _rcie; - volatile Register* const _rmer; - }; -} - - -void Xilinx::Xps_intc::unmask() { *_rsie = ~0; } - - -void Xilinx::Xps_intc::unmask(Irq const & i) -{ - if (!valid(i)) { return; } - *_rsie = 1 << i; -} - - -void Xilinx::Xps_intc::mask() { *_rcie = ~0; } - - -void Xilinx::Xps_intc::mask(Irq const & i) -{ - if (!valid(i)) { return; } - *_rcie = 1 << i; -} - - -bool Xilinx::Xps_intc::pending(Irq const & i) -{ - if (!valid(i)) { return false; } - Register const pending = *_risr & *_rier; - return pending & (1 << i); -} - - -bool Xilinx::Xps_intc::valid(Irq const & i) -{ - return !(i == INVALID_IRQ || i > MAX_IRQ); -} - - -Xilinx::Xps_intc::Xps_intc(Constr_arg const & ca) : - _risr((Register*)(ca.base + RISR_OFFSET)), - _rier((Register*)(ca.base + RIER_OFFSET)), - _riar((Register*)(ca.base + RIAR_OFFSET)), - _rsie((Register*)(ca.base + RSIE_OFFSET)), - _rcie((Register*)(ca.base + RCIE_OFFSET)), - _rmer((Register*)(ca.base + RMER_OFFSET)) -{ - *_rmer = 1 << RMER_HIE_LSHIFT | 1 << RMER_ME_LSHIFT; - mask(); -} - - -Xilinx::Xps_intc::~Xps_intc() -{ - mask(); -} - - -Xilinx::Xps_intc::Irq Xilinx::Xps_intc::next_irq() -{ - Register const pending = *_risr & *_rier; - Register bit_mask = 1; - - for (unsigned int i=0; i - -namespace Xilinx { - - /** - * Driver for the Xilinx LogiCORE XPS Timer/Counter IP 1.02 - */ - class Xps_timer - { - public: - - /** - * CPU dependencies - */ - typedef Cpu::word_t word_t; - typedef Cpu::addr_t addr_t; - typedef Cpu::size_t size_t; - typedef Cpu::uint32_t uint32_t; - - /** - * MMIO register - */ - typedef uint32_t Register; - - /** - * Constructor, resets timer, overwrites timer value with '0' - */ - inline Xps_timer(addr_t const &base); - - /** - * Destructor, resets timer, overwrites timer value with '0' - */ - inline ~Xps_timer(); - - /** - * Overwrite timer value with X>0, count downwards to '0', set the - * IRQ output to '1' for one cycle and simultaneously start counting - * downwards again from X, and so on ... - * - * \param value the value X - */ - inline void run_periodic(unsigned int const &value); - - /** - * Overwrite timer value with X>0, count downwards to '0', set the - * IRQ output to '1' for one cycle and simultaneously start counting - * downwards from max_value() to '0', and so on ... - * - * \param value the value X - */ - inline void run_circulating(unsigned int const &value); - - /** - * Overwrite timer value with X>0, count downwards to '0', set the - * IRQ output to '1' for one cycle, timer value remains '0' - * - * \param value the value X - */ - inline void run_oneshot(unsigned int const &value); - - /** - * Prepare a 'run_oneshot()'-like run that shall be triggered with - * simple means. Useful for starting the timer out of assembly-code. - * - * \param value native time-value used to assess the delay - * of the timer IRQ as of the triggering - * \param start_val at this address the start value gets deposited - * \param start_reg at this address an address X gets deposited - * writing the start value to X later starts the - * timer as prepared - */ - inline void prepare_oneshot(unsigned int const & value, - volatile Register * & start_reg, - Register & start_val); - - /** - * Current timer value - */ - inline unsigned int value(); - - /** - * Return the timers current value and determine if the timer has hit '0' - * before the returned value and after the last time we started it or called - * 'period_value' on it. Called during non-periodic runs 'rolled_over' - * becomes 'true' if value is '0' and 'false' otherwise - * - * Enable exclusive access only to this function to ensure correct behavior! - * This function delays the timer about the duration of a few cpu cycles! - */ - inline unsigned int period_value(bool * const & rolled_over); - - /** - * Size of the MMIO provided by the timer device - */ - static inline size_t size(); - - /** - * Maximum timer value - */ - static inline unsigned int max_value(); - - /** - * Converting a native time value to milliseconds - */ - static inline unsigned int native_to_msec(unsigned int const &v); - - /** - * Converting milliseconds to a native time value - */ - static inline unsigned int msec_to_native(unsigned int const &v); - - /** - * Converting a native time value to microseconds - */ - static inline unsigned int native_to_usec(unsigned int const &v); - - /** - * Converting microseconds to a native time value - */ - static inline unsigned int usec_to_native(unsigned int const &v); - - private: - - /** - * General constraints - */ - enum { - WORD_SIZE = sizeof(word_t), - BYTE_WIDTH = Cpu::BYTE_WIDTH, - FREQUENCY_PER_US = 62, - }; - - /** - * Registers - */ - enum { - /* Control/status register */ - RTCSR0_OFFSET = 0*WORD_SIZE, - - /* Load register, written to RTCR when RTCSR[LOAD]='1' */ - RTLR0_OFFSET = 1*WORD_SIZE, - - /* On timer/counter register the counting is done */ - RTCR0_OFFSET = 2*WORD_SIZE, - - /* Respectively for the second timer/counter module */ - RTCSR1_OFFSET = 4*WORD_SIZE, - RTLR1_OFFSET = 5*WORD_SIZE, - RTCR1_OFFSET = 6*WORD_SIZE, - - MMIO_SIZE = 8*WORD_SIZE, - - /* r/w '0': generate timer mode - * r/w '1': capture timer mode */ - RTCSR_MDT_LSHIFT = 0, - - /* r/w '0': count upward mode - * r/w '1': count downward mode */ - RTCSR_UDT_LSHIFT = 1, - - /* r/w '0': external generate signal disabled mode - * r/w '1': external generate signal enabled mode */ - RTCSR_GENT_LSHIFT = 2, - - /* r/w '0': external capture trigger disabled mode - * r/w '1': external capture trigger enabled mode */ - RTCSR_CAPT_LSHIFT = 3, - - /* r/w '0': hold values mode - * r/w '0': auto reload (generate timer) / overwrite (capture timer) mode */ - RTCSR_ARHT_LSHIFT = 4, - - /* w/r '0': disable loading mode - * w/r '1': loading timer mode (RTCR=RTLR) */ - RTCSR_LOAD_LSHIFT = 5, - - /* w/r '0': throw no IRQ mode (doesn't affect RTCSR[TINT]) - * w/r '1': throw IRQ on 0-1-edge at RTCSR[TINT] mode */ - RTCSR_ENIT_LSHIFT = 6, - - /* w/r '0': don't count (RTCR remains constant) - * w/r '1': count on RTCR */ - RTCSR_ENT_LSHIFT = 7, - - /* r '0': no IRQ has occured - * r '1': IRQ has occured - * w '0': no effect - * w '1': RTCSR[TINT]=0 */ - RTCSR_TINT_LSHIFT = 8, - - /* r/w '0': pulse width modulation disabled mode - * r/w '1': pulse width modulation enabled mode */ - RTCSR_PWM_LSHIFT = 9, - - /* w/r '0': nothing - * w/r '1': RTCSR[ENT]='1' for all timer/counter modules */ - RTCSR_ENALL_LSHIFT = 10, - }; - - /** - * Controls for RTCSR - */ - enum { - RUN_ONCE = 0 - | 0 << RTCSR_MDT_LSHIFT - | 1 << RTCSR_UDT_LSHIFT - | 0 << RTCSR_CAPT_LSHIFT - | 0 << RTCSR_GENT_LSHIFT - | 0 << RTCSR_ARHT_LSHIFT - | 0 << RTCSR_LOAD_LSHIFT - | 1 << RTCSR_ENIT_LSHIFT - | 1 << RTCSR_ENT_LSHIFT - | 1 << RTCSR_TINT_LSHIFT - | 0 << RTCSR_PWM_LSHIFT - | 0 << RTCSR_ENALL_LSHIFT - , - - STOP_N_LOAD = 0 - | 0 << RTCSR_MDT_LSHIFT - | 1 << RTCSR_UDT_LSHIFT - | 0 << RTCSR_CAPT_LSHIFT - | 0 << RTCSR_GENT_LSHIFT - | 0 << RTCSR_ARHT_LSHIFT - | 1 << RTCSR_LOAD_LSHIFT - | 0 << RTCSR_ENIT_LSHIFT - | 0 << RTCSR_ENT_LSHIFT - | 0 << RTCSR_TINT_LSHIFT - | 0 << RTCSR_PWM_LSHIFT - | 0 << RTCSR_ENALL_LSHIFT - , - - RUN_PERIODIC = RUN_ONCE - | 1 << RTCSR_ARHT_LSHIFT - , - - STOP_N_RESET = STOP_N_LOAD - | 1 << RTCSR_TINT_LSHIFT - , - }; - - /** - * Absolute register addresses - */ - volatile Register *const _rtcsr0; - volatile Register *const _rtlr0; - volatile Register *const _rtcr0; - volatile Register *const _rtcsr1; - volatile Register *const _rtlr1; - volatile Register *const _rtcr1; - }; -} - - -Xilinx::Xps_timer::Xps_timer(addr_t const &base) -: - _rtcsr0((Register *)(base + RTCSR0_OFFSET)), - _rtlr0((Register *)(base + RTLR0_OFFSET)), - _rtcr0((Register *)(base + RTCR0_OFFSET)), - _rtcsr1((Register *)(base + RTCSR1_OFFSET)), - _rtlr1((Register *)(base + RTLR1_OFFSET)), - _rtcr1((Register *)(base + RTCR1_OFFSET)) -{ - *_rtcsr0 = STOP_N_RESET; - *_rtcsr1 = STOP_N_RESET; - *_rtlr0 = 0; -} - - -Xilinx::Xps_timer::size_t Xilinx::Xps_timer::size() -{ - return (size_t)MMIO_SIZE; -} - - -unsigned int Xilinx::Xps_timer::max_value() { return ((unsigned int)~0); } - - -void Xilinx::Xps_timer::prepare_oneshot(unsigned int const & value, - volatile Register * & start_reg, - Register & start_val) -{ - *_rtcsr0 = STOP_N_LOAD; - *_rtlr0 = value; - - start_reg = _rtcsr0; - start_val = RUN_ONCE; -} - - -void Xilinx::Xps_timer::run_circulating(unsigned int const &value) -{ - *_rtcsr0 = STOP_N_LOAD; - *_rtlr0 = value; - *_rtcsr0 = RUN_PERIODIC; - *_rtlr0 = max_value(); -} - - -void Xilinx::Xps_timer::run_periodic(unsigned int const &value) -{ - *_rtcsr0 = STOP_N_LOAD; - *_rtlr0 = value; - *_rtcsr0 = RUN_PERIODIC; -} - - -void Xilinx::Xps_timer::run_oneshot(unsigned int const &value) -{ - *_rtcsr0 = STOP_N_LOAD; - *_rtlr0 = value; - *_rtcsr0 = RUN_ONCE; -} - - -unsigned int Xilinx::Xps_timer::value() { return *_rtcr0; } - - -unsigned int Xilinx::Xps_timer::period_value(bool * const &rolled_over) -{ - if(!(*_rtcsr0 & (1 << RTCSR_ARHT_LSHIFT))){ - /* this is no periodic run */ - unsigned int const v = *_rtcr0; - *rolled_over = !(v); - return value(); - } - - /* 2 measurements are necessary to ensure that - * 'rolled_over' and the returned value are fit together - * because we can not halt the timer or read both simulanously */ - unsigned int const v1 = *_rtcr0; - *rolled_over = (bool)(*_rtcsr0 & (1 << RTCSR_TINT_LSHIFT)); - unsigned int const v2 = *_rtcr0; - - if(*rolled_over) { - /* v2 must be a value the timer had after rolling over, so restart - * the timer with the current value but RTCSR[TINT] reset */ - unsigned int const initial_rtlr = *_rtlr0; - unsigned int const restart_n_reset = *_rtcsr0 | (1 << RTCSR_TINT_LSHIFT); - *_rtlr0 = *_rtcr0; // timer gets delayed about the - *_rtcsr0 = restart_n_reset; // duration of these two operations - *_rtlr0 = initial_rtlr; - return v2; - } - - /* v1 must be a value that the timer had before rolling - * over, so we don't have to reset the "rolled over" status even - * if the timer has rolled over till now */ - return v1; -} - - -Xilinx::Xps_timer::~Xps_timer() -{ - *_rtcsr0 = STOP_N_RESET; - *_rtcsr1 = STOP_N_RESET; -} - - -unsigned int Xilinx::Xps_timer::native_to_msec(unsigned int const &v) -{ - return 1000*native_to_usec(v); -} - - -unsigned int Xilinx::Xps_timer::msec_to_native(unsigned int const &v) -{ - return 1000*usec_to_native(v); -} - - -unsigned int Xilinx::Xps_timer::native_to_usec(unsigned int const &v) -{ - return v/FREQUENCY_PER_US; -} - - -unsigned int Xilinx::Xps_timer::usec_to_native(unsigned int const &v) -{ - return v*FREQUENCY_PER_US; -} - - -#endif /* _INCLUDE__DEVICES__XILINX_XPS_TIMER_H_ */ diff --git a/base-mb/include/xilinx/xps_uartl.h b/base-mb/include/xilinx/xps_uartl.h deleted file mode 100644 index 7a8369b16..000000000 --- a/base-mb/include/xilinx/xps_uartl.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * \brief Driver for the Xilinx LogiCORE IP XPS UART Lite 1.01a - * \author Martin stein - * \date 2011-05-06 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__DEVICES__XILINX_XPS_UARTL_H_ -#define _INCLUDE__DEVICES__XILINX_XPS_UARTL_H_ - -#include - -namespace Xilinx { - - /** - * Driver for the Xilinx LogiCORE IP XPS UART Lite 1.01a - */ - class Xps_uartl - { - public: - - /** - * Constructor - */ - Xps_uartl(Cpu::addr_t const & base); - - /** - * Send one ASCII char over the UART interface - */ - inline void send(char const & c); - - private: - - /** - * Relative MMIO structure - */ - - typedef Cpu::uint32_t Register; - - enum { - RX_FIFO_OFF = 0 * Cpu::WORD_SIZE, - TX_FIFO_OFF = 1 * Cpu::WORD_SIZE, - STAT_REG_OFF = 2 * Cpu::WORD_SIZE, - CTRL_REG_OFF = 3 * Cpu::WORD_SIZE, - }; - - struct Rx_fifo { - enum { - BITFIELD_ENUMS(RX_DATA, 0, 8) - }; - }; - - struct Tx_fifo { - enum { - BITFIELD_ENUMS(TX_DATA, 0, 8) - }; - }; - - struct Ctrl_reg { - enum { - BITFIELD_ENUMS(RST_TX_FIFO, 0, 1) - BITFIELD_ENUMS(RST_RX_FIFO, 1, 1) - BITFIELD_ENUMS(ENABLE_INTR, 4, 1) - }; - }; - - struct Stat_reg { - enum { - BITFIELD_ENUMS(RX_FIFO_VALID_DATA, 0, 1) - BITFIELD_ENUMS(RX_FIFO_FULL, 1, 1) - BITFIELD_ENUMS(TX_FIFO_EMPTY, 2, 1) - BITFIELD_ENUMS(TX_FIFO_FULL, 3, 1) - BITFIELD_ENUMS(INTR_ENABLED, 4, 1) - BITFIELD_ENUMS(OVERRUN_ERROR, 5, 1) - BITFIELD_ENUMS(FRAME_ERROR, 6, 1) - BITFIELD_ENUMS(PARITY_ERROR, 7, 1) - }; - }; - - /** - * Absolute register pointers - */ - volatile Register* const _rx_fifo; - volatile Register* const _tx_fifo; - volatile Register* const _stat_reg; - volatile Register* const _ctrl_reg; - }; -} - - -Xilinx::Xps_uartl::Xps_uartl(Cpu::addr_t const & base) : - _rx_fifo((Register*)(base + RX_FIFO_OFF)), - _tx_fifo((Register*)(base + TX_FIFO_OFF)), - _stat_reg((Register*)(base + STAT_REG_OFF)), - _ctrl_reg((Register*)(base + CTRL_REG_OFF)) -{} - - -void Xilinx::Xps_uartl::send(char const & c){ - while(*_stat_reg & Stat_reg::TX_FIFO_FULL_MSK); - *_tx_fifo = c; -} - - -#endif /* _INCLUDE__DEVICES__XILINX_XPS_UARTL_H_ */ diff --git a/base-mb/lib/mk/cxx.mk b/base-mb/lib/mk/cxx.mk deleted file mode 100755 index 5d176c384..000000000 --- a/base-mb/lib/mk/cxx.mk +++ /dev/null @@ -1,87 +0,0 @@ -LIBS = allocator_avl -CXX_SRC_CC += misc.cc new_delete.cc malloc_free.cc exception.cc guard.cc - -vpath %.cc $(BASE_DIR)/src/base/cxx - -# -# Microblaze-specific supplement -# -CXX_SRC_CC += atexit.cc - -vpath %.cc $(REP_DIR)/src/base/cxx - -# -# Here we define all symbols we want to hide in libsupc++ and libgcc_eh -# -LIBC_SYMBOLS += malloc free calloc realloc \ - abort fputc fputs fwrite \ - stderr strcat strcpy strlen up \ - memcmp strncmp strcmp sprintf - -# -# Take the right system libraries -# -# Normally, we never include build-system-internal files from library- -# description files. For building the 'cxx' library, however, we need the -# information about the used 'gcc' for resolving the location of the C++ -# support libraries. This definition is performed by 'mk/lib.mk' after -# including this library description file. Hence, we need to manually -# include 'global.mk' here. -# -include $(BASE_DIR)/mk/global.mk - -LIBCXX_GCC = $(shell $(CUSTOM_CXX_LIB) -print-file-name=libsupc++.a) \ - $(shell $(CUSTOM_CXX_LIB) -print-libgcc-file-name) - -# $(shell $(CUSTOM_CXX_LIB) -print-file-name=libgcc_eh.a) - -# -# Dummy target used by the build system -# -SRC_S = supc++.o -CXX_SRC = $(sort $(CXX_SRC_CC)) -CXX_OBJECTS = $(addsuffix .o,$(basename $(CXX_SRC))) -LOCAL_SYMBOLS = $(patsubst %,--localize-symbol=%,$(LIBC_SYMBOLS)) - -# -# Prevent symbols of the gcc support libs from being discarded during 'ld -r' -# -KEEP_SYMBOLS += __cxa_guard_acquire -KEEP_SYMBOLS += __moddi3 __divdi3 __umoddi3 __udivdi3 -KEEP_SYMBOLS += _ZTVN10__cxxabiv116__enum_type_infoE -KEEP_SYMBOLS += __fixunsdfdi -KEEP_SYMBOLS += __udivsi3 __divsi3 - -# -# Keep symbols additionally needed for linking the libc on ARM -# -KEEP_SYMBOLS += __muldi3 __eqdf2 __fixdfsi __ltdf2 __ltdf2 __nedf2 __ltdf2 \ - __gtdf2 __ltdf2 __ledf2 __fixdfsi __ltdf2 __ltdf2 __eqdf2 \ - __fixdfsi __ltdf2 __fixdfsi __eqdf2 __gtdf2 __ltdf2 __gtdf2 \ - __eqdf2 __muldi3 __muldi3 - -# -# Keep symbols needed for floating-point support on ARM -# -KEEP_SYMBOLS += __addsf3 __gtsf2 __ltsf2 - -# -# Additional symbols we need to keep when using the arm-none-linux-gnueabi -# tool chain -# -KEEP_SYMBOLS += __aeabi_ldivmod __aeabi_uldivmod __dynamic_cast -KEEP_SYMBOLS += _ZN10__cxxabiv121__vmi_class_type_infoD0Ev -KEEP_SYMBOLS += __aeabi_idiv __aeabi_ulcmp __aeabi_fmul __aeabi_dcmpun \ - __aeabi_d2lz __aeabi_f2lz __aeabi_d2f __aeabi_fcmpun \ - __aeabi_f2iz ctx_done sincos sincosf tgamma - -# -# Rule to link all libc definitions and libsupc++ libraries -# and to hide after that the exported libc symbols -# -$(SRC_S): $(CXX_OBJECTS) - $(MSG_MERGE)$@ - $(VERBOSE)$(LD) $(addprefix -u ,$(KEEP_SYMBOLS)) -r $(CXX_OBJECTS) $(LIBCXX_GCC) -o $@.tmp - $(MSG_CONVERT)$@ - $(VERBOSE)$(OBJCOPY) $(LOCAL_SYMBOLS) $@.tmp $@ - $(VERBOSE)$(RM) $@.tmp diff --git a/base-mb/lib/mk/ipc.mk b/base-mb/lib/mk/ipc.mk deleted file mode 100755 index 46a5dcd7f..000000000 --- a/base-mb/lib/mk/ipc.mk +++ /dev/null @@ -1,7 +0,0 @@ -SRC_CC = ipc.cc ipc_marshal_cap.cc -SRC_CC += pager.cc -LIBS += thread_context cap_copy - -vpath ipc.cc $(REP_DIR)/src/base/ipc -vpath pager.cc $(REP_DIR)/src/base/ipc -vpath ipc_marshal_cap.cc $(BASE_DIR)/src/base/ipc diff --git a/base-mb/lib/mk/kernel.inc b/base-mb/lib/mk/kernel.inc deleted file mode 100755 index 5d7fbe218..000000000 --- a/base-mb/lib/mk/kernel.inc +++ /dev/null @@ -1,41 +0,0 @@ -KERNEL_DIR = $(REP_DIR)/src/kernel - -INC_DIR += $(KERNEL_DIR)/include -INC_DIR += $(REP_DIR)/src/core/include - - -## -## Platform-specific kernel parts -## - -PLATFORM = petalogix_s3adsp1800_mmu - -# -# Basic platform support -# -include $(LIBINC_DIR)/$(PLATFORM)__kernel_support.inc - -# -# Enable atomic operations for this platform -# -LIBS += $(PLATFORM)__atomic_operations - - -## -## Generic kernel parts -## - -GENERIC_DIR = $(KERNEL_DIR)/generic - -SRC_CC += kernel.cc -SRC_CC += scheduler.cc -SRC_CC += thread.cc -SRC_CC += blocking.cc -SRC_CC += syscall_events.cc - -vpath kernel.cc $(GENERIC_DIR) -vpath scheduler.cc $(GENERIC_DIR) -vpath thread.cc $(GENERIC_DIR) -vpath blocking.cc $(GENERIC_DIR) -vpath syscall_events.cc $(GENERIC_DIR) - diff --git a/base-mb/lib/mk/kernel_core.mk b/base-mb/lib/mk/kernel_core.mk deleted file mode 100755 index 090e52136..000000000 --- a/base-mb/lib/mk/kernel_core.mk +++ /dev/null @@ -1,13 +0,0 @@ -LIBINC_DIR = $(REP_DIR)/lib/mk - -include $(LIBINC_DIR)/kernel.inc - -INC_DIR += $(REP_DIR)/src/platform -INC_DIR += $(REP_DIR)/src/core -INC_DIR += $(BASE_DIR)/src/platform - -include $(LIBINC_DIR)/kernel.inc -CC_OPT += -DROOTTASK_ENTRY=_main -SRC_CC += _main.cc - -vpath _main.cc $(BASE_DIR)/src/platform diff --git a/base-mb/lib/mk/kernel_test.inc b/base-mb/lib/mk/kernel_test.inc deleted file mode 100755 index a35e00097..000000000 --- a/base-mb/lib/mk/kernel_test.inc +++ /dev/null @@ -1,7 +0,0 @@ -LIBINC_DIR = $(REP_DIR)/lib/mk - -include $(LIBINC_DIR)/kernel.inc - -INC_DIR += $(REP_DIR)/src/platform -INC_DIR += $(REP_DIR)/src/core -INC_DIR += $(BASE_DIR)/src/platform diff --git a/base-mb/lib/mk/lock.mk b/base-mb/lib/mk/lock.mk deleted file mode 100755 index b34dacabd..000000000 --- a/base-mb/lib/mk/lock.mk +++ /dev/null @@ -1,6 +0,0 @@ -PLATFORM = petalogix_s3adsp1800_mmu -LIBS = thread_context $(PLATFORM)__atomic_operations -SRC_CC = lock.cc -INC_DIR += $(REP_DIR)/src/base/lock - -vpath lock.cc $(BASE_DIR)/src/base/lock diff --git a/base-mb/lib/mk/pager.mk b/base-mb/lib/mk/pager.mk deleted file mode 100755 index 24f25bcf8..000000000 --- a/base-mb/lib/mk/pager.mk +++ /dev/null @@ -1,4 +0,0 @@ -SRC_CC = pager.cc -INC_DIR += $(REP_DIR)/include/codezero/dummies - -vpath pager.cc $(REP_DIR)/src/base/pager diff --git a/base-mb/lib/mk/petalogix_s3adsp1800_mmu__atomic_operations.mk b/base-mb/lib/mk/petalogix_s3adsp1800_mmu__atomic_operations.mk deleted file mode 100644 index 8ace07986..000000000 --- a/base-mb/lib/mk/petalogix_s3adsp1800_mmu__atomic_operations.mk +++ /dev/null @@ -1,6 +0,0 @@ -PLATFORM_DIR = $(REP_DIR)/src/kernel/platforms/petalogix_s3adsp1800_mmu - -INC_DIR += $(PLATFORM_DIR)/include - -SRC_S += atomic.s -vpath atomic.s $(PLATFORM_DIR) diff --git a/base-mb/lib/mk/petalogix_s3adsp1800_mmu__kernel_support.inc b/base-mb/lib/mk/petalogix_s3adsp1800_mmu__kernel_support.inc deleted file mode 100755 index 5c703ad10..000000000 --- a/base-mb/lib/mk/petalogix_s3adsp1800_mmu__kernel_support.inc +++ /dev/null @@ -1,29 +0,0 @@ -## -## Platform -## -PLATFORM = petalogix_s3adsp1800_mmu - -# -# Assembly include paths -# -INC_DIR += $(KERNEL_DIR)/platforms/$(PLATFORM)/include - -# -# C++ include paths -# -INC_DIR += $(KERNEL_DIR)/include/$(PLATFORM) - -# -# Sources -# -PLATFORM_DIR = $(KERNEL_DIR)/platforms/$(PLATFORM) - -SRC_CC += platform.cc -SRC_S += crt0_kernel.s -SRC_S += kernel_entry.s -SRC_S += userland_entry.s - -vpath platform.cc $(PLATFORM_DIR) -vpath crt0_kernel.s $(PLATFORM_DIR) -vpath kernel_entry.s $(PLATFORM_DIR) -vpath userland_entry.s $(PLATFORM_DIR) diff --git a/base-mb/lib/mk/printf_microblaze.mk b/base-mb/lib/mk/printf_microblaze.mk deleted file mode 100755 index 00c6c7588..000000000 --- a/base-mb/lib/mk/printf_microblaze.mk +++ /dev/null @@ -1,5 +0,0 @@ -SRC_CC = microblaze_console.cc -LIBS = cxx console -INC_DIR += $(REP_DIR)/src/platform - -vpath %.cc $(REP_DIR)/src/base/console diff --git a/base-mb/lib/mk/startup.mk b/base-mb/lib/mk/startup.mk deleted file mode 100755 index 9aec768c8..000000000 --- a/base-mb/lib/mk/startup.mk +++ /dev/null @@ -1,13 +0,0 @@ -PLATFORM = petalogix_s3adsp1800_mmu -KERNEL_DIR = $(REP_DIR)/src/kernel -PLATFORM_DIR = $(KERNEL_DIR)/platforms/$(PLATFORM) - -LIBS = cxx lock -SRC_S = crt0.s -SRC_CC += _main.cc -INC_DIR += $(REP_DIR)/src/platform -INC_DIR += $(BASE_DIR)/src/platform -INC_DIR += $(PLATFORM_DIR)/include - -vpath crt0.s $(PLATFORM_DIR) -vpath _main.cc $(dir $(call select_from_repositories,src/platform/_main.cc)) diff --git a/base-mb/lib/mk/test_env.mk b/base-mb/lib/mk/test_env.mk deleted file mode 100755 index 99adcd34f..000000000 --- a/base-mb/lib/mk/test_env.mk +++ /dev/null @@ -1,6 +0,0 @@ -SRC_CC = context_area.cc thread_roottask.cc thread.cc -LIBS += lock thread_context - -vpath thread.cc $(BASE_DIR)/src/base/thread -vpath thread_roottask.cc $(REP_DIR)/src/test -vpath context_area.cc $(REP_DIR)/src/test diff --git a/base-mb/lib/mk/thread.mk b/base-mb/lib/mk/thread.mk deleted file mode 100644 index 265adc053..000000000 --- a/base-mb/lib/mk/thread.mk +++ /dev/null @@ -1,8 +0,0 @@ -SRC_CC = thread.cc thread_start.cc thread_bootstrap.cc -INC_DIR += $(REP_DIR)/include/codezero/dummies -INC_DIR += $(REP_DIR)/src/core/include - -vpath thread.cc $(REP_DIR)/src/base/thread -vpath thread_start.cc $(REP_DIR)/src/base/thread -vpath thread_bootstrap.cc $(REP_DIR)/src/base/thread -vpath %.cc $(BASE_DIR)/src/base/thread diff --git a/base-mb/lib/mk/thread_context.mk b/base-mb/lib/mk/thread_context.mk deleted file mode 100755 index 3693bce60..000000000 --- a/base-mb/lib/mk/thread_context.mk +++ /dev/null @@ -1,5 +0,0 @@ -SRC_CC = thread_context.cc - -INC_DIR += $(REP_DIR)/src/core/include - -vpath thread_context.cc $(REP_DIR)/src/base/thread diff --git a/base-mb/mk/spec-mb_ml507.mk b/base-mb/mk/spec-mb_ml507.mk deleted file mode 100644 index e6199c897..000000000 --- a/base-mb/mk/spec-mb_ml507.mk +++ /dev/null @@ -1,7 +0,0 @@ -SPECS += 32bit mb_timer - -STARTUP_LIB ?= startup - -PRG_LIBS += $(STARTUP_LIB) - -include $(call select_from_repositories,mk/spec-32bit.mk) diff --git a/base-mb/mk/spec-mb_s3a_starter_kit.mk b/base-mb/mk/spec-mb_s3a_starter_kit.mk deleted file mode 100644 index e6199c897..000000000 --- a/base-mb/mk/spec-mb_s3a_starter_kit.mk +++ /dev/null @@ -1,7 +0,0 @@ -SPECS += 32bit mb_timer - -STARTUP_LIB ?= startup - -PRG_LIBS += $(STARTUP_LIB) - -include $(call select_from_repositories,mk/spec-32bit.mk) diff --git a/base-mb/platform/mb_s3a_starter_kit/Makefile b/base-mb/platform/mb_s3a_starter_kit/Makefile deleted file mode 100644 index 5d215f2c9..000000000 --- a/base-mb/platform/mb_s3a_starter_kit/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# -# \brief Prepare the Xilinx Spartan 3A Starter Kit to run Genode on it -# \author Martin Stein -# \date 2011-05-23 -# - -HW = s3a_starter_kit -WORK_DIR = $(shell pwd) -BIT_FILE = $(WORK_DIR)/system.bit -VERBOSE ?= @ -REP_DIR = ../.. -MK_DIR = $(REP_DIR)/platform/mk/ - -all: configure - -clean: - $(VERBOSE) rm -f $(TMP_FILES) - -.PHONY: all clean - -include $(MK_DIR)/$(HW).mk -include $(MK_DIR)/microblaze.mk diff --git a/base-mb/platform/mb_s3a_starter_kit/system.bit b/base-mb/platform/mb_s3a_starter_kit/system.bit deleted file mode 100644 index 13ca4c7f449374790dd6f3371249337f5c596cfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341653 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 z%0DAQfrUxwpn3y{ujzP%1w?bOu+9O|5*& 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

jwnG&%FflNL=4P0U6AoOy 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 diff --git a/base-mb/platform/mk/microblaze.mk b/base-mb/platform/mk/microblaze.mk deleted file mode 100644 index a0b8be9a6..000000000 --- a/base-mb/platform/mk/microblaze.mk +++ /dev/null @@ -1,19 +0,0 @@ -# -# \brief Upload an image to the supported Microblaze SoC's -# \author Martin Stein -# \date 2011-05-23 -# - -UPLOAD_XMD = $(WORK_DIR)/upload.xmd - -upload: $(UPLOAD_XMD) - $(VERBOSE) xmd -opt $(UPLOAD_XMD) - -$(UPLOAD_XMD): - $(VERBOSE)echo \ - "connect mb mdm"\ - "\ndow $(IMAGE)"\ - > $(UPLOAD_XMD) - -.INTERMEDIATE: $(UPLOAD_XMD) -.PHONY: upload diff --git a/base-mb/platform/mk/ml507.mk b/base-mb/platform/mk/ml507.mk deleted file mode 100644 index e26bf6d7b..000000000 --- a/base-mb/platform/mk/ml507.mk +++ /dev/null @@ -1,19 +0,0 @@ -# -# \brief Configure support for the Xilinx ML507 Development Kit via JTAG -# \author Martin Stein -# \date 2011-05-23 -# - -$(CONFIGURE_IMPACT): - $(VERBOSE) echo \ - "setMode -bscan"\ - "\nsetCable -p auto"\ - "\nidentify"\ - "\nassignfile -p 5 -file $(BIT_FILE)"\ - "\nprogram -p 5"\ - "\nquit"\ - > $@ - -.INTERMEDIATE: $(CONFIGURE_IMPACT) - -include $(MK_DIR)/xilinx.mk diff --git a/base-mb/platform/mk/s3a_starter_kit.mk b/base-mb/platform/mk/s3a_starter_kit.mk deleted file mode 100644 index 5ea33e93e..000000000 --- a/base-mb/platform/mk/s3a_starter_kit.mk +++ /dev/null @@ -1,22 +0,0 @@ -# -# \brief Configure support for the Xilinx Spartan 3A Starter Kit via JTAG -# \author Martin Stein -# \date 2011-05-23 -# - -CONFIGURE_IMPACT = $(WORK_DIR)/configure.impact - -$(CONFIGURE_IMPACT): - $(VERBOSE) echo \ - "\nsetMode -bs"\ - "\nsetCable -port auto"\ - "\nIdentify -inferir"\ - "\nidentifyMPM"\ - "\nassignFile -p 1 -file \"$(BIT_FILE)\""\ - "\nProgram -p 1"\ - "\nquit"\ - > $@ - -.INTERMEDIATE: $(CONFIGURE_IMPACT) - -include $(MK_DIR)/xilinx.mk diff --git a/base-mb/platform/mk/xilinx.mk b/base-mb/platform/mk/xilinx.mk deleted file mode 100644 index a607f7bce..000000000 --- a/base-mb/platform/mk/xilinx.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -# \brief Configure the supported Xilinx FPGAs -# \author Martin Stein -# \date 2011-05-23 -# - -TMP_FILES += $(WORK_DIR)/_impactbatch.log -CLEANLOCK_IMPACT = $(WORK_DIR)/cleanlock.impact - -configure: $(CONFIGURE_IMPACT) cleanlock - $(VERBOSE) impact -batch $(CONFIGURE_IMPACT) - $(VERBOSE) make clean - -cleanlock: $(CLEANLOCK_IMPACT) - $(VERBOSE) impact -batch $(CLEANLOCK_IMPACT) || true - -$(CLEANLOCK_IMPACT): - $(VERBOSE) echo \ - "cleancablelock"\ - "\nexit"\ - > $@ - -.INTERMEDIATE: $(UPLOAD_XMD) $(CLEANLOCK_IMPACT) -.PHONY: configure cleanlock diff --git a/base-mb/run/env b/base-mb/run/env deleted file mode 100755 index fb595ba1f..000000000 --- a/base-mb/run/env +++ /dev/null @@ -1,211 +0,0 @@ -# -# \brief Environment for executing Genode on Microblaze -# \author Norman Feske -# \author Martin Stein -# \date 2010-09-01 -# -# For the documentation of the implemented API functions, -# please refer to the comments in 'tool/run'. -# - -proc create_boot_directory { } { - catch { - exec rm -rf [run_dir] - exec mkdir -p [run_dir] - } -} - - -proc build {targets {build_core 0}} { - - if {[get_cmd_switch --skip-build]} return - - regsub -all {\s\s+} $targets " " targets - - # Save building 'core' until last - if {$build_core == 0} { - regsub -all {\mcore\M} $targets "" targets - } - - puts "building targets: $targets" - set timeout 10000 - set pid [eval "spawn make $targets"] - expect { eof { } } - if {[lindex [wait $pid] end] != 0} { - puts "Error: Genode build failed" - exit -4 - } - puts "genode build completed" -} - -proc stripped_copy {binary} { - exec mkdir -p bin/stripped/ - exec rm -rf bin/stripped/$binary - exec cp bin/${binary} bin/stripped/${binary} - catch {exec [cross_dev_prefix]strip bin/stripped/${binary}} -} - - -# -# Microblaze needs a single boot image, thus this function creates an temporary assembly file that -# includes all images wich are needed by the boot image to be included by it -# -proc build_boot_modules {} { - - global boot_modules - global boot_modules_s - set boot_modules_s "[genode_dir]/base-mb/src/core/boot_modules.s" - - exec echo -e \ - "\n/**"\ - "\n * This file was generated by the expect procedure"\ - "\n * 'build_boot_modules' in 'run/env'"\ - "\n */"\ - "\n\n"\ - "\n.global _boot_modules_meta_start" \ - "\n.global _boot_modules_meta_end" \ - "\n\n" \ - "\n.section .data" \ - "\n.string \"GROM\"" \ - "\n.long header_end" \ - "\n.align 4" \ - "\n_boot_modules_meta_start:" > $boot_modules_s - - # Header, pointers part - set i 1 - foreach module $boot_modules { - exec echo -e \ - "\n.long mod${i}_name" \ - "\n.long mod${i}_start" \ - "\n.long mod${i}_end - mod${i}_start" >> $boot_modules_s - incr i - } - - exec echo -e \ - "\n.align 4"\ - "\n_boot_modules_meta_end:" >> $boot_modules_s - - # Header, names part - set i 1 - foreach module $boot_modules { - exec echo -e \ - "\nmod${i}_name:" \ - "\n.string \"${module}\"" \ - "\n.byte 0" >> $boot_modules_s - incr i - } - - exec echo -e "header_end:" >> $boot_modules_s - - # Modulecontents - set i 1 - foreach module $boot_modules { - exec echo -e ".align 12" >> $boot_modules_s - -# Stripped images the boot image depends on are not enabled because 'mb-strip' destroys -# the file offset alignments and Genode needs a specific minimum file offset alignment -# -# if { [catch {exec [cross_dev_prefix]readelf -h bin/${module}}] } { - exec echo -e "mod${i}_start: .incbin \"../bin/${module}\"" >> $boot_modules_s -# } else { -# exec echo -e "mod${i}_start: .incbin \"../bin/stripped/${module}\"" >> $boot_modules_s -# } - exec echo -e "mod${i}_end:" >> $boot_modules_s - incr i - } - - exec echo -e ".align 12" >> $boot_modules_s -} - - -proc build_boot_image {images} { - global boot_modules - global boot_modules_s - - foreach image $images { - if {$image != "core"} { - -# Stripped images the boot image depends on are not enabled because 'mb-strip' destroys -# the file offset alignments and Genode needs a specific minimum file offset alignment -# -# if { [catch {exec [cross_dev_prefix]readelf -h bin/${image}}] == 0 } { -# stripped_copy $image -# } - append boot_modules "${image}" " " - } - } - - build_boot_modules - build "core" 1 - stripped_copy "core" - catch { - exec ln -sf ../../../bin/stripped/core [run_dir]/image.elf - } - exec rm -f $boot_modules_s -} - -proc run_genode_until {{wait_for_re forever} {timeout_value 0}} { - - set image [pwd]/[run_dir]/image.elf - set target [get_cmd_arg --target "qemu"] - - if { $target == "jtag" } { - - # try to run on device via jtag - spawn make -C [genode_dir]/base-mb/platform/[hardware] upload IMAGE=$image VERBOSE= - interact - - } elseif { $target == "qemu" } { - - # run on qemu - global output - set timeout $timeout_value - set pid [spawn [qemu] -kernel $image -serial stdio] - if {$wait_for_re == "forever"} { interact $pid } - expect { - -re $wait_for_re { } - timeout { puts stderr "Error: Test execution timed out"; exit -2 } - } - set output $expect_out(buffer) - } else { - - puts stderr "Error: Target '${target}' is not supported" - puts stderr " Supported targets are: 'jtag' and 'qemu'"; exit -3 - - } -} - - -proc install_config {config} { - global boot_modules - append boot_modules "config" " " - - set fh [open "bin/config" "WRONLY CREAT TRUNC"] - puts $fh $config - close $fh - exec touch [genode_dir]/base-mb/src/core/boot_modules.s -} - - -proc qemu { } { - global _qemu - set _qemu [get_cmd_arg --qemu "qemu-system-microblaze"] - return $_qemu -} - -proc hardware { } { - global _hardware - - # - # Test on all supported platforms - # - - if { [have_spec {mb_s3a_starter_kit}] } { - set _hardware mb_s3a_starter_kit - return $_hardware - } - if { [have_spec {mb_ml507}] } { - set _hardware mb_ml507 - return $_hardware - } -} diff --git a/base-mb/run/hello.run b/base-mb/run/hello.run deleted file mode 100755 index eaec3f3fe..000000000 --- a/base-mb/run/hello.run +++ /dev/null @@ -1,15 +0,0 @@ -build "core init test/hello" - -install_config { - - - - - - - -} - -create_boot_directory -build_boot_image "core init hello" -run_genode_until "child exited with exit value 0" 20 diff --git a/base-mb/run/nested_init.run b/base-mb/run/nested_init.run deleted file mode 100755 index fef6631f3..000000000 --- a/base-mb/run/nested_init.run +++ /dev/null @@ -1,34 +0,0 @@ -build "init core" - -install_config { - - - - - - - - - - - - - - - - - - - - - - - - - - -} - -create_boot_directory -build_boot_image "init core" -run_genode_until forever diff --git a/base-mb/src/base/console/microblaze_console.cc b/base-mb/src/base/console/microblaze_console.cc deleted file mode 100755 index 649d4ecb0..000000000 --- a/base-mb/src/base/console/microblaze_console.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* - * \brief Console backend for Microblaze - * \author Martin Stein - * \date 2011-02-22 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include - -namespace Genode { - - class Microblaze_console : public Console - { - private: - - Xilinx::Xps_uartl _uart; - - protected: - - virtual void _out_char(char c) - { - _uart.send(c); - } - - public: - - Microblaze_console() : _uart(0x84000000) {} - }; -} - - -using namespace Genode; - - -static Microblaze_console µblaze_console() -{ - static Microblaze_console static_microblaze_console; - return static_microblaze_console; -} - - -void Genode::printf(const char *format, ...) -{ - va_list list; - va_start(list, format); - - microblaze_console().vprintf(format, list); - - va_end(list); -} - - -void Genode::vprintf(const char *format, va_list list) -{ - microblaze_console().vprintf(format, list); -} diff --git a/base-mb/src/base/cxx/atexit.cc b/base-mb/src/base/cxx/atexit.cc deleted file mode 100755 index d1d583e40..000000000 --- a/base-mb/src/base/cxx/atexit.cc +++ /dev/null @@ -1,19 +0,0 @@ -/* - * \brief C++ support for Microblaze cross compiler - * \author Norman Feske - * \date 2010-07-21 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* - * The mb-gcc generates calls to 'atexit' instead of '__cxa_atexit' as - * usual. - */ -extern "C" __attribute__((weak)) -void *atexit() { return 0; } diff --git a/base-mb/src/base/ipc/ipc.cc b/base-mb/src/base/ipc/ipc.cc deleted file mode 100755 index f7c92b603..000000000 --- a/base-mb/src/base/ipc/ipc.cc +++ /dev/null @@ -1,201 +0,0 @@ -/* - * \brief Implementation of the IPC API - * \author Norman Feske - * \date 2010-09-06 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include - -/* kernel includes */ -#include - -using namespace Genode; - - -/*************** - ** Utilities ** - ***************/ - -template -static unsigned size_to_size_in(unsigned s) -{ - return (unsigned)(s+sizeof(T)-1)/sizeof(T); -} - - -/** - * Copy message registers from UTCB to destination message buffer - */ -static void copy_utcb_to_msgbuf(unsigned message_size, - Msgbuf_base *receive_buffer) -{ - if (!message_size) return; - - if (message_size > receive_buffer->size()) - message_size = receive_buffer->size(); - - Cpu::word_t *message_buffer = (Cpu::word_t*)receive_buffer->buf; - Native_utcb *utcb = Thread_base::myself()->utcb(); - unsigned msg_size_in_words = size_to_size_in(message_size); - - for (unsigned i=0; i < msg_size_in_words; i++) - message_buffer[i] = utcb->word[i]; -} - - -/** - * Copy message payload to UTCB message registers - */ -static void copy_msgbuf_to_utcb(Msgbuf_base *send_buffer, - unsigned message_size, - unsigned local_name) -{ - typedef Kernel::Utcb Utcb; - - if (!message_size) return; - - Native_utcb *utcb = Thread_base::myself()->utcb(); - unsigned header_size = sizeof(local_name); - - if (message_size + header_size > utcb->size()) { - if (header_size > utcb->size()) - return; - - message_size = utcb->size()-header_size; - } - - Cpu::word_t *message_buffer = (Cpu::word_t*)send_buffer->buf; - unsigned msg_size_in_words = size_to_size_in(message_size); - unsigned h_size_in_words = size_to_size_in(header_size); - - utcb->word[0] = local_name; - - for (unsigned i = h_size_in_words; i < msg_size_in_words; i++) { - utcb->word[i] = message_buffer[i]; - } -} - - -/***************** - ** Ipc_ostream ** - *****************/ - -Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg) -: - Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()), - _snd_msg(snd_msg), - _dst(dst) -{ - _write_offset = sizeof(umword_t); -} - - -/***************** - ** Ipc_istream ** - *****************/ - -void Ipc_istream::_wait() { Kernel::thread_sleep(); } - - -Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg) -: - Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()), - Native_capability(Genode::my_thread_id(), 0), - _rcv_msg(rcv_msg), - _rcv_cs(-1) -{ - _read_offset = sizeof(umword_t); -} - - -Ipc_istream::~Ipc_istream() { } - - -/**************** - ** Ipc_client ** - ****************/ - - -void Ipc_client::_call() -{ - unsigned request_size = _write_offset; - copy_msgbuf_to_utcb(_snd_msg, request_size, Ipc_ostream::_dst.local_name()); - - unsigned reply_size = Kernel::ipc_request(Ipc_ostream::_dst.dst(), request_size); - - copy_utcb_to_msgbuf(reply_size, _rcv_msg); - - /* reset marshalling / unmarshalling pointers */ - _write_offset = _read_offset=sizeof(umword_t); -} - - -Ipc_client::Ipc_client(Native_capability const &srv, - Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg) -: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) -{ } - - -/**************** - ** Ipc_server ** - ****************/ - -void Ipc_server::_prepare_next_reply_wait() -{ - /* now we have a request to reply */ - _reply_needed = true; - - enum { RETURN_VALUE_SIZE = sizeof(umword_t) }; - _write_offset = sizeof(umword_t)+RETURN_VALUE_SIZE; - - _read_offset = sizeof(umword_t); -} - - -void Ipc_server::_wait() -{ - /* wait for new request */ - Cpu::size_t reply_size = 0; - Cpu::size_t request_size = Kernel::ipc_serve(reply_size); - - - copy_utcb_to_msgbuf(request_size, _rcv_msg); - _prepare_next_reply_wait(); -} - - -void Ipc_server::_reply() { _prepare_next_reply_wait(); } - - -void Ipc_server::_reply_wait() -{ - unsigned reply_size = 0; - if (_reply_needed) { - reply_size = _write_offset; - copy_msgbuf_to_utcb(_snd_msg, reply_size, Ipc_ostream::_dst.local_name()); - } - - unsigned request_size = Kernel::ipc_serve(reply_size); - - copy_utcb_to_msgbuf(request_size, _rcv_msg); - _prepare_next_reply_wait(); -} - - -Ipc_server::Ipc_server(Msgbuf_base *snd_msg, - Msgbuf_base *rcv_msg) -: - Ipc_istream(rcv_msg), - Ipc_ostream(Native_capability(my_thread_id(), 0), snd_msg), - _reply_needed(false) -{ } - diff --git a/base-mb/src/base/ipc/pager.cc b/base-mb/src/base/ipc/pager.cc deleted file mode 100755 index 9d08b0cea..000000000 --- a/base-mb/src/base/ipc/pager.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* - * \brief Pager support for Microblaze Kernel - * \author Norman Feske - * \author Martin Stein - * \date 2010-09-23 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include - -/* kernel includes */ -#include - -using namespace Genode; - - -void Ipc_pager::wait_for_fault() -{ - typedef Kernel::Paging::Request Request; - - while (1) { - - /* wait for fault message */ - unsigned const msg_length=Kernel::ipc_serve(0); - - /* check message format */ - if (msg_length==sizeof(Request)){ - - _request=*((Request*)Thread_base::myself()->utcb()); - -// PERR( -// "Recieved pagefault, va=%p, tid=%i, pid=%i", -// _request.virtual_page.address(), -// _request.source.tid, -// _request.virtual_page.protection_id()); - - return; - } - } -} - - -void Ipc_pager::reply_and_wait_for_fault() -{ - /* load mapping to tlb (not to be considered permanent) */ - if (_mapping.valid()) - Kernel::tlb_load( - _mapping.physical_page.address(), - _mapping.virtual_page.address(), - _request.virtual_page.protection_id(), - _mapping.physical_page.size(), - _mapping.physical_page.permissions()); - -// PERR( -// "Resoluted, pa=%p, va=%p, tid=%i, pid=%i", -// _mapping.physical_page.address(), -// _mapping.virtual_page.address(), -// _request.source.tid, -// _request.virtual_page.protection_id()); - - /* wake up faulter if mapping succeeded */ acknowledge_wakeup(); - - /* wait for next page fault */ wait_for_fault(); -} - - diff --git a/base-mb/src/base/lock/lock_helper.h b/base-mb/src/base/lock/lock_helper.h deleted file mode 100755 index 9493e3186..000000000 --- a/base-mb/src/base/lock/lock_helper.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * \brief Dummy helper functions for the Lock implementation - * \author Norman Feske - * \date 2009-10-02 - * - * For documentation about the interface, please revisit the 'base-pistachio' - * implementation. - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include - -/* kernel includes */ -#include -#include - - -static inline void thread_yield() { Kernel::thread_yield(); } - - -static bool thread_check_stopped_and_restart(Genode::Native_thread_id tid) -{ - Kernel::thread_wake(tid); - return true; -} - - -static inline Genode::Native_thread_id thread_get_my_native_id() -{ - return Genode::my_thread_id(); -} - - -static inline Genode::Native_thread_id thread_invalid_id() { return -1; } - - -static inline bool thread_id_valid(Genode::Native_thread_id tid) -{ - return tid != thread_invalid_id(); -} - - -static inline void thread_switch_to(Genode::Native_thread_id tid) -{ - thread_yield(); -} - - -static inline void thread_stop_myself() { Kernel::thread_sleep(); } diff --git a/base-mb/src/base/pager/pager.cc b/base-mb/src/base/pager/pager.cc deleted file mode 100644 index 2bd210040..000000000 --- a/base-mb/src/base/pager/pager.cc +++ /dev/null @@ -1,122 +0,0 @@ -/* - * \brief Dummy pager framework - * \author Norman Feske - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - - -using namespace Genode; - - -/********************** - ** Pager activation ** - **********************/ - -void Pager_activation_base::entry() -{ - Ipc_pager pager; - _cap = pager; - _cap_valid.unlock(); - -// PINF("Ready for page faults"); - Pager_object * obj; - bool reply = false; - - while (1) { - - if (reply) - pager.reply_and_wait_for_fault(); - else - pager.wait_for_fault(); - - /* lookup referenced object */ - Object_pool::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); - obj = _obj; - reply = false; - - /* handle request */ - if (obj) { -// PINF("Pagefault request from a common pager object"); - - if (pager.resolved()) { - reply = true; - continue; - } - - reply = !obj->pager(pager); - if (!reply) { - /* something strange occured - leave thread in pagefault */ -// PINF("Leave unresolved, wait for next page fault"); - } else { -// PINF("Resolved, reply and wait for next page fault"); - } - continue; - } - else { -// PINF("Pagefault request from one of cores region manager sessions"); - - /* - * We got a request from one of cores region-manager sessions - * to answer the pending page fault of a resolved region-manager - * client. Hence, we have to send the page-fault reply to the - * specified thread and answer the call of the region-manager - * session. - * - * When called from a region-manager session, we receive the - * core-local address of the targeted pager object via the - * first message word, which corresponds to the 'fault_ip' - * argument of normal page-fault messages. - */ - obj = reinterpret_cast(pager.fault_ip()); - - /* send reply to the calling region-manager session */ - pager.acknowledge_wakeup(); - - /* answer page fault of resolved pager object */ - pager.set_reply_dst(obj->cap()); - pager.acknowledge_wakeup(); - -// PINF("Wait for next page fault"); - } - } -} - - -/********************** - ** Pager entrypoint ** - **********************/ - -Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a) -: _activation(a) -{ - _activation->ep(this); -} - - -void Pager_entrypoint::dissolve(Pager_object *obj) { remove_locked(obj); } - - -Pager_capability Pager_entrypoint::manage(Pager_object *obj) -{ - /* return invalid capability if no activation is present */ - if (!_activation) return Pager_capability(); - - Native_capability cap = Native_capability(_activation->cap().dst(), obj->badge()); - - /* add server object to object pool */ - obj->cap(cap); - insert(obj); - - /* return capability that uses the object id as badge */ - return reinterpret_cap_cast(cap); -} diff --git a/base-mb/src/base/thread/thread.cc b/base-mb/src/base/thread/thread.cc deleted file mode 100644 index 4ac8af919..000000000 --- a/base-mb/src/base/thread/thread.cc +++ /dev/null @@ -1,215 +0,0 @@ -/* - * \brief Implementation of the Thread API - * \author Norman Feske - * \date 2010-01-11 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include -#include -#include -#include - -using namespace Genode; - - -/** - * Return the managed dataspace holding the thread context area - * - * This function is provided by the process environment. - */ -namespace Genode { - Rm_session *env_context_area_rm_session(); - Ram_session *env_context_area_ram_session(); -} - -static addr_t context_virtual_base_mask() { - return ~(Native_config::context_virtual_size() - 1); } - -/****************************** - ** Thread-context allocator ** - ******************************/ - -Thread_base::Context *Thread_base::Context_allocator::base_to_context(addr_t base) -{ - addr_t result = base + Native_config::context_virtual_size() - sizeof(Context); - return reinterpret_cast(result); -} - - -addr_t Thread_base::Context_allocator::addr_to_base(void *addr) -{ - return ((addr_t)addr) & context_virtual_base_mask(); -} - - -bool Thread_base::Context_allocator::_is_in_use(addr_t base) -{ - List_element *le = _threads.first(); - for (; le; le = le->next()) - if (base_to_context(base) == le->object()->_context) - return true; - - return false; -} - - -Thread_base::Context *Thread_base::Context_allocator::alloc(Thread_base *thread_base) -{ - Lock::Guard _lock_guard(_threads_lock); - - /* - * Find slot in context area for the new context - */ - addr_t base = Native_config::context_area_virtual_base(); - for (; _is_in_use(base); base += Native_config::context_virtual_size()) { - - /* check upper bound of context area */ - if (base >= Native_config::context_area_virtual_base() + Native_config::context_area_virtual_size()) - return 0; - } - - _threads.insert(&thread_base->_list_element); - - return base_to_context(base); -} - - -void Thread_base::Context_allocator::free(Thread_base *thread_base) -{ - Lock::Guard _lock_guard(_threads_lock); - - _threads.remove(&thread_base->_list_element); -} - - -/***************** - ** Thread base ** - *****************/ - -Thread_base::Context_allocator *Thread_base::_context_allocator() -{ - static Context_allocator context_allocator_inst; - return &context_allocator_inst; -} - - -Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) -{ - /* - * Synchronize context list when creating new threads from multiple threads - * - * XXX: remove interim fix - */ - static Lock alloc_lock; - Lock::Guard _lock_guard(alloc_lock); - - /* allocate thread context */ - Context *context = _context_allocator()->alloc(this); - if (!context) throw Context_alloc_failed(); - - /* determine size of dataspace to allocate for context members and stack */ - enum { PAGE_SIZE_LOG2 = 12 }; - size_t ds_size = align_addr(stack_size, PAGE_SIZE_LOG2); - - if (stack_size >= Native_config::context_virtual_size() - sizeof(Native_utcb) - (1 << PAGE_SIZE_LOG2)) - throw Stack_too_large(); - - /* - * Calculate base address of the stack - * - * The stack is always located at the top of the context. - */ - addr_t ds_addr = Context_allocator::addr_to_base(context) + Native_config::context_virtual_size() - - ds_size; - - /* add padding for UTCB if defined for the platform */ - if (sizeof(Native_utcb) >= (1 << PAGE_SIZE_LOG2)) - ds_addr -= sizeof(Native_utcb); - - /* allocate and attach backing store for the stack */ - Ram_dataspace_capability ds_cap; - try { - ds_cap = env_context_area_ram_session()->alloc(ds_size); - addr_t attach_addr = ds_addr - Native_config::context_area_virtual_base(); - env_context_area_rm_session()->attach_at(ds_cap, attach_addr, ds_size); - - } catch (Ram_session::Alloc_failed) { - throw Stack_alloc_failed(); - } - - _init_context(context); - - /* - * Now the thread context is backed by memory, so it is safe to access its - * members. - */ - - context->thread_base = this; - context->stack_base = ds_addr; - context->ds_cap = ds_cap; - return context; -} - - -void Thread_base::_free_context() -{ - addr_t ds_addr = _context->stack_base - Native_config::context_area_virtual_base(); - Ram_dataspace_capability ds_cap = _context->ds_cap; - Genode::env_context_area_rm_session()->detach((void *)ds_addr); - Genode::env_context_area_ram_session()->free(ds_cap); - _context_allocator()->free(this); -} - - -void Thread_base::name(char *dst, size_t dst_len) -{ - snprintf(dst, min(dst_len, (size_t)Context::NAME_LEN), _context->name); -} - - -Thread_base *Thread_base::myself() -{ - addr_t sp = Xilinx::Microblaze::stack_pointer(); - - /* - * If the stack pointer is outside the thread-context area, we assume that - * we are the main thread because this condition can never met by any other - * thread. - */ - if (sp < Native_config::context_area_virtual_base() - || sp >= Native_config::context_area_virtual_base() + Native_config::context_area_virtual_size()) - return 0; - - addr_t base = Context_allocator::addr_to_base((void*)sp); - return Context_allocator::base_to_context(base)->thread_base; -} - - -Thread_base::Thread_base(const char *name, size_t stack_size) -: _list_element(this), _context(_alloc_context(stack_size)) -{ - strncpy(_context->name, name, sizeof(_context->name)); - _init_platform_thread(); -} - - -Thread_base::~Thread_base() -{ - _deinit_platform_thread(); - _free_context(); -} - -void Thread_base::join() -{ - _join_lock.lock(); -} - diff --git a/base-mb/src/base/thread/thread_bootstrap.cc b/base-mb/src/base/thread/thread_bootstrap.cc deleted file mode 100755 index 7f52a3515..000000000 --- a/base-mb/src/base/thread/thread_bootstrap.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Default thread bootstrap code - * \author Norman Feske - * \date 2009-04-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include - -using namespace Genode; - -void Thread_base::_thread_bootstrap() -{ - myself()->_tid=*((Native_thread_id*)myself()->utcb()); -} diff --git a/base-mb/src/base/thread/thread_context.cc b/base-mb/src/base/thread/thread_context.cc deleted file mode 100755 index 0699c2b1f..000000000 --- a/base-mb/src/base/thread/thread_context.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* - * \brief Thread-context specific part of the thread library - * \author Norman Feske - * \date 2010-01-19 - * - * This part of the thread library is required by the IPC framework - * also if no threads are used. - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -/* kernel includes */ -#include -#include -#include - -using namespace Genode; - - -extern Genode::Native_utcb* _main_utcb_addr; -Genode::Native_thread_id _main_thread_id; - - -bool is_this_main_thread() { return Thread_base::myself() == 0; } - - -Native_utcb* Thread_base::utcb() -{ - if (is_this_main_thread()) - return _main_utcb_addr; - - return &_context->utcb; -} - - -Native_thread_id Genode::my_thread_id() -{ - if (!is_this_main_thread()) - return Thread_base::myself()->tid(); - - unsigned pid = (unsigned)Xilinx::Microblaze::protection_id(); - - if (pid == Roottask::PROTECTION_ID) - return Roottask::MAIN_THREAD_ID; - - return _main_thread_id; -} - - diff --git a/base-mb/src/base/thread/thread_start.cc b/base-mb/src/base/thread/thread_start.cc deleted file mode 100644 index 34059c26d..000000000 --- a/base-mb/src/base/thread/thread_start.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* - * \brief Implementation of the Thread API - * \author Norman Feske - * \date 2010-01-19 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include - -using namespace Genode; - - -/** - * Entry point entered by new threads - */ -void Thread_base::_thread_start() -{ - Thread_base::myself()->_thread_bootstrap(); - Thread_base::myself()->entry(); - Thread_base::myself()->_join_lock.unlock(); - Genode::sleep_forever(); -} - - -/***************** - ** Thread base ** - *****************/ - -void Thread_base::_init_context(Context* c) { } - -void Thread_base::_init_platform_thread() { } - - -void Thread_base::_deinit_platform_thread() -{ - env()->cpu_session()->kill_thread(_thread_cap); - env()->rm_session()->remove_client(_pager_cap); -} - - -void Thread_base::start() -{ - /* create thread at core */ - char buf[48]; - name(buf, sizeof(buf)); - _thread_cap = env()->cpu_session()->create_thread(buf); - - /* assign thread to protection domain */ - env()->pd_session()->bind_thread(_thread_cap); - - /* create new pager object and assign it to the new thread */ - _pager_cap = env()->rm_session()->add_client(_thread_cap); - env()->cpu_session()->set_pager(_thread_cap, _pager_cap); - - /* register initial IP and SP at core */ - addr_t thread_sp = (addr_t)&_context->stack[-4]; - thread_sp &= ~0xf; /* align initial stack to 16 byte boundary */ - env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, thread_sp); -} - - -void Thread_base::cancel_blocking() -{ - env()->cpu_session()->cancel_blocking(_thread_cap); -} diff --git a/base-mb/src/core/context_area.cc b/base-mb/src/core/context_area.cc deleted file mode 100644 index 60544f60c..000000000 --- a/base-mb/src/core/context_area.cc +++ /dev/null @@ -1,148 +0,0 @@ -/* - * \brief Support code for the thread API - * \author Norman Feske - * \date 2010-01-13 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include - -/* local includes */ -#include -#include -#include - -using namespace Genode; - - -/** - * Pointer to dataspace used to hold core contexts - */ -enum { MAX_CORE_CONTEXTS = 256 }; -static Dataspace_component *context_ds[MAX_CORE_CONTEXTS]; - - -/** - * Region-manager session for allocating thread contexts - * - * This class corresponds to the managed dataspace that is normally - * used for organizing thread contexts with the thread context area. - * It "emulates" the sub address space by adjusting the local address - * argument to 'attach' with the offset of the thread context area. - */ -class Context_area_rm_session : public Rm_session -{ - public: - - /** - * Attach backing store to thread-context area - */ - Local_addr attach(Dataspace_capability ds_cap, - size_t size, off_t offset, - bool use_local_addr, Local_addr local_addr, bool) - { - Dataspace_component *ds = context_ds[ds_cap.local_name()]; - if (!ds) { - PERR("dataspace for core context does not exist"); - return 0; - } - - if (!map_local(ds->phys_addr(), - (addr_t)local_addr + Native_config::context_area_virtual_base(), - ds->size() >> get_page_size_log2())) - return 0; - - return local_addr; - } - - void detach(Local_addr) { } - - Pager_capability add_client(Thread_capability) { - return Pager_capability(); } - - void fault_handler(Signal_context_capability) { } - - State state() { return State(); } - - Dataspace_capability dataspace() { return Dataspace_capability(); } -}; - - -class Context_area_ram_session : public Ram_session -{ - public: - - Ram_dataspace_capability alloc(size_t size, bool) - { - /* find free context */ - unsigned i; - for (i = 0; i < MAX_CORE_CONTEXTS; i++) - if (!context_ds[i]) - break; - - if (i == MAX_CORE_CONTEXTS) { - PERR("maximum number of core contexts (%d) reached", MAX_CORE_CONTEXTS); - return Ram_dataspace_capability(); - } - - /* allocate physical memory */ - size = round_page(size); - void *phys_base; - if (platform_specific()->ram_alloc()->alloc_aligned(size, &phys_base, - get_page_size_log2()).is_error()) { - PERR("could not allocate backing store for new context"); - return Ram_dataspace_capability(); - } - - context_ds[i] = new (platform()->core_mem_alloc()) - Dataspace_component(size, 0, (addr_t)phys_base, false, true, 0); - - /* - * We do not manage the dataspace via an entrypoint because it will - * only be used by the 'context_area_rm_session'. Therefore, we - * construct a "capability" by hand using the context ID as local - * name. - */ - Native_capability cap; - return reinterpret_cap_cast(Native_capability(cap.dst(), i)); - } - - void free(Ram_dataspace_capability ds) { PDBG("not yet implemented"); } - - int ref_account(Ram_session_capability ram_session) { return 0; } - - int transfer_quota(Ram_session_capability ram_session, size_t amount) { return 0; } - - size_t quota() { return 0; } - - size_t used() { return 0; } -}; - - -/** - * Return single instance of the context-area RM and RAM session - */ -namespace Genode { - - Rm_session *env_context_area_rm_session() - { - static Context_area_rm_session inst; - return &inst; - } - - Ram_session *env_context_area_ram_session() - { - static Context_area_ram_session inst; - return &inst; - } -} diff --git a/base-mb/src/core/core_rm_session.cc b/base-mb/src/core/core_rm_session.cc deleted file mode 100644 index 4ee2972d2..000000000 --- a/base-mb/src/core/core_rm_session.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * \brief Core-local RM session - * \author MArtin Stein - * \date 2010-09-09 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -/* core includes */ -#include -#include -#include - -using namespace Genode; - - -Rm_session::Local_addr -Core_rm_session::attach(Dataspace_capability ds_cap, size_t size, - off_t offset, bool use_local_addr, - Rm_session::Local_addr local_addr, - bool executable) -{ - Object_pool::Guard ds(_ds_ep->lookup_and_lock(ds_cap)); - if (!ds) - throw Invalid_dataspace(); - - /* roottask is mapped identically */ - return ds->phys_addr(); -} diff --git a/base-mb/src/core/cpu_session_support.cc b/base-mb/src/core/cpu_session_support.cc deleted file mode 100644 index adcad731c..000000000 --- a/base-mb/src/core/cpu_session_support.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* - * \brief Platform specific parts of CPU session - * \author Martin Stein - * \date 2012-11-27 - */ - -/* - * Copyright (C) 2012-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -/* core includes */ -#include - -using namespace Genode; - - -Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability) { - PDBG("Not implemented"); - return Ram_dataspace_capability(); -}; - diff --git a/base-mb/src/core/include/core_rm_session.h b/base-mb/src/core/include/core_rm_session.h deleted file mode 100644 index 8f4cc0281..000000000 --- a/base-mb/src/core/include/core_rm_session.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * \brief Core-local region manager session - * \author Norman Feske - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _CORE__INCLUDE__CORE_RM_SESSION_H_ -#define _CORE__INCLUDE__CORE_RM_SESSION_H_ - -/* Genode includes */ -#include - -/* core includes */ -#include - -namespace Genode { - - class Core_rm_session : public Rm_session - { - private: - - Rpc_entrypoint *_ds_ep; - - public: - - Core_rm_session(Rpc_entrypoint *ds_ep) : _ds_ep(ds_ep) { } - - Local_addr attach(Dataspace_capability ds_cap, size_t size=0, - off_t offset=0, bool use_local_addr = false, - Local_addr local_addr = 0, - bool executable = false); - - void detach(Local_addr) { } - - Pager_capability add_client(Thread_capability thread) { - return Pager_capability(); } - - void fault_handler(Signal_context_capability handler) { } - - State state() { return State(); } - - Dataspace_capability dataspace() { return Dataspace_capability(); } - }; -} - -#endif /* _CORE__INCLUDE__CORE_RM_SESSION_H_ */ diff --git a/base-mb/src/core/include/cpu/prints.h b/base-mb/src/core/include/cpu/prints.h deleted file mode 100644 index f0ddac03e..000000000 --- a/base-mb/src/core/include/cpu/prints.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * \brief Saver print methods than the luxury dynamic-number/type-of-arguments one's - * \author Martin Stein - * \date 2010-09-16 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__XMB__PRINTS_H_ -#define _INCLUDE__XMB__PRINTS_H_ - - -#include - - -enum { UART_OUT_REGISTER=0x84000004 }; - - -inline static void _prints_chr1(volatile char chr1) -{ - unsigned volatile* uart = (volatile unsigned*)UART_OUT_REGISTER; - *uart = chr1; -} - - -inline static void _prints_hex2(volatile char hex2) -{ - volatile char hex1 = ((hex2 >> 4) & 0xf); - if (hex1 > 9) hex1 += 39; - hex1 += 48; - _prints_chr1((volatile char)hex1); - - hex1 = hex2 & 0xf; - if (hex1 > 9) hex1 += 39; - hex1 += 48; - _prints_chr1((volatile char)hex1); -} - - -inline static void _prints_hex8(unsigned volatile hex8) -{ - _prints_hex2((volatile char)(hex8 >> 24)); - _prints_hex2((volatile char)(hex8 >> 16)); - _prints_hex2((volatile char)(hex8 >> 8)); - _prints_hex2((volatile char)(hex8 >> 0)); -} - - -inline static void _prints_hex8l(unsigned volatile hex8) -{ - _prints_hex8(hex8); - _prints_chr1('\n'); -} - - -inline static void _prints_str0(const char* volatile str0) -{ - while (*str0) _prints_chr1(*str0++); -} - - -#endif /* _INCLUDE__XMB__PRINTS_H_ */ diff --git a/base-mb/src/core/include/irq_session_component.h b/base-mb/src/core/include/irq_session_component.h deleted file mode 100644 index 1a4a54842..000000000 --- a/base-mb/src/core/include/irq_session_component.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * \brief IRQ session interface for the Microblaze Kernel - * \author Norman Feske - * \author Martin Stein - * \date 2010-01-30 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ -#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ - -#include -#include -#include - -#include - -namespace Genode { - - class Irq_session_component : public Rpc_object, - public List::Element - { - private: - - enum { STACK_SIZE = 4096 }; - - unsigned _irq_number; - Range_allocator *_irq_alloc; - Rpc_entrypoint _entrypoint; - Irq_session_capability _cap; - bool _attached; - - public: - - /** - * Constructor - * - * \param cap_session capability session to use - * \param irq_alloc platform-dependent IRQ allocator - * \param args session construction arguments - */ - Irq_session_component(Cap_session *cap_session, - Range_allocator *irq_alloc, - const char *args); - - /** - * Destructor - */ - ~Irq_session_component(); - - /** - * Return capability to this session - * - * If an initialization error occurs, returned capability is invalid. - */ - Irq_session_capability cap() const { return _cap; } - - - /*************************** - ** Irq session interface ** - ***************************/ - - void wait_for_irq(); - }; -} - -#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */ diff --git a/base-mb/src/core/include/kernel/print.h b/base-mb/src/core/include/kernel/print.h deleted file mode 100644 index 28795f46f..000000000 --- a/base-mb/src/core/include/kernel/print.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * \brief Kernels syscall frontend - * \author Martin stein - * \date 2010.07.02 - */ - -#ifndef _INCLUDE__KERNEL__PRINT_H_ -#define _INCLUDE__KERNEL__PRINT_H_ - -#include - -namespace Kernel { - - class Serial_port - { - /** - * Print constant integer < 2^4 as hexadecimal value - * to serial port via syscalls - */ - inline void _print_hex_4(unsigned char x); - - public: - - /** - * Print constant zero-terminated string via syscalls to serial port - */ - inline Serial_port &operator << (char const *s); - - /** - * Print constant integer < 2^32 as hexadecimal value - * to serial port via syscalls (no leading zeros) - */ - inline Serial_port &operator << (unsigned int const &x); - }; - - /** - * Give static 'Serial_port' reference as target for stream operators - */ - inline Serial_port& serial_port(); -} - - -Kernel::Serial_port& Kernel::serial_port() -{ - static Serial_port _sp; - return _sp; -} - - -void Kernel::Serial_port::_print_hex_4(unsigned char x) -{ - x &= 0x0f; - if (x > 9) - x += 39; - - x += 48; - - Kernel::print_char(x); -} - - -Kernel::Serial_port& Kernel::Serial_port::operator << (char const *s) -{ - while (*s) print_char(*s++); - return *this; -} - - -Kernel::Serial_port& Kernel::Serial_port::operator << (unsigned int const &x) -{ - enum{ - BYTE_WIDTH = 8, - CW = sizeof(unsigned char)*BYTE_WIDTH, - IW = sizeof(unsigned int)*BYTE_WIDTH - }; - - bool leading = true; - for (int i = IW - CW; i >= 0; i = i - CW){ - unsigned char c =(char)((x >> i) & 0xff); - if (leading) { - if (c == 0x00) { - if (i == 0) - _print_hex_4(c); - continue; - } - leading = false; - if (c < 0x10) { - _print_hex_4(c); - continue; - } - } - _print_hex_4(c >> 4); - _print_hex_4(c); - } - return *this; -} - -#endif /* _INCLUDE__KERNEL__PRINT_H_ */ diff --git a/base-mb/src/core/include/map_local.h b/base-mb/src/core/include/map_local.h deleted file mode 100755 index 63345f9d4..000000000 --- a/base-mb/src/core/include/map_local.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * \brief Core-local mapping - * \author Norman Feske - * \date 2010-02-15 - * - * These functions are normally doing nothing because core's using 1-to-1 paging at kernel - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SRC__CORE__INCLUDE__MAP_LOCAL_H_ -#define _SRC__CORE__INCLUDE__MAP_LOCAL_H_ - -/* Genode includes */ -#include - -/* core includes */ -#include - - -namespace Genode { - - /** - * Map physical pages to core-local virtual address range - * - * Always true because roottask pager handles all core page faults - */ - inline bool map_local(addr_t from_phys, addr_t to_virt, size_t num_pages) - { - return true; - } - - /** - * Unmap virtual pages from core-local virtual address range - * - * Does nothing because roottask pager handles all core page faults - */ - inline bool unmap_local(addr_t virt_addr, size_t num_pages) - { - return true; - } -} - -#endif /* _SRC__CORE__INCLUDE__MAP_LOCAL_H_ */ diff --git a/base-mb/src/core/include/platform.h b/base-mb/src/core/include/platform.h deleted file mode 100755 index c8e57394e..000000000 --- a/base-mb/src/core/include/platform.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * \brief Platform interface - * \author Martin Stein - * \date 2010-09-08 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SRC__CORE__INCLUDE__PLATFORM_H_ -#define _SRC__CORE__INCLUDE__PLATFORM_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace Roottask -{ - enum { - PAGER_TID = User::MIN_THREAD_ID, - - CONTEXT_PAGE_SIZE_LOG2 = Kernel::Utcb::ALIGNMENT_LOG2, - CONTEXT_PAGE_SIZE = 1< Phys_allocator; - - /* - * Core is mapped 1-to-1 physical-to-virtual except for the thread - * context area. mapping out of context area. So a single memory - * allocator suffices for both, assigning physical RAM to - * dataspaces and allocating core-local memory. - */ - Phys_allocator _core_mem_alloc; /* core-accessible memory */ - Phys_allocator _io_mem_alloc; /* MMIO allocator */ - Phys_allocator _io_port_alloc; /* I/O port allocator */ - Phys_allocator _irq_alloc; /* IRQ allocator */ - Rom_fs _rom_fs; /* ROM file system */ - - /** - * Virtual address range usable by non-core processes - */ - addr_t _vm_base; - size_t _vm_size; - - void _optimize_init_img_rom(long int & base, size_t const & size); - - public: - - virtual ~Platform() {} - - /** - * Constructor - */ - Platform(); - - - /******************************** - ** Generic platform interface ** - ********************************/ - - inline Range_allocator *ram_alloc() { return &_core_mem_alloc; } - inline Range_allocator *io_mem_alloc() { return &_io_mem_alloc; } - inline Range_allocator *io_port_alloc() { return &_io_port_alloc; } - inline Range_allocator *irq_alloc() { return &_irq_alloc; } - inline Range_allocator *region_alloc() { return 0; } - - /** - * We need a 'Range_allocator' instead of 'Allocator' as in - * 'Platform_generic' to allocate aligned space for e.g. UTCB's - */ - inline Range_allocator *core_mem_alloc() { return &_core_mem_alloc; } - - inline addr_t vm_start() const { return _vm_base; } - inline size_t vm_size() const { return _vm_size; } - - inline Rom_fs *rom_fs() { return &_rom_fs; } - - inline void wait_for_exit() { sleep_forever(); } - - }; -} - -#endif /* _SRC__CORE__INCLUDE__PLATFORM_H_ */ diff --git a/base-mb/src/core/include/platform_pd.h b/base-mb/src/core/include/platform_pd.h deleted file mode 100755 index 9097ee511..000000000 --- a/base-mb/src/core/include/platform_pd.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * \brief Protection-domain facility - * \author Martin Stein - * \date 2010-09-13 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SRC__CORE__INCLUDE__PLATFORM_PD_H_ -#define _SRC__CORE__INCLUDE__PLATFORM_PD_H_ - -/* core includes */ -#include -#include -#include - -namespace Genode { - - class Platform_pd; - - typedef Id_allocator Pid_allocator; - - Pid_allocator *pid_allocator(); - - - class Platform_thread; - class Platform_pd - { - public: - - typedef unsigned Context_id; - typedef Thread_base::Context Context; - - private: - - addr_t context_area_base() { - return Native_config::context_area_virtual_base(); - } - addr_t context_area_size() { - return Native_config::context_area_virtual_size(); - } - addr_t context_area_top() { - return context_area_base() + context_area_size(); - } - addr_t context_size() { - return Native_config::context_virtual_size(); - } - addr_t context_base_mask() { - return ~(Native_config::context_virtual_size() - 1); - } - addr_t context_offset_mask() { - return ~context_base_mask(); - } - - enum { - CONTEXT_SIZE = Native_config::CONTEXT_VIRTUAL_SIZE, - CONTEXT_AREA_SIZE = Native_config::CONTEXT_AREA_VIRTUAL_SIZE, - MAX_CONTEXT_ID = CONTEXT_AREA_SIZE / CONTEXT_SIZE - 1 - }; - - Native_process_id _pid; - - Native_thread_id owner_tid_by_context_id[MAX_CONTEXT_ID + 1]; - - void _free_context(Native_thread_id const & t) - { - for (Context_id cid = 0; cid <= MAX_CONTEXT_ID; cid++) { - if (owner_tid_by_context_id[cid] == t) { - owner_tid_by_context_id[cid] = 0; - } - } - } - - - public: - - /** - * Constructors - */ - Platform_pd(signed pid = 0, bool create = true) : _pid(pid) - { - static bool const verbose = false; - - if ((unsigned)User::MAX_THREAD_ID>(unsigned)MAX_CONTEXT_ID) { - PERR("More threads allowed than context areas available"); - return; - } - if (!_pid) - _pid=pid_allocator()->allocate(this); - - if (!_pid) { - PERR("Allocating new Process ID failed"); - return; - } - if (verbose) - PDBG("Create protection domain %i", (unsigned int)_pid); - } - - /** - * Destructor - */ - ~Platform_pd() { } - - enum Context_part{ NO_CONTEXT_PART = 0, - MISC_AREA = 1, - UTCB_AREA = 2, - STACK_AREA = 3 }; - - bool cid_if_context_address(addr_t a, Context_id* cid) - { - if (a < context_area_base() || a >= context_area_top()) - return false; - - addr_t context_base = a & context_base_mask(); - *cid = (Context_id)((context_base-context_area_base()) / context_size()); - return true; - } - - Context *context(Context_id i) - { - return (Context*)(context_area_base()+(i+1)*context_size()-sizeof(Context)); - } - - Context *context_by_tid(Native_thread_id tid) - { - for (unsigned cid = 0; cid <= MAX_CONTEXT_ID; cid++) - if (owner_tid_by_context_id[cid] == tid) - return context(cid); - - return 0; - } - - bool metadata_if_context_address(addr_t a, Native_thread_id *context_owner_tid, - Context_part *cp, unsigned *stack_offset) - { - Context_id cid; - if (!cid_if_context_address(a, &cid)) - return false; - - if (cid > MAX_CONTEXT_ID) { - PERR("Context ID %i out of range", (unsigned int)cid); - return false; - } - - *context_owner_tid = owner_tid_by_context_id[cid]; - if (!*context_owner_tid) { - if (_pid == Roottask::PROTECTION_ID) - PERR("Context %p is not in use", (void*)a); - - return false; - } - - addr_t offset = a & context_offset_mask(); - Context *context = (Context *)(context_size() - sizeof(Context)); - - if ((void*)offset >= &context->utcb) { - *cp = UTCB_AREA; - - } else if ((void*)offset < &context->stack) { - *cp = STACK_AREA; - *stack_offset = (((unsigned)&(context->stack)) - (unsigned)offset); - } else { - *cp = MISC_AREA; - } - return true; - } - - bool allocate_context(Native_thread_id tid, Context_id cid) - { - static bool const verbose = false; - - if (cid > MAX_CONTEXT_ID) - return 0; - - if (owner_tid_by_context_id[cid]){ - PERR("Context is already in use"); - return false; - } - owner_tid_by_context_id[cid] = tid; - if (verbose) - PDBG("Thread %i owns Context %i (0x%p) of PD %i", - tid, cid, context(cid), _pid); - return true; - } - - Context *allocate_context(Native_thread_id tid) - { - static bool const verbose = false; - - /* - * First thread is assumed to be the main thread and gets last - * context-area by convention - */ - if (!owner_tid_by_context_id[MAX_CONTEXT_ID]){ - owner_tid_by_context_id[MAX_CONTEXT_ID] = tid; - if (verbose) - PDBG("Thread %i owns Context %i (0x%p) of Protection Domain %i", - tid, MAX_CONTEXT_ID, context(MAX_CONTEXT_ID), _pid); - - return context(MAX_CONTEXT_ID); - } - - for (unsigned i = 0; i <= MAX_CONTEXT_ID - 1; i++) { - if (!owner_tid_by_context_id[i]) { - owner_tid_by_context_id[i] = tid; - if (verbose) - PDBG("Thread %i owns Context %i (0x%p) of Protection Domain %i", - tid, MAX_CONTEXT_ID, context(MAX_CONTEXT_ID), _pid); - return context(i); - } - } - return 0; - } - - /** - * Bind thread to protection domain - * - * \return 0 on success - */ - inline int bind_thread(Platform_thread* pt) - { - Context *context = allocate_context(pt->tid()); - if (!context) { - PERR("Context allocation failed"); - return -1; - } - Native_utcb *utcb = &context->utcb; - pt->_assign_physical_thread(_pid, utcb, this); - return 0; - } - - /** - * Unbind thread from protection domain - * - * Free the thread's slot and update thread object. - */ - inline void unbind_thread(Platform_thread *pt) - { - _free_context(pt->tid()); - } - - /** - * Free a context so it is allocatable again - * \param c PD wide unique context ID - */ - void free_context(Context_id const & c) - { - if (c > MAX_CONTEXT_ID) { return; } - owner_tid_by_context_id[c] = Kernel::INVALID_THREAD_ID; - } - - /** - * Assign parent interface to protection domain - */ - inline int assign_parent(Native_capability parent) { return 0; } - }; -} - -#endif /* _SRC__CORE__INCLUDE__PLATFORM_PD_H */ - - - diff --git a/base-mb/src/core/include/platform_thread.h b/base-mb/src/core/include/platform_thread.h deleted file mode 100755 index 2a8b89a71..000000000 --- a/base-mb/src/core/include/platform_thread.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * \brief Thread facility - * \author Martin Stein - * \date 2010-09-13 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SRC__CORE__INCLUDE__PLATFORM_THREAD_H_ -#define _SRC__CORE__INCLUDE__PLATFORM_THREAD_H_ - -#include -#include -#include -#include -#include -#include - -namespace Genode { - - class Platform_thread; - typedef Id_allocator Tid_allocator; - Tid_allocator* tid_allocator(); - - /** - * Base of the physical UTCB belonging to a specific thread - */ - Kernel::Utcb* physical_utcb(Native_thread_id tid); - - - /** - * Set physical UTCB address according to a specific thread ID. - * Useful to propagate UTCB address when allocating the whole context - * at a stretch as e.g. in core - */ - int physical_utcb(Native_thread_id const &tid, Kernel::Utcb * const &utcb); - - - class Platform_pd; - class Platform_thread - { - private: - - friend class Platform_pd; - - Native_thread_id _tid; /* global kernel thread ID */ - Native_process_id _pid; - Native_utcb* _utcb; - Pager_object *_pager; - uint32_t _params; - - /* for debugging purpose only */ - Platform_pd* _pd; - - /** - * Assign physical thread ID and UTCB address to thread - * - * This function is called from 'Platform_pd::bind_thread'. - */ - void _assign_physical_thread(int pid, Native_utcb* utcb, Platform_pd* pd) - { - _utcb = utcb; - _pid = pid; - _pd = pd; - } - - public: - - unsigned pid(){ return (unsigned)_pid; } - unsigned tid(){ return (unsigned)_tid; } - - enum { THREAD_INVALID = -1 }; /* invalid thread number */ - - /** - * Constructor - */ - Platform_thread(const char *name = 0, unsigned priority = 0, - int thread_id = THREAD_INVALID, uint32_t params = 0); - - /** - * Destructor - */ - ~Platform_thread(); - - /** - * Start thread - * - * \param ip instruction pointer to start at - * \param sp stack pointer to use - * \param cpu_no target cpu - * - * \retval 0 successful - * \retval -1 thread could not be started - */ - int start(void *ip, void *sp, unsigned int cpu_no = 0); - - /** - * Pause this thread - */ - void pause(); - - /** - * Resume this thread - */ - void resume(); - - /** - * Cancel currently blocking operation - */ - void cancel_blocking(); - - /** - * Override thread state with 's' - * - * \throw Cpu_session::State_access_failed - */ - void state(Thread_state s); - - /** - * Read thread state - * - * \throw Cpu_session::State_access_failed - */ - Thread_state state(); - - - /************************ - ** Accessor functions ** - ************************/ - - /** - * Set pager capability - */ - inline Pager_object *pager() { return _pager; } - inline void pager(Pager_object *pager) { _pager = pager; } - - /** - * Return identification of thread when faulting - */ - inline unsigned long pager_object_badge() const { return _tid; } - - /** - * Set the executing CPU for this thread - */ - void affinity(unsigned cpu); - - /** - * Get thread name - */ - inline const char *name() const { return "noname"; } - - - /********************* - ** Kernel specific ** - *********************/ - - inline addr_t utcb() const { return (addr_t)_utcb; } - }; -} - -#endif /* _SRC__CORE__INCLUDE__PLATFORM_THREAD_H_ */ diff --git a/base-mb/src/core/include/util.h b/base-mb/src/core/include/util.h deleted file mode 100755 index b440eec60..000000000 --- a/base-mb/src/core/include/util.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * \brief Core-internal utilities - * \author Martin Stein - * \date 2010-09-08 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SRC__CORE__INCLUDE__UTIL_H_ -#define _SRC__CORE__INCLUDE__UTIL_H_ - -/* Genode includes */ -#include -#include - -/* Kernel includes */ -#include - -namespace Genode { - - inline size_t get_page_size_log2() { return 12; } - inline size_t get_page_size() { return 1 << get_page_size_log2(); } - inline addr_t get_page_mask() { return ~(get_page_size() - 1); } - inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); } - inline addr_t round_page(addr_t addr) { return trunc_page(addr + get_page_size() - 1); } - - inline addr_t map_src_addr(addr_t core_local, addr_t phys) { return phys; } - inline size_t constrain_map_size_log2(size_t size_log2) - { - if (size_log2<14) return 12; - if (size_log2<16) return 14; - if (size_log2<18) return 16; - if (size_log2<20) return 18; - if (size_log2<22) return 20; - if (size_log2<24) return 22; - return 24; - } - - inline void print_page_fault(const char *msg, addr_t pf_addr, addr_t pf_ip, - Rm_session::Fault_type pf_type, - unsigned long faulter_badge) - { - printf("%s (%s pf_addr=%p pf_ip=%p from %02lx)\n", msg, - pf_type == Rm_session::WRITE_FAULT ? "WRITE" : "READ", - (void *)pf_addr, (void *)pf_ip, - faulter_badge); - } -} - -#endif /* _CORE__INCLUDE__UTIL_H_ */ diff --git a/base-mb/src/core/include/util/array.h b/base-mb/src/core/include/util/array.h deleted file mode 100644 index e0f161864..000000000 --- a/base-mb/src/core/include/util/array.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * \brief Utils to ease the work with arrays - * \author Martin stein - * \date 2011-03-22 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__UTIL__ARRAY_H_ -#define _INCLUDE__UTIL__ARRAY_H_ - -#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0])) -#define MAX_ARRAY_ID(array) (ARRAY_SIZE(array)-1) -#define LAST_ARRAY_ELEM(array) array[MAX_ARRAY_ID(array)] - -#endif /* _INCLUDE__UTIL__ARRAY_H_ */ diff --git a/base-mb/src/core/include/util/debug.h b/base-mb/src/core/include/util/debug.h deleted file mode 100644 index 48051438f..000000000 --- a/base-mb/src/core/include/util/debug.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * \brief Some tools for general purpose debugging - * \author Martin stein - * \date 2011-04-06 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__UTIL__DEBUG_H_ -#define _INCLUDE__UTIL__DEBUG_H_ - -#include -#include - -namespace Debug { - - /** - * Print out address and the according 32 bit memory-value - * XXX Should print a word instead of a fixed bitwidth XXX - */ - inline void dump(Cpu::addr_t const & a); - - /** - * Print memory-contents of a given area over the local addressspace - * as list with the according addresses in front - */ - inline void dump(Cpu::addr_t const & base, Cpu::size_t const & size, - bool downward = false); -}; - - -void Debug::dump(Cpu::addr_t const & a) { - printf("%8X: %8X", (Cpu::uint32_t)a, *((Cpu::uint32_t*)a)); -} - - -void Debug::dump(Cpu::addr_t const & base, Cpu::size_t const & size, - bool downward) -{ - using namespace Genode; - Cpu::addr_t top = base + size; - - if(!downward) { - for(Cpu::addr_t i=base; i=base;) { - i = i-Cpu::WORD_SIZE; - dump(i); - } -} - -#endif /* _INCLUDE__UTIL__DEBUG_H_ */ - diff --git a/base-mb/src/core/include/util/id_allocator.h b/base-mb/src/core/include/util/id_allocator.h deleted file mode 100644 index 486cecebf..000000000 --- a/base-mb/src/core/include/util/id_allocator.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * \brief Allocator for ID-labeled resources - * \author Martin Stein - * \date 2010-09-13 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__UTIL__ID_ALLOCATOR_H_ -#define _INCLUDE__UTIL__ID_ALLOCATOR_H_ - -/** - * \param HOLDER_T type that should hold ID's - * \param ID_T type of the allocatable ID's should be - * an enumeration type that expresses a variety - * less than the CPUs word width to the power of 2 - * \param BYTE_WIDTH the CPU's bytewidth - */ -template -class Id_allocator -{ - enum { - ID_WIDTH = sizeof(ID_T)*BYTE_WIDTH, - ID_RANGE = 1 << ID_WIDTH - }; - - ID_T _first_allocatable; - ID_T _last_allocatable; - - bool _id_in_use[ID_RANGE]; - HOLDER_T *_holder_by_id[ID_RANGE]; - - public: - - Id_allocator() : - _first_allocatable(0), - _last_allocatable(ID_RANGE-1) - { - for (unsigned i = _first_allocatable; - i <= _last_allocatable; i++) - - _id_in_use[i]=false; - } - - Id_allocator(ID_T first, ID_T last) : - _first_allocatable(first), - _last_allocatable(last) - { - for (unsigned i = _first_allocatable; - i <= _last_allocatable; i++) - - _id_in_use[i]=false; - } - - ID_T allocate() - { - for (unsigned i = _first_allocatable; - i <= _last_allocatable; i++) { - - if (_id_in_use[i]) - continue; - - _id_in_use[i] = true; - _holder_by_id[i] = 0; - return (ID_T)i; - } - - PERR("All ID's in use"); - return (ID_T)0; - } - - ID_T allocate(HOLDER_T* o) - { - for (unsigned i = _first_allocatable; - i <= _last_allocatable; i++) { - - if (_id_in_use[i]) - continue; - - _id_in_use[i] = true; - _holder_by_id[i] = o; - return (ID_T)i; - } - - PERR("All ID's in use"); - return (ID_T)0; - } - - bool allocate(HOLDER_T *o, ID_T id) - { - if (id < _first_allocatable || id > _last_allocatable) { - PERR("ID unallocatable"); - return false; - } - if (!_id_in_use[id]) { - _id_in_use[id] = true; - _holder_by_id[id] = o; - return true; - } - else{ - PERR("ID in use"); - return false; - } - } - - HOLDER_T *holder(ID_T id) { return _holder_by_id[id]; } - - void free(ID_T id) - { - _id_in_use[id]=false; - _holder_by_id[id]=0; - } -}; - -#endif /*_INCLUDE__UTIL__ID_ALLOCATOR_H_*/ - - diff --git a/base-mb/src/core/include/util/math.h b/base-mb/src/core/include/util/math.h deleted file mode 100644 index 76baace67..000000000 --- a/base-mb/src/core/include/util/math.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * \brief Core-internal utilities - * \author Martin Stein - * \date 2011-03-17 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__UTIL__MATH_H_ -#define _INCLUDE__UTIL__MATH_H_ - -namespace Math -{ - template - inline T round_up(T v, T rounding_log2); - - template - inline T round_down(T v, T rounding_log2); -} - - -template -T Math::round_up(T v, T rounding_log2) -{ - return round_down(v + (1< -T Math::round_down(T v, T rounding_log2) -{ - return v & ~((1 << rounding_log2) - 1); -} - -#endif /* _INCLUDE__UTIL__MATH_H_ */ diff --git a/base-mb/src/core/include/util/queue.h b/base-mb/src/core/include/util/queue.h deleted file mode 100644 index 6ec4f071c..000000000 --- a/base-mb/src/core/include/util/queue.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * \brief Queue with first-in first-out semantics - * \author Norman Feske - * \date 2008-08-15 - */ - -/* - * Copyright (C) 2008-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__UTIL__QUEUE_H_ -#define _INCLUDE__UTIL__QUEUE_H_ - -namespace Kernel { - - /* - * \param QT queue element type - */ - template - class Queue - { - protected: - - QT *_head; /* oldest element */ - QT *_tail; /* newest element */ - - public: - - class Item - { - protected: - - friend class Queue; - - QT *_next; - - public: - - Item() : _next(0) {} - - ~Item() { } - -// /** -// * Return true is fifo element is enqueued in a fifo -// */ -// bool is_enqueued() { return _next != 0; } - }; - - public: - - QT* head(){ return _head; } - - /** - * Return true if queue is empty - */ - bool empty() { return _tail == 0; } - - /** - * Constructor - * - * Start with an empty list. - */ - Queue(): _head(0), _tail(0) { } - - /** - * Destructor - */ - virtual ~Queue() { } - - /** - * Attach element at the end of the queue - */ - void enqueue(QT *e) - { - e->_next = 0; - - if (empty()) - _tail = _head = e; - else { - _tail->_next = e; - _tail = e; - } - _enqueue__verbose__success(); -} - - /** - * Obtain head element of the queue and remove element from queue - * - * \return head element or 0 if queue is empty - */ - QT *dequeue() - { - QT *result = _head; - - /* check if queue has only one last element */ - if (_head == _tail) - _head = _tail = 0; - else - _head = _head->_next; - - /* mark fifo queue element as free */ - if (result) - result->_next = 0; - - return result; - } - - /** - * Remove element from queue if it is enqueued - */ - void remove(QT *e) - { - QT* current=_head; - QT* predecessor=0; - - if (current!=e){ - while (1){ - predecessor=current; - current=current->_next; - if (current==e || !current) - break; - } - } else { - dequeue(); - return; - } - - if (!current) return; - if (current==_tail) _tail=predecessor; - - predecessor->_next=e->_next; - e->_next=0; -} - - protected: - - virtual void _enqueue__verbose__success(){} - - }; -} - -#endif /* _INCLUDE__UTIL__QUEUE_H_ */ diff --git a/base-mb/src/core/include/xilinx/microblaze.h b/base-mb/src/core/include/xilinx/microblaze.h deleted file mode 100644 index d46c0ee7c..000000000 --- a/base-mb/src/core/include/xilinx/microblaze.h +++ /dev/null @@ -1,403 +0,0 @@ -/* - * \brief Implementation of the Microblaze MMU - * \author Martin Stein - * \date 2010-11-08 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__DEVICES__XILINX_MICROBLAZE_H_ -#define _INCLUDE__DEVICES__XILINX_MICROBLAZE_H_ - -#include -#include -#include -#include - -namespace Xilinx { - - struct Microblaze - { - typedef Cpu::uint8_t Protection_id; - typedef Cpu::uint32_t Register; - - class Mmu { - - enum Error { - SUCCESS = 0, - INVALID_ENTRY_ID = -1, - INVALID_PAGE_SIZE = -2, - }; - - enum { - VERBOSE = 0, - USE_PROTECTION_ZONES = 0, - UTLB_SIZE = 64, - - TLBLO_GUARDED_LSHIFT = 0, - TLBLO_MEMCOHER_LSHIFT = 1, - TLBLO_INHIBCACHE_LSHIFT = 2, - TLBLO_WTHROUGH_LSHIFT = 3, - TLBLO_ZONE_LSHIFT = 4, - TLBLO_WRITEABLE_LSHIFT = 8, - TLBLO_EXECUTABLE_LSHIFT = 9, - TLBLO_REALPAGE_LSHIFT = 10, TLBLO_REALPAGE_MASK=0x3fffff, - - TLBHI_USER_LSHIFT = 4, - TLBHI_ENDIAN_LSHIFT = 5, - TLBHI_VALID_LSHIFT = 6, - TLBHI_SIZE_LSHIFT = 7, TLBHI_SIZE_MASK = 0x7, - TLBHI_TAG_LSHIFT = 10, TLBHI_TAG_MASK = 0x3fffff, - }; - - public: - - typedef Cpu::uint8_t Entry_id; - - enum { MAX_ENTRY_ID = UTLB_SIZE - 1, }; - - struct Page - { - typedef Cpu::uint8_t Size_id; - - enum { - MAX_SIZE_LOG2 = 24, - MAX_SIZE_ID = 7, - INVALID_SIZE_ID = MAX_SIZE_ID+1, - }; - - /** - * Translation between the native size ID's and the real memory size - * the page covers - */ - static inline unsigned int size_id_to_size_log2(Size_id const & i); - static inline Size_id size_log2_to_size_id(unsigned int const & size_log2); - }; - - private: - - /** - * Focus further operations on a specific entry - */ - inline void _entry(Entry_id & i); - - /** - * Read basic informations from a specific TLB entry - */ - inline void _entry(Entry_id & i, - Register & tlblo, - Register & tlbhi, - Protection_id & pid); - - /** - * Protection zones constrain access to mappings additionally, - * disable this feature - */ - inline void _disable_protection_zones(); - - public: - - /** - * Constructor - */ - inline Mmu(); - - /** - * Get some informations about a specific TLB entry - */ - inline signed int get_entry(Entry_id & i, Cpu::addr_t & vbase, - Protection_id & pid, unsigned int & size_log2); - /** - * Get all informations about a specific TLB entry - */ - inline signed int get_entry(Entry_id & i, Cpu::addr_t & pb, Cpu::addr_t & vb, - Protection_id & pid, unsigned int & size_log2, - bool & writeable, bool & executable); - - /** - * Overwrite a specific TLB entry with a new resolution - */ - inline signed int set_entry(Entry_id i, Cpu::addr_t const & pb, Cpu::addr_t const & vb, - Protection_id const & pid, unsigned int const & size_log2, - bool const & writeable, bool const & executable); - - /** - * Render a specific TLB entry ineffective - */ - inline void clear_entry(Entry_id i); - - /** - * Maximum available entry ID - */ - static inline Entry_id max_entry_id() { return (Entry_id) MAX_ENTRY_ID; }; - }; - - /** - * Read the current stack-pointer - */ - ALWAYS_INLINE static inline Cpu::addr_t stack_pointer(); - - /** - * Read, write and exchange the current protection ID - */ - static inline Protection_id protection_id(); - static inline void protection_id(Protection_id i); - static inline void protection_id(Protection_id & o, Protection_id n); - - inline Mmu * mmu(); - }; -} - - -/************************************** - * Xilinx::Microblaze implementations * - **************************************/ - -Cpu::addr_t Xilinx::Microblaze::stack_pointer() -{ - Register sp; - asm volatile("add %[sp], r1, r0" :[sp]"=r"(sp)::); - return (Cpu::addr_t)sp; -} - - -Xilinx::Microblaze::Mmu * Xilinx::Microblaze::mmu() { - static Mmu _mmu; - return &_mmu; -} - - -Xilinx::Microblaze::Protection_id Xilinx::Microblaze::protection_id() -{ - Protection_id i; - asm volatile ("mfs %[i], rpid" - : [i] "=r" (i) ::); - return i; -} - - -void Xilinx::Microblaze::protection_id(Protection_id i) -{ - asm volatile ("mts rpid, %[i] \n" - "bri 4" - : [i] "+r" (i) ::); -} - - -void Xilinx::Microblaze::protection_id(Protection_id & o, Protection_id n) -{ - asm volatile ("mfs %[o], rpid \n" - "mts rpid, %[n] \n" - "bri 4" - : [o] "=r" (o), - [n] "+r" (n) ::); -} - - -/******************************************* - * Xilinx::Microblaze::Mmu implementations * - *******************************************/ - -Xilinx::Microblaze::Mmu::Mmu() -{ - if (!USE_PROTECTION_ZONES) { _disable_protection_zones(); } - else { PERR("Protection zones not supported"); } -} - - -void Xilinx::Microblaze::Mmu::_disable_protection_zones() -{ - asm volatile ("addik r31, r0, 0xC0000000 \n" - "mts rzpr, r31 \n" - "bri 4" - ::: "r31" ); -} - - -signed int Xilinx::Microblaze::Mmu::get_entry(Entry_id & i, Cpu::addr_t & vb, - Protection_id & pid, unsigned int & size_log2) -{ - if(i>MAX_ENTRY_ID) { return INVALID_ENTRY_ID; }; - - Protection_id opid = protection_id(); - - /* Read TLB entry */ - asm volatile ("mts rtlbx, %[i] \n" - "bri 4 \n" - "mfs %[vb], rtlbhi \n" - "mfs %[pid], rpid" - : [i] "+r" (i), - [vb] "=r" (vb), - [pid] "=r" (pid) ::); - - protection_id(opid); - - /** - * Decode informations - */ - Page::Size_id const s = (vb & (TLBHI_SIZE_MASK<>TLBHI_SIZE_LSHIFT; - size_log2 = Page::size_id_to_size_log2(s); - - vb = Math::round_down(vb, size_log2); - return SUCCESS; -} - - -signed int Xilinx::Microblaze::Mmu::get_entry(Entry_id & i, Cpu::addr_t & pb, Cpu::addr_t & vb, - Protection_id & pid, unsigned int & size_log2, - bool & writeable, bool & executable) -{ - if(i>MAX_ENTRY_ID) { return INVALID_ENTRY_ID; }; - - Protection_id opid = protection_id(); - - /* Read TLB entry */ - asm volatile ("mts rtlbx, %[i] \n" - "bri 4 \n" - "mfs %[pb], rtlblo \n" - "mfs %[vb], rtlbhi \n" - "mfs %[pid], rpid" - : [i] "+r" (i), - [pb] "=r" (pb), - [vb] "=r" (vb), - [pid] "=r" (pid) ::); - - protection_id(opid); - - /** - * Decode informations - */ - writeable = pb & (1<>TLBHI_SIZE_LSHIFT; - size_log2 = Page::size_id_to_size_log2(s); - - pb = Math::round_down(pb, size_log2); - vb = Math::round_down(vb, size_log2); - return SUCCESS; -} - - -signed int Xilinx::Microblaze::Mmu::set_entry(Entry_id i, Cpu::addr_t const & pb, Cpu::addr_t const & vb, - Protection_id const & pid, unsigned int const & size_log2, - bool const & writeable, bool const & executable) -{ - Protection_id opid; - protection_id(opid, pid); - - /** - * Create TLBLO register value - */ - Register tlblo = (Register)Math::round_down(pb, size_log2); - tlblo |= writeable << TLBLO_WRITEABLE_LSHIFT; - tlblo |= executable << TLBLO_EXECUTABLE_LSHIFT; - - /** - * Create TLBHI register value - */ - Register tlbhi = Math::round_down(vb, size_log2); - tlbhi |= 1 << TLBHI_VALID_LSHIFT; - - Page::Size_id s = Page::size_log2_to_size_id(size_log2); - if(s == Page::INVALID_SIZE_ID) { return INVALID_PAGE_SIZE; } - tlbhi |= ((s & TLBHI_SIZE_MASK) << TLBHI_SIZE_LSHIFT); - - /* Write TLB entry */ - asm volatile ("mts rtlbx, %[i] \n" - "bri 4 \n" - "mts rtlblo, %[tlblo] \n" - "bri 4 \n" - "mts rtlbhi, %[tlbhi] \n" - "bri 4" - : [i] "+r" (i), - [tlblo] "+r" (tlblo), - [tlbhi] "+r" (tlbhi) ::); - - if(VERBOSE) - { - PINF("TLB + %2u[0x%8X..0x%8X) r%c%c\n" - " [0x%8X..0x%8X) 2**%i\n", - pid, Math::round_down(vb, size_log2), - Math::round_down(vb+(1<(pb, size_log2), - Math::round_down(pb+(1<MAX_ENTRY_ID) { return; }; - - Protection_id pid = protection_id(); - - if(VERBOSE) { - Cpu::addr_t page; - Protection_id pid; - unsigned size_log2; - - if(!get_entry(i, page, pid, size_log2)) { - PINF("TLB - %i[0x%8X..0x%8X] 2**%i", - pid, (Cpu::uint32_t)page, - (Cpu::uint32_t)page+(1<MAX_ARRAY_ID(_size_log2_to_size_id)) { return INVALID_SIZE_ID; } - return (unsigned int)_size_log2_to_size_id[size_log2]; -} - - -unsigned int Xilinx::Microblaze::Mmu::Page::size_id_to_size_log2(Size_id const & i) -{ - static unsigned const _size_id_to_size_log2 [MAX_SIZE_ID+1] = - { 10, 12, 14, 16, 18, 20, 22, 24 }; - - if(i>ARRAY_SIZE(_size_id_to_size_log2)-1) { return 0; } - return (unsigned int)_size_id_to_size_log2[i]; -} - -#endif /* _INCLUDE__DEVICES__XILINX_MICROBLAZE_H_ */ - diff --git a/base-mb/src/core/io_mem_session_support.cc b/base-mb/src/core/io_mem_session_support.cc deleted file mode 100755 index 26c743136..000000000 --- a/base-mb/src/core/io_mem_session_support.cc +++ /dev/null @@ -1,28 +0,0 @@ -/* - * \brief Implementation of the IO_MEM session interface - * \author Norman Feske - * \author Martin Stein - * \date 2010-09-09 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include - -using namespace Genode; - - -void Io_mem_session_component::_unmap_local(addr_t base, size_t size) -{ } - - -addr_t Io_mem_session_component::_map_local(addr_t base, size_t size) -{ - /* Core memory gets mapped 1:1 except of the context area */ - return base; -} diff --git a/base-mb/src/core/irq_session_component.cc b/base-mb/src/core/irq_session_component.cc deleted file mode 100644 index 33457ed6b..000000000 --- a/base-mb/src/core/irq_session_component.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* - * \brief Implementation of IRQ session component - * \author Norman Feske - * \author Martin Stein - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include -#include -#include -#include - -using namespace Genode; - -void Irq_session_component::wait_for_irq() -{ - using namespace Xilinx; - if (!_attached) { - if(Kernel::irq_allocate(_irq_number)) { - PERR("Kernel::irq_allocate(%i) failed", _irq_number); - sleep_forever(); - } - _attached = true; - } - Kernel::irq_wait(); -} - - -Irq_session_component::Irq_session_component(Cap_session *cap_session, - Range_allocator *irq_alloc, - const char *args) -: - _irq_alloc(irq_alloc), - _entrypoint(cap_session, STACK_SIZE, "irq"), - _attached(false) -{ - long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1); - if (!_irq_alloc || (irq_number == -1) || - _irq_alloc->alloc_addr(1, irq_number).is_error()) - { - PERR("unavailable IRQ %lx requested", irq_number); - return; - } - _irq_number = irq_number; - _entrypoint.activate(); - _cap = Irq_session_capability(_entrypoint.manage(this)); -} - - -Irq_session_component::~Irq_session_component() -{ - _irq_alloc->free((void*)_irq_number, 1); - if (_attached) { - if(Kernel::irq_free(_irq_number)){ - PERR("Kernel::irq_free failed"); - } - } -} - diff --git a/base-mb/src/core/platform.cc b/base-mb/src/core/platform.cc deleted file mode 100644 index a7986481b..000000000 --- a/base-mb/src/core/platform.cc +++ /dev/null @@ -1,312 +0,0 @@ -/* - * \brief Platform interface implementation - * \author Martin Stein - * \date 2010-09-08 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include -#include -#include -#include -#include - -static bool const verbose = 0; - -extern unsigned _program_image_begin; -extern unsigned _program_image_end; - -extern unsigned _boot_modules_meta_start; -extern unsigned _boot_modules_meta_end; - -namespace Roottask -{ - /** - * Entry for the core-pager-thread that handles all - * pagefaults belonging to core-threads. Itself has - * to be paged 1:1 by the kernel. Core pager maps all - * 1:1 except of the thread-context-area - */ - static void pager(); - - static Kernel::Utcb pager_utcb; - static Cpu::word_t pager_stack[Cpu::_4KB_SIZE]; -} - - -Genode::Thread_base::Context * Roottask::physical_context(Genode::Native_thread_id tid) -{ - using namespace Cpu; - using Genode::Thread_base; - - static const unsigned int aligned_size = - Math::round_up(CONTEXT_SIZE, - CONTEXT_PAGE_SIZE_LOG2); - static Thread_base::Context * _context[User::MAX_THREAD_ID]; - - if (tid >= sizeof(_context)/sizeof(_context[0])) { - PERR("Native thread ID out of range"); - return 0; - } - - if(!_context[tid]) { - - /* Allocate new context */ - if (Genode::platform_specific() - ->core_mem_alloc() - ->alloc_aligned(aligned_size, - (void**)&_context[tid], - CONTEXT_PAGE_SIZE_LOG2).is_error()) - { - PERR("Allocate memory for a new stack- and misc-area failed"); - return 0; - } - _context[tid] = (Thread_base::Context*)((addr_t)_context[tid] + - aligned_size - sizeof(Thread_base::Context)); - - /* Synchronize output of 'Genode::physical_utcb' if alignment fits */ - if(Math::round_up((addr_t)&_context[tid]->utcb, - Kernel::Utcb::ALIGNMENT_LOG2)!= - (addr_t)&_context[tid]->utcb) - { - PINF("%8X, %8X", (unsigned)Math::round_up((addr_t)&_context[tid]->utcb, - Kernel::Utcb::ALIGNMENT_LOG2), (unsigned)&_context[tid]->utcb); - - PWRN("Wrong UTCB alignment in context"); - } else { - Genode::physical_utcb(tid, (Kernel::Utcb*)&_context[tid]->utcb); - } - if(verbose) { - PDBG("Context %i: [%p|%p|%p|%p]", tid, - (void*)((addr_t)_context[tid] + sizeof(Thread_base::Context) - aligned_size), - (Thread_base::Context*)((addr_t)_context[tid] - STACK_SIZE), - _context[tid], &_context[tid]->utcb); - } - } - return _context[tid]; -} - - -void Roottask::pager() -{ - using namespace Genode; - using namespace Roottask; - - typedef Platform_pd::Context_part Context_part; - typedef Kernel::Paging::Request Request; - typedef Kernel::Paging::Physical_page Physical_page; - - static Physical_page::size_t context_page_size; - if(Physical_page::size_by_size_log2(context_page_size, CONTEXT_PAGE_SIZE_LOG2)){ - PERR("Invalid page size for thread context area"); - } - - Request *r = (Request*)&pager_utcb; - - while (1) { - unsigned request_length = Kernel::ipc_serve(0); - if (request_length != sizeof(Request)) { - PERR("Invalid request"); - continue; - } - - addr_t pa = 0; - - Physical_page::size_t ps = Physical_page::INVALID_SIZE; - addr_t va = r->virtual_page.address(); - - Native_thread_id context_owner = 0; - Context_part context_part = Platform_pd::NO_CONTEXT_PART; - unsigned stack_offset = 0; - - if (platform_pd()->metadata_if_context_address(va, &context_owner, - &context_part, - &stack_offset)) - { - switch (context_part) { - - case Platform_pd::STACK_AREA: - { - Cpu::word_t* pstack = (Cpu::word_t*)physical_context(context_owner); - pa = (addr_t)(pstack-(stack_offset/sizeof(Cpu::word_t))); - break; - } - - case Platform_pd::UTCB_AREA: - pa = (addr_t)physical_utcb(context_owner); - break; - - case Platform_pd::MISC_AREA: - pa = (addr_t)physical_context(context_owner)->stack; - break; - - default: - PERR("No roottask mapping, " - "vaddr=0x%p, tid=%i, ip=%p\n", - (void*)r->virtual_page.address(), - r->source.tid, - (void*)r->source.ip); - break; - } - ps = context_page_size; - } else { - pa = va; - ps = Physical_page::MAX_VALID_SIZE; - } - - Kernel::tlb_load(pa, va, r->virtual_page.protection_id(), - ps, Physical_page::RWX); - - Kernel::thread_wake(r->source.tid); - } -} - - -void Genode::Platform::_optimize_init_img_rom(long int & base, size_t const & size) -{ - enum { - INIT_TEXT_SEGM_ALIGN_LOG2 = Cpu::_64KB_SIZE_LOG2, - INIT_TEXT_SEGM_ALIGN = 1 << INIT_TEXT_SEGM_ALIGN_LOG2, - ELF_HEADER_SIZE = Cpu::_4KB_SIZE - }; - - /* Preserve old location for now */ - long int const old_base = base; - _core_mem_alloc.remove_range((addr_t)old_base, size); - - /* Search for location where text-segment would be mapable - * with pages of size INIT_TEXT_SEGM_ALIGN */ - if (_core_mem_alloc.alloc_aligned(size + 2*INIT_TEXT_SEGM_ALIGN, - (void**)&base, INIT_TEXT_SEGM_ALIGN_LOG2).is_ok()) - { - /* Found better location so move */ - base = base + INIT_TEXT_SEGM_ALIGN - ELF_HEADER_SIZE; - memcpy((void*)base, (void*)old_base, size); - _core_mem_alloc.add_range((addr_t)old_base, size); - return; - } - /* Keep old location */ - base = old_base; -} - - -Genode::Platform::Platform() : - _core_mem_alloc(0), - _io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()), - _irq_alloc(core_mem_alloc()), _vm_base(0), _vm_size(0) -{ - - using namespace Roottask; - using namespace Genode; - - _core_mem_alloc.add_range((addr_t)Cpu::RAM_BASE, (size_t)Cpu::RAM_SIZE); - - /*************************************************** - * Avoid allocations on '_core_mem_alloc' since it * - * contains space yet that is in use * - ***************************************************/ - - /* Preserve core's program image range with page-granularity from allocation */ - addr_t const img_base = trunc_page((addr_t)&_program_image_begin); - size_t const img_size = round_page((addr_t)&_program_image_end) - img_base; - _core_mem_alloc.remove_range(img_base, img_size); - - /* Preserve core's context area with page-granularity from allocation */ - addr_t const ctxt_area_base = trunc_page((addr_t)Native_config::context_area_virtual_base()); - size_t const ctxt_area_size = round_page((addr_t)Native_config::context_area_virtual_base()); - _core_mem_alloc.remove_range(ctxt_area_base, ctxt_area_size); - - /* Preserve UART MMIO with page-granularity from allocation */ - addr_t const uart_base = trunc_page(User::UART_BASE); - _core_mem_alloc.remove_range(uart_base, get_page_size()); - - /* Format of module meta-data as found in the ROM module image */ - struct Boot_module - { - long name; /* physical address of null-terminated string */ - long base; /* physical address of module data */ - long size; /* size of module data in bytes */ - }; - - addr_t const md_base = (addr_t)&_boot_modules_meta_start; - addr_t const md_top = (addr_t)&_boot_modules_meta_end; - size_t const meta_size = md_top - md_base; - - if (meta_size > get_page_size()) { - PERR("Boot modules header is larger than supported"); - sleep_forever(); - } - Boot_module * module = (Boot_module *)md_base; - Boot_module * init_module=0; - - /* Preserve boot modules from allocation */ - for (; (addr_t)module < md_top; module++) { - const char *name = (const char*)module->name; - - /* Init's module will need allocation because we optimize its location */ - if (!strcmp(name, "init")) - { - init_module = module; - continue; - } - _core_mem_alloc.remove_range(trunc_page(module->base), - round_page(module->size)); - } - _optimize_init_img_rom(init_module->base, init_module->size); - _core_mem_alloc.remove_range(trunc_page(init_module->base), - round_page(init_module->size)); - - /***************************************************************** - * from now on it's save to allocate memory on '_core_mem_alloc' * - *****************************************************************/ - - /* Initialize ROM FS with the given boot modules */ - module = (Boot_module *)md_base; - for (; (addr_t)module < md_top; module++) { - Rom_module *rom_module = new (core_mem_alloc()) - Rom_module(module->base, module->size, (const char*)module->name); - _rom_fs.insert(rom_module); - } - - /* Start the core-pager */ - if(Kernel::thread_create(PAGER_TID, PROTECTION_ID, - Kernel::INVALID_THREAD_ID, - &pager_utcb, - (addr_t)pager, - (addr_t)&pager_stack[sizeof(pager_stack)/sizeof(pager_stack[0])], - true << Kernel::THREAD_CREATE__PARAM__IS_ROOT_LSHIFT)) - { - PERR("Couldn't start cores pager"); - sleep_forever(); - } - - /* Core's mainthread shall be paged by the core-pager */ - Kernel::thread_pager(MAIN_THREAD_ID, PAGER_TID); - - /* Initialze core's remaining allocators */ - _irq_alloc.add_range(User::MIN_IRQ, User::MAX_IRQ-User::MIN_IRQ); - _io_mem_alloc.add_range(User::IO_MEM_BASE, User::IO_MEM_SIZE); - - /* Setup virtual memory for common programs */ - _vm_base=User::VADDR_BASE; - _vm_size=User::VADDR_SIZE - get_page_size(); - - if (verbose) { - PINF("Printing core memory layout summary"); - printf("[_core_mem_alloc]\n"); _core_mem_alloc.raw()->dump_addr_tree(); - printf("[_io_mem_alloc]\n"); _io_mem_alloc.raw()->dump_addr_tree(); - printf("[_irq_alloc]\n"); _irq_alloc.raw()->dump_addr_tree(); - } -} - -void Genode::Core_parent::exit(int exit_value) { } - - diff --git a/base-mb/src/core/platform_thread.cc b/base-mb/src/core/platform_thread.cc deleted file mode 100755 index 0d6b20a84..000000000 --- a/base-mb/src/core/platform_thread.cc +++ /dev/null @@ -1,191 +0,0 @@ -/* - * \brief Thread facility - * \author Norman Feske - * \author Martin Stein - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include -#include -#include -#include "include/platform.h" -#include - -static bool const verbose = 0; - -using namespace Genode; - - -Tid_allocator* Genode::tid_allocator() -{ - static Tid_allocator _tida(User::MIN_THREAD_ID+1, User::MAX_THREAD_ID); - return &_tida; -} - - -Pid_allocator* Genode::pid_allocator() -{ - static Pid_allocator _pida(User::MIN_PROTECTION_ID, User::MAX_PROTECTION_ID); - return &_pida; -} - - -namespace Genode -{ - static Kernel::Utcb * phys_utcb[User::MAX_THREAD_ID]; -} - - -int Genode::physical_utcb(Native_thread_id const &tid, Kernel::Utcb * const &utcb) -{ - if (tid < sizeof(phys_utcb)/sizeof(phys_utcb[0])) { - Genode::phys_utcb[tid] = utcb; - return true; - } - return false; -} - - -Kernel::Utcb* Genode::physical_utcb(Native_thread_id tid) -{ - - if (tid >= sizeof(phys_utcb)/sizeof(phys_utcb[0])) { - PERR("Native thread ID out of range"); - return 0; - } - - if(!phys_utcb[tid]) { - if (platform_specific()-> - core_mem_alloc()-> - alloc_aligned(sizeof(Kernel::Utcb), - (void**)&phys_utcb[tid], - Kernel::Utcb::ALIGNMENT_LOG2).is_error()) - { - PERR("Allocate memory for a new UTCB failed"); - return 0; - } - if(verbose) { - PDBG("UTCB %i: [%p|%p]", tid, phys_utcb[tid], - (void*)((addr_t)phys_utcb[tid] + sizeof(Kernel::Utcb))); - } - } - return phys_utcb[tid]; -} - - -void Platform_thread::affinity(unsigned int cpu_no) { PERR("not implemented"); } - - -void Platform_thread::cancel_blocking() { PERR("not implemented"); } - - -void Platform_thread::state(Thread_state s) -{ - PDBG("Not implemented"); - throw Cpu_session::State_access_failed(); -} - - -Thread_state Platform_thread::state() -{ - PDBG("Not implemented"); - throw Cpu_session::State_access_failed(); -} - - -int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no) -{ - Native_thread_id pager_tid = _pager ? _pager->cap().dst() : 0; - Kernel::Utcb* putcb = physical_utcb(_tid); - - /* Hand over arguments for the thread's bootstrap */ - *((Native_thread_id*)&putcb->byte[0]) = _tid; - if (verbose) { - PDBG("Start Thread, tid=%i, pid=%i, pager=%i", _tid, _pid, pager_tid); - PDBG("vip=0x%p, vsp=%p, vutcb=0x%p", ip, sp, _utcb); - } - int const error = Kernel::thread_create(_tid, _pid, pager_tid, - putcb, (addr_t)ip, (addr_t)sp, 0); - if (error) { - PERR("Kernel::thread_create failed, error=%di", error); - return -1; - } - return 0; -} - - -void Platform_thread::pause() -{ - PDBG("not implemented"); -} - - -void Platform_thread::resume() -{ - PDBG("not implemented"); -} - - -Platform_thread::Platform_thread(const char *name, unsigned, int thread_id, - uint32_t params) -: _tid(0), _utcb(0), _params(params) -{ - if (!_tid) { - if (!(_tid = tid_allocator()->allocate(this))) { - PERR("TID allocation failed"); - return; - } - } - else if (!tid_allocator()->allocate(this, (Native_thread_id)thread_id)) { - PERR("TID allocation failed"); - return; - } -} - - -Platform_thread::~Platform_thread() { - _pd->unbind_thread(this); - if(Kernel::thread_kill(_tid)){ - PERR("Kernel::thread_kill(%i) failed", (unsigned)_tid); - } - tid_allocator()->free(_tid); -} - - -bool Ipc_pager::resolved() -{ - typedef Platform_pd::Context_part Context_part; - typedef Mapping::Physical_page Physical_page; - - addr_t va = (addr_t)_request.virtual_page.address(); - Native_thread_id context_owner = 0; - Context_part context_part = Platform_pd::NO_CONTEXT_PART; - unsigned stack_offset = 0; - - Platform_pd* pd = - pid_allocator()->holder(_request.virtual_page.protection_id()); - - if (!pd) { return false; } - if (!pd->metadata_if_context_address(va, &context_owner, &context_part, - &stack_offset)) - { - return false; - } - - if (context_part != Platform_pd::UTCB_AREA) { return false; } - - Native_utcb * const putcb = physical_utcb(context_owner); - set_reply_mapping(Genode::Mapping(va, (addr_t)putcb, false, - Native_utcb::size_log2(), true)); - - return true; -} diff --git a/base-mb/src/core/ram_session_support.cc b/base-mb/src/core/ram_session_support.cc deleted file mode 100755 index a012e3185..000000000 --- a/base-mb/src/core/ram_session_support.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* - * \brief Export RAM dataspace as shared memory object (dummy) - * \author Norman Feske - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -/* core includes */ -#include - - -using namespace Genode; - -static bool const verbose = false; - -void Ram_session_component::_export_ram_ds(Dataspace_component *ds) -{ - if (verbose) PERR("not implemented"); -} - - -void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds) -{ - if (verbose) PERR("not implemented"); -} - - -void Ram_session_component::_clear_ds(Dataspace_component *ds) -{ - /* - * We don't have to allocate a core local dataspace to get - * virtual access because core is mapped 1-to-1. (except for - * its context-area) - */ - memset((void *)ds->phys_addr(), 0, ds->size()); -} diff --git a/base-mb/src/core/rm_session_support.cc b/base-mb/src/core/rm_session_support.cc deleted file mode 100755 index a46914cda..000000000 --- a/base-mb/src/core/rm_session_support.cc +++ /dev/null @@ -1,38 +0,0 @@ -/* - * \brief RM-session implementation - * \author Norman Feske - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -/* core includes */ -#include -#include - -using namespace Genode; - -static bool const verbose = false; - -void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size) -{ - if (verbose) { - PDBG("Flush %i B from [%p,%p)", - (unsigned int)size, - (void*)virt_base, - (void*)((unsigned int)virt_base+size)); - } - - Kernel::Protection_id pid = - tid_allocator()->holder(this->badge())->pid(); - - Kernel::tlb_flush(pid, virt_base, (unsigned int)size); -} diff --git a/base-mb/src/core/target.inc b/base-mb/src/core/target.inc deleted file mode 100755 index 9a0b275ca..000000000 --- a/base-mb/src/core/target.inc +++ /dev/null @@ -1,54 +0,0 @@ -GEN_CORE_DIR = $(BASE_DIR)/src/core -SPEC_CORE_DIR = $(REP_DIR)/src/core -SPEC_BASE_DIR = $(REP_DIR)/src/base - - -SRC_CC = \ - context_area.cc \ - core_rm_session.cc \ - cpu_session_component.cc \ - dataspace_component.cc \ - dump_alloc.cc \ - io_mem_session_component.cc \ - io_mem_session_support.cc \ - irq_session_component.cc \ - main.cc \ - pd_session_component.cc \ - platform.cc \ - platform_services.cc \ - platform_thread.cc \ - cpu_session_support.cc \ - ram_session_component.cc \ - ram_session_support.cc \ - rm_session_component.cc \ - rm_session_support.cc \ - rom_session_component.cc \ - signal_session_component.cc \ - signal_source_component.cc \ - thread.cc \ - thread_bootstrap.cc \ - thread_roottask.cc \ - -INC_DIR = $(SPEC_CORE_DIR)/include \ - $(GEN_CORE_DIR)/include - -vpath context_area.cc $(SPEC_CORE_DIR) -vpath cpu_session_component.cc $(GEN_CORE_DIR) -vpath dataspace_component.cc $(GEN_CORE_DIR) -vpath dump_alloc.cc $(GEN_CORE_DIR) -vpath io_mem_session_component.cc $(GEN_CORE_DIR) -vpath io_mem_session_support.cc $(SPEC_CORE_DIR) -vpath irq_session_component.cc $(SPEC_CORE_DIR) -vpath main.cc $(GEN_CORE_DIR) -vpath pd_session_component.cc $(GEN_CORE_DIR) -vpath platform.cc $(GEN_CORE_DIR) -vpath platform_services.cc $(GEN_CORE_DIR) -vpath platform_thread.cc $(GEN_CORE_DIR) -vpath ram_session_component.cc $(GEN_CORE_DIR) -vpath rm_session_component.cc $(GEN_CORE_DIR) -vpath rom_session_component.cc $(GEN_CORE_DIR) -vpath signal_session_component.cc $(GEN_CORE_DIR) -vpath signal_source_component.cc $(GEN_CORE_DIR) -vpath thread.cc $(SPEC_BASE_DIR)/thread -vpath thread_bootstrap.cc $(SPEC_BASE_DIR)/thread -vpath thread_roottask.cc $(GEN_CORE_DIR) diff --git a/base-mb/src/core/target.mk b/base-mb/src/core/target.mk deleted file mode 100755 index 348c5788c..000000000 --- a/base-mb/src/core/target.mk +++ /dev/null @@ -1,10 +0,0 @@ -TARGET = core -LIBS = kernel_core cxx ipc heap printf_microblaze child pager lock \ - raw_signal raw_server - -STARTUP_LIB = kernel_core -LD_SCRIPT = $(REP_DIR)/src/platform/genode.ld - -SRC_S += boot_modules.s - -include $(PRG_DIR)/target.inc diff --git a/base-mb/src/core/thread_roottask.cc b/base-mb/src/core/thread_roottask.cc deleted file mode 100755 index 8c8c6e22b..000000000 --- a/base-mb/src/core/thread_roottask.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - * \brief Implementation of Thread API for roottask - * \author Norman Feske - * \date 2010-09-01 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include -#include -#include -#include -#include - -using namespace Genode; - -static bool const verbose = 0; - -namespace Roottask { - - Platform_pd* platform_pd() - { - static Platform_pd _pd(PROTECTION_ID); - return &_pd; - } -} - - -void Thread_base::_init_platform_thread() { } - - -void Thread_base::_deinit_platform_thread() -{ - Platform_pd *pd = Roottask::platform_pd(); - Platform_pd::Context_id cid; - - if (pd->cid_if_context_address((addr_t)_context, &cid)){ - pd->free_context(cid); - } - - if(Kernel::thread_kill(_tid)){ - PERR("Kernel::thread_kill(%i) failed", (unsigned)_tid); - } - tid_allocator()->free(_tid); -} - - -void Thread_base::_thread_start() -{ - myself()->entry(); - PDBG("Thread returned, tid=%i, pid=%i", - myself()->tid(), Roottask::PROTECTION_ID); - - Thread_base::myself()->_join_lock.unlock(); - Genode::sleep_forever(); -} - - -void Thread_base::_init_context(Context* context) -{ - _tid=tid_allocator()->allocate(); - Platform_pd *pd = Roottask::platform_pd(); - - Platform_pd::Context_id cid; - if (!pd->cid_if_context_address((addr_t)context, &cid)){ - PERR("Invalid context address 0x%p", context); - return; - } - if (!pd->allocate_context(_tid, cid)){ - PERR("Allocating context %i failed", cid); - return; - } -} - - -void Thread_base::start() -{ - using namespace Genode; - - Native_process_id const pid = Roottask::PROTECTION_ID; - Native_thread_id const pager_tid = Roottask::PAGER_TID; - void * const vsp = &_context->stack; - Native_utcb * const vutcb = &_context->utcb; - Kernel::Utcb * const putcb = physical_utcb(_tid); - void * const vip = (void *)_thread_start; - - if(verbose) { - PDBG("Start Thread, tid=%i, pid=%i, pager=%i", _tid, pid, pager_tid); - PDBG(" vip=0x%p, vsp=%p, vutcb=0x%p", vip, vsp, vutcb); - PDBG(" pip=0x%p, psp=%p, putcb=0x%p", - vip, (void*)Roottask::physical_context(_tid)->stack, putcb); - } - - if (Kernel::thread_create(_tid, pid, pager_tid, - putcb, (addr_t)vip, (addr_t)vsp, - 1 << Kernel::THREAD_CREATE__PARAM__IS_ROOT_LSHIFT)) - { - PERR("Kernel::thread_create failed"); - } -} - - -void Thread_base::cancel_blocking() { PERR("not implemented"); } - diff --git a/base-mb/src/kernel/generic/blocking.cc b/base-mb/src/kernel/generic/blocking.cc deleted file mode 100755 index 52251a330..000000000 --- a/base-mb/src/kernel/generic/blocking.cc +++ /dev/null @@ -1,268 +0,0 @@ -/* - * \brief Blockings that can prevent a thread from beeing executed - * \author Martin Stein - * \date 2011-02-22 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include -#include "include/thread.h" -#include -#include - -Kernel::Data_tlb_miss::On_occurence__result Kernel::Data_tlb_miss::on_occurence() -{ - if (!_missing_resolution.virtual_page.valid()) { - _on_occurence__error__virtual_page_invalid(); } - - Event::_populate(); - if (!_missing_resolution.physical_page.valid()) { - _on_occurence__verbose__waiting_for_resolution(); - return EVENT_PENDING; } - - tlb()->add(&_missing_resolution); - _missing_resolution.invalidate(); - return EVENT_PROCESSED; -} - - -void Kernel::Data_tlb_miss::Listener::_resolve_identically(Physical_page::size_t s, - Physical_page::Permissions p) -{ - new (&_resolution->physical_page) - Physical_page(_resolution->virtual_page.address(), s, p); -} - - -Kernel::Instruction_tlb_miss::On_occurence__result Kernel::Instruction_tlb_miss::on_occurence() -{ - if (!_missing_resolution.virtual_page.valid()) - _on_occurence__error__virtual_page_invalid(); - - Event::_populate(); - if (!_missing_resolution.physical_page.valid()) { - _on_occerence__verbose__waiting_for_resolution(); - return EVENT_PENDING; - } - - tlb()->add(&_missing_resolution); - _missing_resolution.invalidate(); - return EVENT_PROCESSED; -} - - -void Kernel::Instruction_tlb_miss::Listener::_resolve_identically(Physical_page::size_t s, - Physical_page::Permissions p) -{ - new (&_resolution->physical_page) - Physical_page(_resolution->virtual_page.address(), s, p); -} - - -void Kernel::Data_tlb_miss::Listener::_on_event() -{ - _on_data_tlb_miss(&_resolution->virtual_page, - _resolution->write_access); -} - - -void Kernel::Instruction_tlb_miss::Listener::_on_event() -{ - _on_instruction_tlb_miss(&_resolution->virtual_page); -} - -extern bool irq_occured[]; - -bool Kernel::Irq::unblock() -{ - Thread * const h = irq_allocator()->holder(_id); - if (!h) { - irq_controller()->ack_irq(_id); - return true; - } - h->handle(_id); - return true; -} - - -bool Kernel::Exception::unblock() -{ - int result = false; - - switch (_id) { - - case INSTRUCTION_TLB_MISS: - - new (&Instruction_tlb_miss::_missing_resolution.virtual_page) - Virtual_page(address(), protection_id()); - - if (Instruction_tlb_miss::on_occurence() == EVENT_PROCESSED) - result = true; - - break; - - case DATA_TLB_MISS: - - new (&Data_tlb_miss::_missing_resolution.virtual_page) - Virtual_page(address(), protection_id()); - - Data_tlb_miss::_missing_resolution.write_access = attempted_write_access(); - - if (Data_tlb_miss::on_occurence() == EVENT_PROCESSED) - result = true; - - break; - - default: - PERR("Unexpected exception %i\n", _id); - halt(); - } - - return result; -} - - -bool Kernel::Syscall::unblock() -{ - switch (_id){ - case PRINT_CHAR: - { - return _source->on_print_char(*_argument_0) == Event::EVENT_PROCESSED ? - true : false; - } - - case THREAD_CREATE: - { - Thread_create::Argument a; - a.tid = (Thread_id)*_argument_0; - a.pid = (Protection_id)*_argument_1; - a.pager_tid = (Thread_id)*_argument_2; - a.utcb = (Utcb*)*_argument_3; - a.vip = (addr_t)*_argument_4; - a.vsp = (addr_t)*_argument_5; - a.is_privileged = - (bool)(*_argument_6&(1<on_thread_create(&a, (Thread_create::Result*)_result_0) == Event::EVENT_PROCESSED ? - true : false; - } - - case THREAD_KILL: - { - Thread_kill::Argument a; - a.tid = (Thread_id)*_argument_0; - - return _source->on_thread_kill(&a, (Thread_kill::Result*)_result_0) == Event::EVENT_PROCESSED ? - true : false; - } - - case THREAD_WAKE: - { - Thread_wake::Argument a; - a.tid = (Thread_id)*_argument_0; - - return _source->on_thread_wake(&a, (Thread_wake::Result*)_result_0) == Event::EVENT_PROCESSED ? - true : false; - } - - case THREAD_SLEEP: - { - return _source->on_thread_sleep() == Event::EVENT_PROCESSED ? - true : false; - } - - case IPC_SERVE: - { - return _source->can_reply_and_get_next_request(*_argument_0, _argument_0); - } - - case IPC_REQUEST: - { - return _source->can_get_reply(thread_factory()->get(*_argument_0), - *_argument_1, - _argument_0); - } - - case TLB_LOAD: - { - using namespace Paging; - - Virtual_page vp((addr_t) *_argument_1, - (Protection_id)*_argument_2); - - Physical_page pp((addr_t) *_argument_0, - (Physical_page::size_t) *_argument_3, - (Physical_page::Permissions)*_argument_4); - - Paging::Resolution r(&vp, &pp); - _source->on_tlb_load(&r); - return true; - } - - case IRQ_ALLOCATE: - { - return _source->irq_allocate((Irq_id)*_argument_0, (int *)_argument_0); - } - - case IRQ_FREE: - { - return _source->irq_free((Irq_id)*_argument_0, (int *)_argument_0); - } - - case IRQ_WAIT: - { - return _source->irq_wait(); - } - - case THREAD_PAGER: - { - _source->on_thread_pager(*_argument_0, *_argument_1); - return true; - } - - case THREAD_YIELD: - { - _source->yield(); - return true; - } - - case TLB_FLUSH: - { - using namespace Paging; - - Virtual_page vp((addr_t) *_argument_1, - (Protection_id)*_argument_0); - _source->on_tlb_flush(&vp, (unsigned)*_argument_2); - return true; - } - - case PRINT_INFO: - { - Thread* t; - if((Thread_id)*_argument_0) { - t=thread_factory()->get((Thread_id)*_argument_0); - } else { - t=thread_factory()->get(_source->tid); - } - if(!t) { return true; } - t->print_state(); - return true; - } - - default: - { - _unblock__warning__unknown_id(); - return false; - } - } -} - - diff --git a/base-mb/src/kernel/generic/include/exception.h b/base-mb/src/kernel/generic/include/exception.h deleted file mode 100755 index ab8cc7d12..000000000 --- a/base-mb/src/kernel/generic/include/exception.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * \brief Handling of concrete set of hardware-exceptions - * \author Martin stein - * \date 2010-06-23 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SRC__CORE__KERNEL__INCLUDE__EXCEPTION_H_ -#define _SRC__CORE__KERNEL__INCLUDE__EXCEPTION_H_ - -#include - -#include "scheduler.h" - -using namespace Genode; - - -/** - * Exception metadata structure - */ -struct Exception -{ - uint32_t cause; - uint32_t status; - uint32_t address; -}; - - -/** - * Virtual class that qualifies heirs be exception handler - */ -class Exception_handler -{ - protected: - - /** - * Enable all hw exceptions and let us be the handler for them - */ - void _alloc_exceptions(); - - /** - * Relieve us of handling any exception - * - * Dissable all exceptions if we are the current handler. - */ - void _free_exceptions(); - - public: - - /** - * Destructor - */ - virtual ~Exception_handler() {} - - /** - * Handle occured exception - * - * \param type type of exception - see xmb/include/config.h - */ - virtual void handle_exception(uint32_t type, uint32_t status, uint32_t address) = 0; -}; - - -/** - * C exception handling, after assembler entry - */ -void handle_exception(); - - -/** - * Clear exception if one is in progress - */ -void _exception_clear(); - - -#endif /* _SRC__CORE__KERNEL__INCLUDE__EXCEPTION_H_ */ diff --git a/base-mb/src/kernel/generic/include/interrupt.h b/base-mb/src/kernel/generic/include/interrupt.h deleted file mode 100755 index ca8077fa7..000000000 --- a/base-mb/src/kernel/generic/include/interrupt.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * \brief Common lowlevel interrupt handling - * \author Martin stein - * \date 2010-06-23 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SRC__CORE__KERNEL__INCLUDE__INTERRUPT_H_ -#define _SRC__CORE__KERNEL__INCLUDE__INTERRUPT_H_ - -/* OS includes */ -#include - -/* kernel includes */ -#include - -/* platform includes */ -#include - - -using namespace Genode; - - -/** - * Interrupt handling level 2, calls handler if possible or nop and return - */ -void handle_interrupt(); - - -/** - * Globally enable all interrupts - * - * \param controller interrupt controller that shall be used by handlings - */ -void enable_interrupts(Irq_controller* const controller); - - -/** - * Globally disable all irq's - */ -void disable_interrupt(); - - -#endif /* _SRC__CORE__KERNEL__INCLUDE__INTERRUPT_H_ */ diff --git a/base-mb/src/kernel/generic/include/thread.h b/base-mb/src/kernel/generic/include/thread.h deleted file mode 100755 index 1c2e3b87f..000000000 --- a/base-mb/src/kernel/generic/include/thread.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - * \brief Declaration of physical backend to userland thread - * \author Martin stein - * \date 2010-06-24 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__GENERIC__INCLUDE__THREAD_H_ -#define _KERNEL__GENERIC__INCLUDE__THREAD_H_ - - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -extern bool irq_occured[Kernel::MAX_IRQ_ID]; - -namespace Kernel { - - enum { THREAD__VERBOSE = 0, - THREAD__WARNING = 1 }; - - enum { ROOTTASK_PAGE_SIZE = Paging::Physical_page::_4KB }; - - - class Thread : public Scheduler::Client, - public Instruction_tlb_miss::Listener, - public Data_tlb_miss::Listener, - public Syscall::Source, - public Paging::Request::Source - { - public: - - typedef Tlb::Virtual_page Virtual_page; - typedef Tlb::Physical_page Physical_page; - typedef Tlb::Resolution Resolution; - typedef Thread_create::Argument Constructor_argument; - typedef Kernel::Thread_id Thread_id; - typedef Kernel::Protection_id Protection_id; - - void* operator new(size_t, void *addr) { return addr; } - - enum State { INVALID = 0, - READY, - WAIT, - WAIT_IPC_REPLY, - WAIT_IPC_REQUEST }; - - enum Print_mode { BRIEF_STATE, DETAILED_STATE }; - - private: - - Platform_thread _platform_thread; - Thread_id _id; - bool _is_privileged; - Thread_id _pager_tid; - Thread_id _substitute_tid; - State _state; - Paging::Request _paging_request; - bool _waits_for_irq; - bool _any_irq_pending; - bool _irq_pending[Kernel::MAX_IRQ_ID]; - - void _unblock() { _platform_thread.unblock(); } - - void _invalidate() { _state = INVALID; } - - Protection_id _protection_id() { return _platform_thread.protection_id(); } - - addr_t _instruction_pointer() { return _platform_thread.instruction_pointer(); } - - void _sleep() { scheduler()->remove(this); } - - void _yield_after_atomic_operation() - { - _platform_thread.yield_after_atomic_operation(); - } - - inline void _clear_pending_irqs(); - - public: - - inline bool irq_allocate(Irq_id i, int * const result); - inline bool irq_free(Irq_id i, int * const result); - inline bool irq_wait(); - inline void handle(Irq_id const & i); - - void pager_tid(Thread_id ptid){ _pager_tid=ptid; } - - /** - * Constructor - */ - Thread(Constructor_argument* a); - - /** - * Constructing invalid thread without parameters - */ - Thread(); - - /** - * Shows several infos about thread depending on print mode argument - */ - void print_state(); - - - /********************** - ** Simple Accessors ** - **********************/ - - Thread_id thread_id() { return _id; } - bool valid() { return _state != INVALID; } - - - /********************************* - ** Scheduler::Client interface ** - *********************************/ - - int label() { return (int)_id; } - - void _on_instruction_tlb_miss(Virtual_page* accessed_page); - - void _on_data_tlb_miss(Virtual_page* accessed_page, bool write_access); - - void yield() { scheduler()->skip_next_time(this); } - - protected: - - void ipc_sleep() { Scheduler::Client::_sleep(); } - - void ipc_wake() { Scheduler::Client::_wake(); } - - bool _preemptable() - { - if (!platform()->is_atomic_operation((void*)_instruction_pointer())) - return true; - - _yield_after_atomic_operation(); - return false; - } - - bool _permission_to_do_print_char() { return true; } - - bool _permission_to_do_thread_create() - { - return _is_privileged; - } - - bool _permission_to_do_thread_kill() - { - return _is_privileged; - } - -// bool _print_info(){ -// _platform_thread.exec_context()->print_content(2); -// return true; -// } - - bool _permission_to_do_tlb_load(){ return _is_privileged; } - - bool _permission_to_do_tlb_flush(){ return _is_privileged; } - - bool _permission_to_do_thread_pager(Thread_id target_tid) - { - return _is_privileged; - } - - bool _permission_to_do_thread_wake(Thread* target) - { - return _is_privileged - || target->_protection_id()==_protection_id(); - } - - Context *_context() - { - return _platform_thread.unblocked_exec_context(); - } - - - enum { CONSTRUCTOR__VERBOSE__SUCCESS = THREAD__VERBOSE }; - - void _on_data_tlb_miss__warning__invalid_pager_tid(Thread_id pager_tid) - { - if (!THREAD__WARNING) return; - - printf("Warning in Kernel::Thread::_on_data_tlb_miss, invalid pager_tid=%i\n", pager_tid); - } - - void _constructor__verbose__success() - { - if (!CONSTRUCTOR__VERBOSE__SUCCESS) return; - - printf("Kernel::Thread::Thread, new valid thread created, printing state\n"); - Verbose::indent(2); - printf("_utcb=0x%8X, _platform_thread(", (uint32_t)utcb()); - _platform_thread.print_state(); - printf(")\n"); - } - - void _on_instruction_tlb_miss__verbose__roottask_resolution(addr_t v) - { - if (!THREAD__VERBOSE) return; - - printf("Kernel::Thread::_on_instruction_tlb_miss, resoluted 0x%p identically\n", - (void*)v); - } - - void _on_data_tlb_miss__verbose__roottask_resolution(addr_t v) - { - if (!THREAD__VERBOSE) return; - - printf("Kernel::Thread::_on_data_tlb_miss, resoluted 0x%p identically\n", - (void*)v); - } - }; - - - class Thread_factory - { - enum { THREAD_ID_RANGE = 1 << (Platform::BYTE_WIDTH*sizeof(Thread_id)) }; - - Thread thread[THREAD_ID_RANGE]; - bool _steady[THREAD_ID_RANGE]; - - public: - - enum Error { - NO_ERROR = 0, - CANT_KILL_STEADY_THREAD = -1 - }; - - typedef Thread::Constructor_argument Create_argument; - - Thread *create(Create_argument *a, bool steady) - { - if(thread[a->tid].valid()) { return 0; } - _steady[a->tid] = steady; - return new(&thread[a->tid])Thread(a); - } - - Error kill(Thread_id tid) - { - if(_steady[tid]) return CANT_KILL_STEADY_THREAD; - thread[tid].~Thread(); - new (&thread[tid]) Thread(); - return NO_ERROR; - } - - Thread *get(Thread_id id) - { - return thread[id].valid() ? &thread[id] : (Thread*)0; - } - }; - - - Thread_factory* thread_factory(); -} - - -void Kernel::Thread::handle(Irq_id const & i) -{ - if(i>sizeof(_irq_pending)/sizeof(_irq_pending[0])){ - printf("Kernel::Thread::handles(Irq_id i): Error"); - halt(); - } - _irq_pending[i]=true; - _any_irq_pending = true; - - if(!_waits_for_irq) { return; } - - Scheduler::Client::_wake(); - _clear_pending_irqs(); - _waits_for_irq=false; - return; -} - - -bool Kernel::Thread::irq_allocate(Irq_id i, int * const result) -{ - if(!_is_privileged){ - *result = -1; - return true; - }; - - if(i == platform()->timer()->irq_id()){ - *result = -3; - return true; - }; - - if(irq_allocator()->allocate(this, i)){ - *result = -2; - return true; - }; - - *result = 0; - return true; -} - - -bool Kernel::Thread::irq_free(Irq_id i, int * const result) -{ - if(!_is_privileged){ - *result = -1; - return true; - }; - - if(irq_allocator()->free(this, i)){ - *result = -2; - return true; - }; - - *result = 0; - return true; -} - - -bool Kernel::Thread::irq_wait() -{ - if(!_any_irq_pending){ - _waits_for_irq = true; - Scheduler::Client::_sleep(); - return true; - } - _clear_pending_irqs(); - return true; -} - - -void Kernel::Thread::_clear_pending_irqs() -{ - for(unsigned int i=0; iack_irq(i); - _irq_pending[i]=false; - } - } - _any_irq_pending=false; -} - -#endif /* _KERNEL__GENERIC__INCLUDE__THREAD_H_ */ - - - - - - - diff --git a/base-mb/src/kernel/generic/kernel.cc b/base-mb/src/kernel/generic/kernel.cc deleted file mode 100755 index 7f0a2029c..000000000 --- a/base-mb/src/kernel/generic/kernel.cc +++ /dev/null @@ -1,189 +0,0 @@ -/* - * \brief Kernel initialization - * \author Martin Stein - * \date 2010-07-22 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include "include/thread.h" -#include -#include -#include -#include -#include -#include -#include - -using namespace Cpu; -using namespace Kernel; - -enum { KERNEL__VERBOSE = 0, - KERNEL__WARNING = 1, - KERNEL__ERROR = 1 }; - - -/* Can be defined via compiler options */ -extern "C" void ROOTTASK_ENTRY(); - -extern Kernel::Exec_context* _userland_context; -extern Utcb* _main_utcb_addr; - -extern int _exit_kernel; - - -Kernel::Thread_factory* Kernel::thread_factory() -{ - static Thread_factory _tf; - return &_tf; -} - - -namespace Kernel { - - static Utcb _roottask_utcb, _idle_utcb; - - void _roottask_thread__verbose__creation(addr_t vip, addr_t vsp, Utcb* vutcb) - { - if (!KERNEL__VERBOSE) return; - printf("Kernel::roottask_thread, roottask thread created, " - "printing constraints\n"); - printf(" vip=0x%8X, vsp=0x%8X, vutcb=0x%8X\n", - (uint32_t)vip, (uint32_t)vsp, (uint32_t)vutcb); - } - - - void idle() - { - while(1); - } - - - Thread *idle_thread() - { - enum{ - IDLE_STACK_WORD_SIZE=32, - IDLE_TID=1, - }; - - static word_t _it_stack[IDLE_STACK_WORD_SIZE]; - static Thread *_it = thread_factory()->get(IDLE_TID); - - if (!_it) { - - Thread_factory::Create_argument itca; - - itca.tid = (Thread_id)IDLE_TID; - itca.pid = (Protection_id)Roottask::PROTECTION_ID; - itca.utcb = &_idle_utcb; - itca.pager_tid = INVALID_THREAD_ID; - itca.vsp = (addr_t)&LAST_ARRAY_ELEM(_it_stack); - itca.vip = (addr_t)&idle; - itca.is_privileged = true; - - _it = thread_factory()->create(&itca, true); - } - return _it; - } - - - Thread *roottask_thread() - { - static word_t _rt_stack[Roottask::MAIN_STACK_SIZE/WORD_SIZE]; - static Thread *_rt = thread_factory()->get(Roottask::MAIN_THREAD_ID); - - if (!_rt) { - - Thread_factory::Create_argument rtca; - - rtca.tid = (Thread_id)Roottask::MAIN_THREAD_ID; - rtca.pid = (Protection_id)Roottask::PROTECTION_ID; - rtca.utcb = &_roottask_utcb; - rtca.pager_tid = INVALID_THREAD_ID; - rtca.vsp = (addr_t)&LAST_ARRAY_ELEM(_rt_stack); - rtca.vip = (addr_t)&ROOTTASK_ENTRY; - rtca.is_privileged = true; - _main_utcb_addr = rtca.utcb; - - _rt = thread_factory()->create(&rtca, false); - if (_rt) - _roottask_thread__verbose__creation( - rtca.vip, rtca.vsp, rtca.utcb); - } - return _rt; - } -} - - -Platform *Kernel::platform() { static Platform _p; return &_p; } - - -Scheduler *Kernel::scheduler() -{ - static bool _init_scheduler = false; - static Scheduler _s = Scheduler(platform(), - platform()->timer(), - idle_thread()); - if(_init_scheduler){ return &_s; } - _s.add(roottask_thread()); - _init_scheduler = true; - return &_s; -} - - -Tlb *Kernel::tlb() { return platform()->tlb(); } - - -Irq_controller * const Kernel::irq_controller() -{ - return platform()->irq_controller(); -} - - -Irq_allocator * const Kernel::irq_allocator() -{ - static Irq_allocator _ia = - Irq_allocator(platform()->irq_controller()); - return &_ia; -} - - -unsigned Kernel::word_width() { return Platform::WORD_WIDTH; } - - -void Kernel::halt() { platform()->halt(); } - - -Kernel::Kernel_entry *Kernel::kernel_entry_event() -{ - static Kernel_entry _ke; - return &_ke; -} - - -Kernel::Kernel_exit *Kernel::kernel_exit_event() -{ - static Kernel_exit _kx; - return &_kx; -} - - -/** - * Kernel main routine, gets called by crt0_kernel.s - */ -extern "C" void _kernel() -{ - kernel_entry_event()->on_occurence(); - - scheduler()->run(); - - kernel_exit_event()->on_occurence(); -} - diff --git a/base-mb/src/kernel/generic/scheduler.cc b/base-mb/src/kernel/generic/scheduler.cc deleted file mode 100755 index d8f0c7994..000000000 --- a/base-mb/src/kernel/generic/scheduler.cc +++ /dev/null @@ -1,130 +0,0 @@ -/* - * \brief Implementation of a round robin scheduler - * \author Martin stein - * \date 2010-06-22 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Generic includes */ -#include -#include -#include -#include "generic/verbose.h" - -/* Platform includes */ -#include - -using namespace Kernel; - -extern unsigned int _current_context_label; - - -Scheduler::Scheduler(Ressource * const r, Scheduling_timer * const t, - Client * const idle_client) -: - _timer(t), - _quota_per_round_per_client(_ms_to_quota(MS_PER_ROUND_PER_CLIENT)), - _ressource(r), - _current_client(0), - _idle_client(idle_client) -{ - _idle_client->_scheduler=this; -} - - -void Scheduler::_schedule() -{ - _last_client=_current_client; - if (_last_client && _last_client != _idle_client) { - _client_queue.enqueue(_last_client); - } - - _current_client=_client_queue.dequeue(); - if (!_current_client){ - _current_client=_idle_client; - } -} - - -Kernel::Scheduler::Client::~Client() -{ - if (_scheduler) - _scheduler->remove(this); -} - - -void Scheduler::run() -{ - if (!_current_client){ - _schedule(); - if (!_current_client) - _run__error__no_ready_client(); - } - - _new_clients = false; - Client* first_client = _current_client; - Client::Context *c = 0; - - while (1) { - - _run__trace__client_checks(); - c = _current_client->_schedulable_context(); - - if (c && _current_client) { - if (_current_client->_quota) { - break; - } else { - _current_client->_earn_quota(_quota_per_round_per_client); - _new_clients = true; - } - } - _schedule(); - - if (_new_clients) { - first_client = _current_client; - _new_clients = false; - } - else if (_current_client == first_client){ - _prep_idle_round(); - } - } - - _current_context_label = (unsigned int)_current_client->label(); - _timer->track_time(_current_client->_quota, this); - _ressource->lock(c); - _run__verbose__success(); -} - - -void Scheduler::add(Client *c) -{ - if (!c) { return; } - if (c == _idle_client) { return; } - if (c->_scheduler == this) { return; } - if (c->_scheduler) { c->_scheduler->remove(c); } - - c->_quota = _quota_per_round_per_client; - c->_scheduler = this; - _client_queue.enqueue(c); - _new_clients = true; -} - - -void Scheduler::remove(Client* c) -{ - if (!c) { return; } - if (c->_scheduler != this) { return; } - if (c == _idle_client) { return; } - - if (_current_client == c) { _current_client = 0; } - else _client_queue.remove(c); - c->_scheduler = 0; - _new_clients = true; -} - diff --git a/base-mb/src/kernel/generic/syscall_events.cc b/base-mb/src/kernel/generic/syscall_events.cc deleted file mode 100755 index f32874995..000000000 --- a/base-mb/src/kernel/generic/syscall_events.cc +++ /dev/null @@ -1,187 +0,0 @@ -/* - * \brief Syscall handling implementation - * \author Martin Stein - * \date 2011-02-22 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include "include/thread.h" -#include -#include - -using namespace Kernel; - -namespace Kernel{ - extern Thread* idle_thread(); -} - - -Print_char::On_occurence__result Print_char::on_print_char(char c) -{ - printf("%c", c); - return EVENT_PROCESSED; -} - - -Thread_create::On_occurence__result -Thread_create::on_thread_create(Argument* a, Result* r) -{ - using namespace Thread_create_types; - - if (!_permission_to_do_thread_create()) { - _on_thread_create__warning__failed(); - *r = INSUFFICIENT_PERMISSIONS; - } else { - Thread *t = thread_factory()->create(a, false); - - if (!t) { - _on_thread_create__warning__failed(); - *r=INAPPROPRIATE_THREAD_ID; - } else{ - scheduler()->add(t); - _on_thread_create__verbose__success(t); - *r=SUCCESS; - } - } - return EVENT_PROCESSED; -} - - -Thread_kill::On_occurence__result -Thread_kill::on_thread_kill(Argument *a, Result *r) -{ - using namespace Thread_kill_types; - - if (!_permission_to_do_thread_kill()) { - *r = INSUFFICIENT_PERMISSIONS; - _on_thread_kill__warning__failed(); - } else { - Thread_factory *tf = thread_factory(); - - if (tf->get(a->tid) == this) { - *r = SUICIDAL; - _on_thread_kill__warning__failed(); - } else { - if(tf->kill(a->tid)){ - printf("Warning in Thread_kill::on_thread_kill: Can't kill thread\n"); - }; - *r=SUCCESS; - _on_thread_kill__verbose__success(a->tid); - } - } - return EVENT_PROCESSED; -} - - -Thread_sleep::On_occurence__result Thread_sleep::on_thread_sleep() -{ - Scheduler *s = scheduler(); - - s->remove(s->current_client()); - _on_thread_sleep__verbose__success(); - - return EVENT_PROCESSED; -} - - -Thread_wake::On_occurence__result -Thread_wake::on_thread_wake(Argument *a, Result *r) -{ - using namespace Thread_wake_types; - Thread* t = thread_factory()->get(a->tid); - - if (!t) { - *r = INAPPROPRIATE_THREAD_ID; - _on_thread_wake__warning__failed(); - } else{ - if (!_permission_to_do_thread_wake(t)) { - *r = INSUFFICIENT_PERMISSIONS; - _on_thread_wake__warning__failed(); - } else { - scheduler()->add(t); - *r = SUCCESS; - _on_thread_wake__verbose__success(a->tid); - } - } - return EVENT_PROCESSED; -} - - -//void Print_info::on_print_info(){ -// _print_info(); -//} - - -void Tlb_flush::on_tlb_flush(Paging::Virtual_page* first_page, unsigned size) -{ - if (!_permission_to_do_tlb_flush()) return; - - tlb()->flush(first_page, size); -} - - -void Tlb_load::on_tlb_load(Paging::Resolution* r) -{ - if (!_permission_to_do_tlb_load()) return; - - tlb()->add(r); -} - - -void Thread_pager::on_thread_pager(Thread_id target_tid, Thread_id pager_tid) -{ - if (!_permission_to_do_thread_pager(target_tid)) { - printf("Warning in Kernel::Thread_pager::on_thread_pager, " - "insufficient permissions\n"); - return; - } - - Thread *target = thread_factory()->get(target_tid); - if (target && target != idle_thread()) { - target->pager_tid(pager_tid); - } else { - printf("Warning in Kernel::Thread_pager::on_thread_pager, " - "invalid target thread id\n"); - } -} - - -void Thread_wake::_on_thread_wake__verbose__success(Thread_id tid) -{ - if (!SYSCALL_EVENT__VERBOSE) return; - - printf("Kernel::Thread_wake::on_thread_wake, success, tid=%i\n", tid); -} - - -void Thread_sleep::_on_thread_sleep__verbose__success() -{ - if (!SYSCALL_EVENT__VERBOSE) return; - - printf("Kernel::Thread_sleep::on_thread_sleep, success\n"); -} - - -void Thread_kill::_on_thread_kill__verbose__success(Thread_id tid) -{ - if (!SYSCALL_EVENT__VERBOSE) return; - - printf("Kernel::Thread_kill::on_thread_kill, success, tid=%i\n", tid); -} - - -void Thread_create::_on_thread_create__verbose__success(Thread* t) -{ - if (!SYSCALL_EVENT__VERBOSE) return; - - printf("Kernel::Thread_create::on_thread_create, success, printing constraints\n"); - t->print_state(); -} - diff --git a/base-mb/src/kernel/generic/thread.cc b/base-mb/src/kernel/generic/thread.cc deleted file mode 100755 index 04dea5fc8..000000000 --- a/base-mb/src/kernel/generic/thread.cc +++ /dev/null @@ -1,117 +0,0 @@ -/* - * \brief Kernels Userland Thread representation - * \author Martin stein - * \date 2010-06-24 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include "include/thread.h" - - -using namespace Kernel; - -extern bool trace_me; - -Thread::Thread(Constructor_argument* a) -: - Syscall::Source(a->utcb, a->tid), - _platform_thread(a->vip, a->vsp, a->pid, this), - _id(a->tid), - _is_privileged(a->is_privileged), - _pager_tid(a->pager_tid), - _substitute_tid(INVALID_THREAD_ID), - _state(READY), - _waits_for_irq(false), - _any_irq_pending(false) -{ - _platform_thread.bootstrap_argument_0( (word_t)utcb() ); - - Instruction_tlb_miss::Listener::_event(_platform_thread.exception()->instruction_tlb_miss()); - Data_tlb_miss::Listener::_event(_platform_thread.exception()->data_tlb_miss()); - - _constructor__verbose__success(); -} - - -Thread::Thread() : Syscall::Source(0, 0) -{ - _invalidate(); -} - - -void Thread::print_state() -{ - printf("Thread ID: %i, pager: %i, substitute: %i, privileged: %c, state: %i\n" - "Context:\n", - _id, _pager_tid, _substitute_tid, _is_privileged ? 'y' : 'n', - _state); - _platform_thread.print_state(); -} - - -void Thread::_on_data_tlb_miss(Virtual_page *accessed_page, bool write_access) -{ - typedef Kernel::Data_tlb_miss::Listener Listener; - using namespace Paging; - - if (_protection_id()==Roottask::PROTECTION_ID & !_pager_tid) { - - Listener::_resolve_identically((Physical_page::size_t)ROOTTASK_PAGE_SIZE, - Physical_page::RW); - _on_data_tlb_miss__verbose__roottask_resolution(accessed_page->address()); - - } else { - Ipc::Participates_dialog * pager = thread_factory()->get(_pager_tid); - if (!pager) { - _on_data_tlb_miss__warning__invalid_pager_tid(_pager_tid); - return; - } else { - Request::Source s = {_id, _instruction_pointer() }; - Request::Access a = write_access ? Request::RW : Request::R; - - _paging_request = Request(accessed_page, s, a); - _send_message(pager, (void*)&_paging_request, - sizeof(_paging_request)); - - _sleep(); - _unblock(); - } - } -} - - -void Thread::_on_instruction_tlb_miss(Virtual_page *accessed_page) -{ - typedef Kernel::Instruction_tlb_miss::Listener Listener; - using namespace Paging; - - if (_protection_id() == Roottask::PROTECTION_ID & !_pager_tid) { - - Listener::_resolve_identically((Physical_page::size_t)ROOTTASK_PAGE_SIZE, - Physical_page::RX); - - _on_instruction_tlb_miss__verbose__roottask_resolution(accessed_page->address()); - - } else { - Ipc::Participates_dialog *pager = thread_factory()->get(_pager_tid); - if (!pager) { - _on_data_tlb_miss__warning__invalid_pager_tid(_pager_tid); - return; - } else{ - Paging::Request::Source s = {_id, _instruction_pointer()}; - _paging_request = Request(accessed_page, s, Request::RX); - - _send_message(pager, (void*)&_paging_request, - sizeof(_paging_request)); - _sleep(); - _unblock(); - } - } -} - diff --git a/base-mb/src/kernel/include/generic/blocking.h b/base-mb/src/kernel/include/generic/blocking.h deleted file mode 100755 index 49d1eb2e9..000000000 --- a/base-mb/src/kernel/include/generic/blocking.h +++ /dev/null @@ -1,417 +0,0 @@ -/* - * \brief Generic userland execution blockings - * \author Martin Stein - * \date 2010-10-27 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__GENERIC__BLOCKING_H_ -#define _KERNEL__INCLUDE__GENERIC__BLOCKING_H_ - -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - - enum { DATA_TLB_MISS__VERBOSE = 0, - INSTRUCTION_TLB_MISS__VERBOSE = 0 }; - - - struct Blocking - { - virtual bool unblock() = 0; - virtual ~Blocking() { } - }; - - - class Kernel_exit; - - - /** - * This event is triggered everytime kernels main - * routine is done and returns - */ - Kernel_exit* kernel_exit_event(); - - - /** - * Event occuring when kernel exits execution - */ - struct Kernel_exit : public Event - { - class Listener : public Event::Listener - { - Kernel_exit* _event; - - protected: - - Listener() : _event(kernel_exit_event()) { _event->add(this); } - - virtual ~Listener(){} - - virtual void _on_kernel_exit() = 0; - void _on_event() { _on_kernel_exit(); } - }; - - void add(Listener *l) { Event::_add(l); } - - On_occurence__result on_occurence() - { - _populate(); - return EVENT_PROCESSED; - } - }; - - - class Kernel_entry; - - /** - * This Event triggers everytime kernels main - * routine starts execution - */ - Kernel_entry* kernel_entry_event(); - - /** - * Event occuring when kernel starts to be executed - */ - struct Kernel_entry : public Event - { - class Listener : public Event::Listener - { - Kernel_entry* _event; - - protected: - - Listener() : _event(kernel_entry_event()) { _event->add(this); } - - virtual ~Listener(){} - - virtual void _on_kernel_entry() = 0; - void _on_event() { _on_kernel_entry(); } - }; - - void add(Listener *l) { Event::_add(l); } - - On_occurence__result on_occurence() - { - _populate(); - return EVENT_PROCESSED; - } - }; - - - class Instruction_tlb_miss : public Event - { - friend class Exception; - friend class Listener; - - void _add(Listener *l) { Event::_add(l); } - - public: - - typedef Tlb::Virtual_page Virtual_page; - typedef Tlb::Physical_page Physical_page; - typedef Tlb::Resolution Resolution; - - class Listener : public Event::Listener - { - typedef Instruction_tlb_miss::Resolution Resolution; - - Resolution* _resolution; - - protected: - - typedef Instruction_tlb_miss::Virtual_page Virtual_page; - typedef Instruction_tlb_miss::Physical_page Physical_page; - - virtual ~Listener(){} - - void _resolve_identically(Physical_page::size_t s, - Physical_page::Permissions p); - - virtual void _on_instruction_tlb_miss(Virtual_page* accessed_page) = 0; - - void _on_event(); - - void _event(Instruction_tlb_miss* itm) - { - itm->_add(this); - _resolution = itm->missing_resolution(); - } - - /** - * Write read access for listeners - */ - Physical_page* physical_page() - { - return &_resolution->physical_page; - } - }; - - Resolution *missing_resolution() { return &_missing_resolution; } - - protected: - - Resolution _missing_resolution; - - void _on_occurence__error__virtual_page_invalid() - { - printf("Error in Kernel::Instruction_tlb_miss::on_occurence, " - "virtual page invalid, halt\n"); - halt(); - } - - void _on_occerence__verbose__waiting_for_resolution() - { - if (!INSTRUCTION_TLB_MISS__VERBOSE) return; - - printf("Kernel::Instruction_tlb_miss::on_occurence, " - "leaving unresoluted virtual page, address=0x%p, pid=%i\n", - (void*)_missing_resolution.virtual_page.address(), - (int)_missing_resolution.virtual_page.protection_id() ); -} - - public: - - On_occurence__result on_occurence(); - }; - - - class Data_tlb_miss : public Event - { - friend class Exception; - friend class Listener; - - void _add(Listener* l) {Event::_add(l); } - - public: - - typedef Tlb::Virtual_page Virtual_page; - typedef Tlb::Physical_page Physical_page; - typedef Tlb::Resolution Resolution; - - class Listener : public Event::Listener - { - typedef Data_tlb_miss::Resolution Resolution; - - Resolution* _resolution; - - protected: - - typedef Data_tlb_miss::Virtual_page Virtual_page; - typedef Data_tlb_miss::Physical_page Physical_page; - - virtual ~Listener(){} - - void _resolve_identically(Physical_page::size_t s, - Physical_page::Permissions p); - - virtual void _on_data_tlb_miss(Virtual_page* accessed_page, - bool write_access) = 0; - - void _on_event(); - - void _event(Data_tlb_miss* dtm) - { - dtm->_add(this); - _resolution = dtm->missing_resolution(); - } - - /** - * Write read access for listeners - */ - Physical_page* physical_page() - { - return &_resolution->physical_page; - } - }; - - Resolution* missing_resolution() { return &_missing_resolution; } - - protected: - - Resolution _missing_resolution; - - enum{ ON_OCCURENCE__ERROR = 1 }; - - void _on_occurence__error__virtual_page_invalid() - { - printf("Error in Kernel::Data_tlb_miss::on_occurence, " - "virtual page invalid, halt\n"); - halt(); - } - - void _on_occurence__verbose__waiting_for_resolution() - { - if (!DATA_TLB_MISS__VERBOSE) return; - - printf("Kernel::Data_tlb_miss::on_occurence, " - "leaving unresoluted virtual page, address=0x%p, pid=%i)\n", - (void*)_missing_resolution.virtual_page.address(), - (int)_missing_resolution.virtual_page.protection_id() ); -} - - public: - - On_occurence__result on_occurence(); - }; - - - class Exception : public Instruction_tlb_miss, - public Data_tlb_miss, - public Blocking - { - typedef Kernel::Tlb::Virtual_page Virtual_page; - - protected: - - Exception_id _id; - - virtual Protection_id protection_id()=0; - virtual addr_t address()=0; - virtual bool attempted_write_access()=0; - - public: - - enum { UNBLOCK__WARNING = 1 }; - - enum { UNBLOCK__RETURN__SUCCESS = 0, - UNBLOCK__RETURN__FAILED= - 1}; - - bool unblock(); - - Instruction_tlb_miss *instruction_tlb_miss() { return this; } - - Data_tlb_miss *data_tlb_miss() { return this; } - }; - - - class Irq : public Blocking - { - public: - - enum{ UNBLOCK__WARNING=1 }; - - enum { UNBLOCK__RETURN__SUCCESS = 0, - UNBLOCK__RETURN__FAILED = -1}; - - bool unblock(); - - protected: - - Irq_id _id; - - void _unblock__error__release_irq_failed() - { - printf("Error in Kernel::Irq::unblock, failed to release IRQ, halt\n"); - halt(); - } - - void _unblock__warning__unknown_id() - { - if (!UNBLOCK__WARNING) return; - - printf("Warning in Kernel::Irq::unblock, unexpected _id=%i\n", _id); - } - }; - - - class Syscall : public Blocking - { - public: - - class Source; - - private: - - word_t *_argument_0, - *_argument_1, - *_argument_2, - *_argument_3, - *_argument_4, - *_argument_5, - *_argument_6, - *_result_0; - - Source* _source; - - protected: - - Syscall_id _id; - - enum{ UNBLOCK__WARNING = 1 }; - - void _unblock__warning__unknown_id() - { - if (!UNBLOCK__WARNING) return; - - printf("Warning in Kernel::Syscall::unblock, unexpected _id=%i\n", _id); - } - - public: - - class Source : public Print_char, - public Thread_create, - public Thread_sleep, - public Thread_kill, - public Thread_wake, - public Thread_pager, - public Ipc::Participates_dialog, - public Tlb_load, - public Tlb_flush, - public Thread_yield -// public Print_info - { - protected: - - Source(Utcb *utcb, Thread_id i) : - Ipc::Participates_dialog(utcb), - tid(i) - { } - - public: - - Thread_id tid; - - virtual bool irq_allocate(Irq_id i, int * const result)=0; - virtual bool irq_free(Irq_id i, int * const result)=0; - virtual bool irq_wait()=0; - }; - - bool unblock(); - - Syscall(word_t* argument_0, - word_t* argument_1, - word_t* argument_2, - word_t* argument_3, - word_t* argument_4, - word_t* argument_5, - word_t* argument_6, - word_t* result_0, - Source* s) - : - _argument_0(argument_0), - _argument_1(argument_1), - _argument_2(argument_2), - _argument_3(argument_3), - _argument_4(argument_4), - _argument_5(argument_5), - _argument_6(argument_6), - _result_0(result_0), - _source(s) - { } - }; -} - -#endif /* _KERNEL__INCLUDE__GENERIC__BLOCKING_H_ */ diff --git a/base-mb/src/kernel/include/generic/event.h b/base-mb/src/kernel/include/generic/event.h deleted file mode 100755 index d054f69cb..000000000 --- a/base-mb/src/kernel/include/generic/event.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * \brief Event throwers and listeners - * \author Martin Stein - * \date 2010-10-27 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__GENERIC__EVENT_H_ -#define _KERNEL__INCLUDE__GENERIC__EVENT_H_ - -#include -#include - -namespace Kernel { - - class Event - { - public: - - class Listener; - typedef Kernel::Queue Listener_queue; - - enum On_occurence__result{ EVENT_PROCESSED, EVENT_PENDING }; - - private: - - Listener_queue _listeners; - Listener *_first; - - protected: - - void _populate() - { - if (!_first) { - _first = _listeners.dequeue(); - if (!_first) - return; - } - Listener *i = _first; - - while (1) { - i->_on_event(); - _listeners.enqueue(i); - i = _listeners.dequeue(); - if (i == _first) break; - } - } - - void _add(Listener* l) { _listeners.enqueue(l); } - - void _remove(Listener* l) { _listeners.remove(l); } - - void print_listeners() - { - printf("print_listeners\n"); - - if (_listeners.empty()) { - printf(" empty\n"); - return; } - - Listener *current; - Listener *first; - first = _listeners.head(); - current = _listeners.dequeue(); - printf(" "); - - while (1) { - printf("0x%p", current); - _listeners.enqueue(current); - if (first == _listeners.head()) - break; - current = _listeners.dequeue(); - printf(" → "); } - - printf("\n"); - } - - public: - - virtual ~Event() { } - - class Listener : public Listener_queue::Item - { - friend class Event; - - protected: - - virtual void _on_event() = 0; - - public: - - virtual ~Listener(){} - }; - }; -} - -#endif /*_KERNEL__INCLUDE__GENERIC__EVENT_H_*/ diff --git a/base-mb/src/kernel/include/generic/ipc.h b/base-mb/src/kernel/include/generic/ipc.h deleted file mode 100755 index 241886c64..000000000 --- a/base-mb/src/kernel/include/generic/ipc.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * \brief IPC Framework inside kernel - * \author Martin Stein - * \date 2011-02-22 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__GENERIC__IPC_H_ -#define _KERNEL__INCLUDE__GENERIC__IPC_H_ - -#include - - -namespace Kernel { - - enum { IPC__VERBOSE = 0 }; - - namespace Ipc { - - class Participates_dialog; - typedef Kernel::Queue Participant_queue; - - class Participates_dialog : - public Participant_queue::Item - { - typedef Participates_dialog Participant; - - public: - - typedef Kernel::Utcb Utcb; - - inline unsigned message_size() { return _message_size; } - - inline byte_t message(unsigned i) { return _message[i]; } - - inline void print_message(); - - byte_t *_message; - - private: - - Participant_queue _announced_clients; - Participant* _current_client; - Utcb* _utcb; - unsigned _message_size; - bool _waiting_for_reply; - bool _recieved_reply; - - inline void _recieve_message(Participant* sender); - - protected: - - inline void _send_message(Participant* server, - void* message, - unsigned size); - - inline Participates_dialog(Utcb* utcb); - - inline Utcb* utcb() { return _utcb; } - - inline void recieve_reply(Participant* server); - - inline void announce_client(Participant* client); - - virtual ~Participates_dialog() { } - - virtual void ipc_sleep() = 0; - - virtual void ipc_wake() = 0; - - public: - - inline bool can_get_reply(Participant *server, - unsigned request_size, - unsigned *reply_size); - - inline bool can_reply_and_get_next_request(unsigned reply_size, - unsigned* request_size); - - protected: - - inline void _can_get_reply__error__invalid_server(); - - inline void _recieve_message__error__invalid_message_size(); - - inline void _can_reply_and_get_request__verbose__replied_to_request(); - - inline void _can_reply_and_get_request__verbose__recieved_request(); - - inline void _can_reply_and_get_request__verbose__waiting_for_request(); - - inline void _send_message__verbose__success(Participant* server); - - inline void _can_get_reply__verbose__waiting_for_reply(Participant* server); - - inline void _can_get_reply__verbose__recieved_reply(Participant* server); - }; - } -} - - -Kernel::Ipc::Participates_dialog::Participates_dialog(Utcb* utcb) : - _current_client(0), - _utcb(utcb), - _waiting_for_reply(false), - _recieved_reply(false) -{ } - - -void Kernel::Ipc::Participates_dialog::print_message() -{ - printf(" _message=0x%p\n", _message); - - for (unsigned current_byte=0;;){ - printf(" offset 0x%2X: 0x%p -> 0x", - current_byte, &_message[current_byte]); - - printf("%2X", _message[current_byte]); - if (++current_byte>=_message_size) break; - - printf("%2X", _message[current_byte]); - if (++current_byte>=_message_size) break; - - printf("%2X", _message[current_byte]); - if (++current_byte>=_message_size) break; - - printf("%2X", _message[current_byte]); - printf("\n"); - if (++current_byte>=_message_size) break; - } -} - - -void Kernel::Ipc::Participates_dialog::_can_get_reply__error__invalid_server() -{ - printf("Error in Kernel::Ipc::Participates_dialog::can_get_reply, " - "invalid server, halt\n"); - halt(); -} - - -void Kernel::Ipc::Participates_dialog::_recieve_message__error__invalid_message_size() -{ - printf("Error in Kernel::Ipc::Participates_dialog::recieve_message, " - "invalid message size, halt"); - Kernel::halt(); -} - - -void Kernel::Ipc::Participates_dialog::_can_reply_and_get_request__verbose__replied_to_request() -{ - if (!IPC__VERBOSE) return; - - - printf("Kernel::Ipc::Participates_dialog::can_reply_and_get_request, " - "replied to request, this=0x%p, _current_client=0x%p, " - "_message_size=%i\n", - this, _current_client, _message_size); -} - - -void Kernel::Ipc::Participates_dialog::_can_reply_and_get_request__verbose__recieved_request() -{ - if (!IPC__VERBOSE) return; - - printf("Kernel::Ipc::Participates_dialog::can_reply_and_get_request, " - "recieved request, this=0x%p, _current_client=0x%p, " - "_message_size=%i\n", - this, _current_client, _message_size); - - if (IPC__VERBOSE >= 2) - print_message(); -} - - -void Kernel::Ipc::Participates_dialog::_can_reply_and_get_request__verbose__waiting_for_request() -{ - if (!IPC__VERBOSE) return; - - printf("Kernel::Ipc::Participates_dialog::can_reply_and_get_request, " - "waiting for request, this=0x%p\n", - this); -} - - -void Kernel::Ipc::Participates_dialog::_send_message__verbose__success(Participant* server) -{ - if (!IPC__VERBOSE) return; - - printf("Kernel::Ipc::Participates_dialog::send_message, " - "this=0x%p, server=0x%p, _message_size=%i, print message\n", - this, server, _message_size); - - if (IPC__VERBOSE >= 2) - print_message(); -} - - -void Kernel::Ipc::Participates_dialog::_can_get_reply__verbose__waiting_for_reply(Participant* server) -{ - if (!IPC__VERBOSE) return; - - printf("Kernel::Ipc::Participates_dialog::can_get_reply, waiting for reply, " - "this=0x%p, server=0x%p, _message_size=%i\n", - this, server, _message_size); -} - - -void Kernel::Ipc::Participates_dialog::_can_get_reply__verbose__recieved_reply(Participant* server) -{ - if (!IPC__VERBOSE) return; - - printf("Kernel::Ipc::Participates_dialog::can_get_reply, recieved reply, " - "this=0x%p, server=0x%p, _message_size=%i\n", - this, server, _message_size); -} - - -void Kernel::Ipc::Participates_dialog::_send_message(Participant* server, - void* message, - unsigned size) -{ - _message_size = size; - _message = (byte_t*)message; - - server->announce_client(this); - _send_message__verbose__success(server); -} - - -bool Kernel::Ipc::Participates_dialog::can_reply_and_get_next_request(unsigned reply_size, - unsigned* request_size) -{ - if (_current_client) { - _message_size = reply_size; - _message = (byte_t*)&_utcb->byte[0]; - - _can_reply_and_get_request__verbose__replied_to_request(); - - _current_client->recieve_reply(this); - _current_client = 0; - } - - _current_client=_announced_clients.dequeue(); - if (!_current_client) { - _can_reply_and_get_request__verbose__waiting_for_request(); - return false; - } else{ - _recieve_message(_current_client); - *request_size = _message_size; - _can_reply_and_get_request__verbose__recieved_request(); - return true; - } -} - - -void Kernel::Ipc::Participates_dialog::_recieve_message(Participant* sender) -{ - if (sender->message_size() > sizeof(Utcb)) - _recieve_message__error__invalid_message_size(); - - _message_size = sender->message_size(); - _message = (byte_t*)&_utcb->byte[0]; - - for (unsigned current_byte = 0; current_byte < _message_size; current_byte++) - _message[current_byte] = - sender->message(current_byte); -} - - -void Kernel::Ipc::Participates_dialog::announce_client(Participant* client) -{ - _announced_clients.enqueue(client); -} - - -void Kernel::Ipc::Participates_dialog::recieve_reply(Participant* server) -{ - if (!_waiting_for_reply || _recieved_reply) - return; - - _recieve_message(server); - _recieved_reply = true; -} - - -bool Kernel::Ipc::Participates_dialog::can_get_reply(Participant * server, - unsigned request_size, - unsigned * reply_size) -{ - if (!_waiting_for_reply) { - - if (!server) - _can_get_reply__error__invalid_server(); - - _message_size = request_size; - _message = (byte_t*)&_utcb->byte[0]; - _recieved_reply = false; - _waiting_for_reply = true; - - server->announce_client(this); - } - - if (!_recieved_reply) { - _can_get_reply__verbose__waiting_for_reply(server); - return false; - } else { - _can_get_reply__verbose__recieved_reply(server); - - _waiting_for_reply = false; - *reply_size = _message_size; - return true; - } -} - - -#endif /* _KERNEL__INCLUDE__GENERIC__IPC_H_ */ diff --git a/base-mb/src/kernel/include/generic/irq_controller.h b/base-mb/src/kernel/include/generic/irq_controller.h deleted file mode 100755 index 0ac0da240..000000000 --- a/base-mb/src/kernel/include/generic/irq_controller.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * \brief Interface for irq controllers - * \author Martin stein - * \date 2010-06-21 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__GENERIC__IRQ_CONTROLLER_H_ -#define _KERNEL__INCLUDE__GENERIC__IRQ_CONTROLLER_H_ - -#include -#include -#include -#include - - -namespace Kernel { - - enum { - IRQ_CONTROLLER__VERBOSE = 0, - BYTE_WIDTH=8, - }; - - - template - class Irq_controller_tpl : public DEVICE_T - { - protected: - - /************************* - * Kernel_exit interface * - *************************/ - - inline void _on_kernel_exit(); - - public: - - /** - * Returns occured IRQ ID with highest priority and masks it - */ - inline Irq_id get_irq(); - - /** - * Release IRQ and unmask it - */ - inline void ack_irq(Irq_id const & i); - - Irq_controller_tpl(typename DEVICE_T::Constr_arg const & dca); - }; - - typedef Irq_controller_tpl Irq_controller; - - class Irq_allocator : - public Id_allocator - { - typedef Id_allocator Allocator; - - Irq_controller * const _controller; - - public: - - /** - * Error-codes that are returned by members - */ - enum Error { - NO_ERROR = 0, - HOLDER_DOESNT_OWN_IRQ = -1, - IRQ_IS_PENDING_YET = -2, - ALLOCATOR_ERROR = -3 - }; - - /** - * Constructor - */ - Irq_allocator(Irq_controller * const ic) : - _controller(ic) - { } - - /** - * Free IRQ if the TID-according thread owns it - */ - inline Error free(Thread * const t, Irq_id irq); - - /** - * Free IRQ if the TID-according thread owns it - */ - inline Error allocate(Thread * const t, Irq_id irq); - }; - - /** - * Pointer to kernels static IRQ allocator - */ - Irq_allocator * const irq_allocator(); - - /** - * Pointer to kernels static IRQ controller - */ - Irq_controller * const irq_controller(); -} - - -template -Kernel::Irq_controller_tpl::Irq_controller_tpl(typename DEVICE_T::Constr_arg const & dca) : - DEVICE_T(dca) -{ } - - -template -Kernel::Irq_id Kernel::Irq_controller_tpl::get_irq() -{ - Irq_id const i = DEVICE_T::next_irq(); - DEVICE_T::mask(i); - return i; -} - - -template -void Kernel::Irq_controller_tpl::ack_irq(Irq_id const & i) -{ - DEVICE_T::release(i); - DEVICE_T::unmask(i); -} - - -Kernel::Irq_allocator::Error -Kernel::Irq_allocator::allocate(Thread * const t, Irq_id irq) -{ - if (_controller->pending(irq)) { return IRQ_IS_PENDING_YET; } - - if (!Allocator::allocate(t, irq)) { return ALLOCATOR_ERROR; } - - _controller->unmask(irq); - return NO_ERROR; -}; - - -Kernel::Irq_allocator::Error -Kernel::Irq_allocator::free(Thread * const t, Irq_id irq) -{ - if (_controller->pending(irq)) { return IRQ_IS_PENDING_YET; } - - Allocator::free(irq); - _controller->mask(irq); - return NO_ERROR; -}; - -#endif /* _KERNEL__INCLUDE__GENERIC__IRQ_CONTROLLER_H_ */ diff --git a/base-mb/src/kernel/include/generic/printf.h b/base-mb/src/kernel/include/generic/printf.h deleted file mode 100755 index 803177f56..000000000 --- a/base-mb/src/kernel/include/generic/printf.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * \brief Import printf function - * \author Martin Stein - * \date 2010-10-12 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__GENERIC__PRINTF_H_ -#define _KERNEL__INCLUDE__GENERIC__PRINTF_H_ - -#include - -using Genode::printf; - -#endif /* _KERNEL__INCLUDE__GENERIC__PRINTF_H_ */ diff --git a/base-mb/src/kernel/include/generic/scheduler.h b/base-mb/src/kernel/include/generic/scheduler.h deleted file mode 100755 index 014576d5d..000000000 --- a/base-mb/src/kernel/include/generic/scheduler.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * \brief Declaration of a round robin scheduler - * \author Martin stein - * \date 2010-06-25 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__GENERIC__INCLUDE__SCHEDULER_H_ -#define _KERNEL__GENERIC__INCLUDE__SCHEDULER_H_ - -/* generic includes */ -#include -#include - -/* util includes */ -#include - -namespace Kernel { - - enum { SHOW_SCHEDULING = 0 }; - - enum { SCHEDULER__TRACE = 1, - SCHEDULER__VERBOSE = 0, - SCHEDULER__ERROR = 1, - SCHEDULER__WARNING = 1 }; - - class Exec_context; - class Platform; - - class Scheduler : public Tracks_time - { - enum { MS_PER_ROUND_PER_CLIENT = SCHEDULING_MS_INTERVAL, - SCHEDULE__VERBOSE__SUCCESS = SCHEDULER__VERBOSE, - SCHEDULE__ERROR = SCHEDULER__ERROR }; - - public: - - typedef Scheduling_timer Timer; - typedef unsigned int Quota; - typedef Kernel::Platform Ressource; - - private: - - Timer * const _timer; - const Quota _quota_per_round_per_client; - Ressource* _ressource; - bool _new_clients; - - void _schedule(); - - inline Quota _ms_to_quota(unsigned int const &ms); - - /** - * Utilise idle client as current client - */ - inline void _prep_idle_round(); - - public: - - inline void time_consumed(Quota const & q); - - enum { CLIENT__WARNING = 1, - CLIENT__VERBOSE = SCHEDULER__VERBOSE }; - - class Client_queue; - - class Client : public Kernel::Queue::Item - { - friend class Scheduler; - friend class Client_queue; - - typedef Kernel::Scheduler::Quota Quota; - - Quota _quota; - Scheduler *_scheduler; - bool _sleeping; - - protected: - - typedef Kernel::Exec_context Context; - - private: - - inline Quota _consume(Quota const &consumed); - inline void _earn_quota(Quota const &q); - inline Context *_schedulable_context(); - - protected: - - enum{ SCHEDULABLE_context__VERBOSE = 1 }; - - inline Client(); - - virtual ~Client(); - - inline void _sleep(); - inline void _wake(); - - virtual Context *_context() = 0; - virtual bool _preemptable() = 0; - - public: - - virtual int label() = 0; - }; - - - struct Client_queue : public Kernel::Queue - { - inline void print_state(); - }; - - private: - - Client_queue _client_queue; - Client* _current_client; - Client* _last_client; - Client* _idle_client; - - public: - - enum{ ADD__VERBOSE = SCHEDULER__VERBOSE||SHOW_SCHEDULING, - REMOVE__VERBOSE = SCHEDULER__VERBOSE||SHOW_SCHEDULING, - RUN__VERBOSE = SCHEDULER__VERBOSE||SHOW_SCHEDULING }; - - /** - * Constructor - * \param r Ressource that is shared by the clients - * \param t Timer to measure exclusive access duration - * \param idle_client this client gets scheduled if there's - * no other client, it can't be removed - */ - Scheduler(Ressource* r, Scheduling_timer * const t, Client* idle_client); - - void add(Client* c); - void remove(Client* c); - void run(); - - inline Client* current_client(); - - inline void skip_next_time(Client* c); - - protected: - - /* debugging */ - inline void _print_clients_via_labels(); - inline void _run__verbose__success(); - inline void _run__error__no_ready_client(); - inline void _run__trace__client_checks(); - inline void _schedule__error__no_clients(); - inline void _schedule__verbose__success() ; - inline void _remove__warning__invalid_client(); - inline void _remove__verbose__success(Client* c); - inline void _remove__trace(Client *c); - inline void _add__warning__invalid_client(); - inline void _add__verbose__success(); - }; - - /** - * Pointer to kernels static scheduler for execution time - */ - Scheduler *scheduler(); -} - - -/*********************************** - ** Kernel::Scheduler definitions ** - ***********************************/ - - -void Kernel::Scheduler::_prep_idle_round() -{ - if(_current_client) { _client_queue.enqueue(_current_client); } - _current_client=_idle_client; -} - - -void Kernel::Scheduler::time_consumed(Quota const & q) -{ - _current_client->_consume(q); -} - - -Kernel::Scheduler::Client* Kernel::Scheduler::current_client() -{ - return _current_client; -} - - -void Kernel::Scheduler::skip_next_time(Client *c) { c->_quota=0; } - - -Kernel::Scheduler::Quota Kernel::Scheduler::_ms_to_quota(unsigned int const & ms) -{ - return _timer->msec_to_native(ms); -} - - -void Kernel::Scheduler::_print_clients_via_labels() -{ - printf("scheduled "); - _last_client ? printf("%i", _last_client->label()) - : printf("ø"); - printf("→"); - _current_client ? printf("%i", _current_client->label()) - : printf("ø"); - printf(", queue "); - _client_queue.print_state(); -} - - -void Kernel::Scheduler::_run__verbose__success() -{ - if (!RUN__VERBOSE) - return; - - printf("Kernel::Scheduler::run, "); - _print_clients_via_labels(); - printf("\n"); -} - - -void Kernel::Scheduler::_run__error__no_ready_client() -{ - if (!SCHEDULER__ERROR) return; - - printf("Error in Kernel::Scheduler::run, no client is ready, halt\n"); - halt(); -} - - -void Kernel::Scheduler::_remove__trace(Client* c) -{ - if (SCHEDULER__TRACE && Verbose::trace_current_kernel_pass()) - printf("rm(%i) ", c->label()); -} - - -void Kernel::Scheduler::_run__trace__client_checks() -{ - if (SCHEDULER__TRACE && Verbose::trace_current_kernel_pass()) - printf("ask(%i,%i) ", - _current_client->label(), _current_client->_quota); -} - - -void Kernel::Scheduler::_schedule__error__no_clients() -{ - if (!SCHEDULER__ERROR) return; - - printf("Error in Kernel::Scheduler::_schedule, no clients registered, halt\n"); - halt(); -} - - -void Kernel::Scheduler::_remove__warning__invalid_client() -{ - if (!SCHEDULER__WARNING) return; - - printf("Warning in Kernel::Scheduler::remove, client invalid, skip\n"); -} - - -void Kernel::Scheduler::_add__warning__invalid_client() -{ - if (!SCHEDULER__WARNING) return; - - printf("Warning in Kernel::Scheduler::add, client invalid, skip\n"); -} - - -void Kernel::Scheduler::_add__verbose__success() -{ - if (!ADD__VERBOSE) return; - - printf("Kernel::Scheduler::add, "); - _print_clients_via_labels(); - printf(" ← )\n"); -} - - -void Kernel::Scheduler::_remove__verbose__success(Client* c) -{ - if (!REMOVE__VERBOSE) return; - - printf("Kernel::Scheduler::remove, "); - _print_clients_via_labels(); - printf(" → %i\n", c->label()); -} - - -void Kernel::Scheduler::_schedule__verbose__success() -{ - if (!SCHEDULER__VERBOSE) return; - - Client* const a = _last_client; - Client* const b = _current_client; - - Verbose::indent(10); - if (a) printf("from %i", a->label()); - else printf("from NULL"); - - Verbose::indent(10); - printf("to %i\n", b->label()); -} - - -/******************************************* - ** Kernel::Scheduler::Client definitions ** - *******************************************/ - -Kernel::Scheduler::Client::Context * -Kernel::Scheduler::Client::_schedulable_context() -{ - Context *result = 0; - if (!_sleeping) { - result = _context(); - if (_sleeping) - result = 0; - } - return result; -} - - -Kernel::Scheduler::Client::Quota -Kernel::Scheduler::Client::_consume(Quota const &consumed) -{ - if (consumed > _quota) { - _quota = 0; - } else{ - _quota = _quota - consumed; - } - return _quota; -} - - -Kernel::Scheduler::Client::Client() -: _quota(0), _scheduler(0), _sleeping(false) { } - - -void Kernel::Scheduler::Client::_earn_quota(Quota const &q) { _quota += q; } - - -void Kernel::Scheduler::Client::_sleep() { _sleeping = true; } - - -void Kernel::Scheduler::Client::_wake(){ _sleeping = false; } - - -/************************************************* - ** Kernel::Scheduler::Client_queue definitions ** - *************************************************/ - -void Kernel::Scheduler::Client_queue::print_state() -{ - Client *i = _head; - if (!i) printf("ø"); - while (i) { - printf("%i", i->label()); - if (i != _tail) printf("→"); - i = i->_next; - } -} - -#endif /* _KERNEL__INCLUDE__SCHEDULER_H_ */ - diff --git a/base-mb/src/kernel/include/generic/syscall_events.h b/base-mb/src/kernel/include/generic/syscall_events.h deleted file mode 100755 index 2da6a3899..000000000 --- a/base-mb/src/kernel/include/generic/syscall_events.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * \brief Syscall event handling behaviors - * \author Martin Stein - * \date 2010-11-18 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__GENERIC__SYSCALL_EVENTS_H_ -#define _KERNEL__INCLUDE__GENERIC__SYSCALL_EVENTS_H_ - -#include -#include - -namespace Kernel { - - enum { SYSCALL_EVENT__ERROR = 1, - SYSCALL_EVENT__WARNING = 1, - SYSCALL_EVENT__VERBOSE = 0 }; - - - class Thread; - - - class Syscall_event : public Event { }; - - - class Print_char : public Syscall_event { - - protected: - - virtual bool _permission_to_do_print_char() = 0; - - public: - - typedef On_occurence__result On_print_char__result; - - On_print_char__result on_print_char(char c); - }; - - - class Thread_create : public Syscall_event { - - protected: - - virtual bool _permission_to_do_thread_create()=0; - - void _on_thread_create__warning__failed() - { - if (SYSCALL_EVENT__WARNING) - printf("Warning in Kernel::Thread_create::on_thread_create, syscall failed\n"); - } - - void _on_thread_create__verbose__success(Thread *t); - - public: - - struct Argument - { - Thread_id tid; - Protection_id pid; - Thread_id pager_tid; - Utcb* utcb; - addr_t vip; - addr_t vsp; - bool is_privileged; - }; - - typedef Thread_create_types::Result Result; - typedef On_occurence__result On_thread_create__result; - - On_thread_create__result on_thread_create(Argument *a, Result *r); - }; - - - class Thread_kill : public Syscall_event - { - protected: - - virtual bool _permission_to_do_thread_kill() = 0; - - void _on_thread_kill__warning__failed() - { - if (SYSCALL_EVENT__WARNING) - printf("Warning in Kernel::Thread_kill::on_thread_kill, syscall failed\n"); - } - - void _on_thread_kill__verbose__success(Thread_id tid); - - public: - - struct Argument { Thread_id tid; }; - - typedef Thread_kill_types::Result Result; - typedef On_occurence__result On_thread_kill__result; - - On_thread_kill__result on_thread_kill(Argument *a, Result *r); - }; - - - class Thread_sleep : public Syscall_event - { - protected: - - void _on_thread_sleep__verbose__success(); - - public: - - typedef On_occurence__result On_thread_sleep__result; - - On_thread_sleep__result on_thread_sleep(); - }; - - - class Thread_wake : public Syscall_event - { - protected: - - virtual bool _permission_to_do_thread_wake(Thread *t) = 0; - - void _on_thread_wake__warning__failed() - { - if (SYSCALL_EVENT__WARNING) - printf("Warning in Kernel::Thread_wake::on_thread_wake, syscall failed\n"); - } - - void _on_thread_wake__verbose__success(Thread_id tid); - - public: - - struct Argument { Thread_id tid; }; - - typedef Thread_wake_types::Result Result; - typedef On_occurence__result On_thread_wake__result; - - On_thread_wake__result on_thread_wake(Argument* a, Result* r); - }; - - - class Tlb_load : public Syscall_event - { - protected: - - virtual bool _permission_to_do_tlb_load() = 0; - - public: - - void on_tlb_load(Paging::Resolution* r); - }; - - - class Thread_pager : public Syscall_event { - - protected: - - virtual bool _permission_to_do_thread_pager(Thread_id tid) = 0; - - public: - - void on_thread_pager(Thread_id target_tid, Thread_id pager_tid); - }; - - - class Tlb_flush : public Syscall_event { - - protected: - - virtual bool _permission_to_do_tlb_flush() = 0; - - public: - - void on_tlb_flush(Paging::Virtual_page *first_page, unsigned size); - }; - - - class Thread_yield: public Syscall_event - { - public: - - virtual void yield()=0; - }; -} - -#endif /* _KERNEL__INCLUDE__GENERIC__SYSCALL_EVENTS_H_ */ - diff --git a/base-mb/src/kernel/include/generic/timer.h b/base-mb/src/kernel/include/generic/timer.h deleted file mode 100755 index e91af2977..000000000 --- a/base-mb/src/kernel/include/generic/timer.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * \brief Declaration of gecoh timer device interface - * \author Martin stein - * \date 2010-06-23 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__GENERIC__TIMER_H_ -#define _KERNEL__INCLUDE__GENERIC__TIMER_H_ - -#include -#include -#include -#include -#include -#include - -extern Cpu::uint32_t volatile * _kernel_timer_ctrl; -extern Cpu::uint32_t _kernel_timer_ctrl_start; - -namespace Kernel { - - - enum { - TIMER__ERROR = 1, - TIMER__WARNING = 1, - TIMER__VERBOSE = 0, - TIMER__TRACE = 1, - }; - - - struct Tracks_time { - virtual ~Tracks_time(){} - virtual void time_consumed(unsigned int const & t) = 0; - }; - - - template - class Timer : public Kernel_entry::Listener, - public Kernel_exit::Listener, - public DEVICE_T - { - private: - - Irq_id const _irq_id; - unsigned int _start_value, _stop_value; - Tracks_time * _client; - - protected: - - /* Kernel::Kernel_entry_event::Listener interface */ - void _on_kernel_entry(); - - /* Kernel::Kernel_exit_event::Listener interface */ - void _on_kernel_exit(); - - /* debugging */ - inline void _on_kernel_exit__error__start_value_invalid(); - inline void _on_kernel_entry__verbose__success(); - inline void _on_kernel_exit__verbose__success(); - - public: - - Timer(Irq_id const & i, addr_t const & dca); - - inline bool is_busy(); - inline void track_time(unsigned int const & v, Tracks_time * const c); - - inline Irq_id irq_id(); - - inline unsigned int stop_value(); - inline unsigned int start_value(); - - /* debugging */ - void inline _start__trace(unsigned int const &v); - void inline _stop__trace(unsigned int const &v); - }; - - - typedef Timer Scheduling_timer; -} - - -/******************* - ** Kernel::Timer ** - *******************/ - - -template -Kernel::Timer::Timer(Irq_id const & i, - addr_t const & dca) : - DEVICE_T(dca), - _irq_id(i), - _start_value(0), - _stop_value(0) -{ - irq_controller()->unmask(_irq_id); -} - - - -template -void Kernel::Timer::_start__trace(unsigned int const &v) -{ - if (TIMER__TRACE && Verbose::trace_current_kernel_pass()) - printf("start(%i) ", v); -} - - -template -void Kernel::Timer::_stop__trace(unsigned int const& v) -{ - if (TIMER__TRACE && Verbose::trace_current_kernel_pass()) - printf("stop(%i) ", v); -} - - -template -unsigned int Kernel::Timer::stop_value() { return _stop_value; } - - -template -void Kernel::Timer::_on_kernel_exit__error__start_value_invalid() -{ - if (TIMER__ERROR) - printf("Error in Kernel::Timer::_on_kernel_exit," - "_start_value=%i invalid\n", _start_value); - halt(); -} - - -template -void Kernel::Timer::_on_kernel_entry__verbose__success() -{ - if (!TIMER__VERBOSE) return; - - printf("Kernel::Timer::_on_kernel_entry," - "_stop_value=%i\n", _stop_value); -} - - -template -void Kernel::Timer::_on_kernel_exit__verbose__success() -{ - if (!TIMER__VERBOSE) return; - - printf("Kernel::Timer::_on_kernel_exit," - "_start_value=%i\n", _start_value); -} - - -template -Kernel::Irq_id Kernel::Timer::irq_id() { return _irq_id; } - - -template -unsigned int Kernel::Timer::start_value() { return _start_value; } - - -template -void Kernel::Timer::track_time(unsigned int const & v, Tracks_time * const c) { - _start_value=v; - _client = c; -} - - -template -void Kernel::Timer::_on_kernel_entry() -{ - _stop_value = DEVICE_T::value(); - _stop__trace(_stop_value); - - unsigned int t = start_value()- stop_value(); - _client->time_consumed(t); - _on_kernel_entry__verbose__success(); -} - - -template -void Kernel::Timer::_on_kernel_exit() -{ - if (!_start_value) - _on_kernel_exit__error__start_value_invalid(); - - _start__trace(_start_value); - DEVICE_T::prepare_oneshot(_start_value, _kernel_timer_ctrl, _kernel_timer_ctrl_start); -} - - -#endif /* _KERNEL__INCLUDE__GENERIC__TIMER_H_ */ - diff --git a/base-mb/src/kernel/include/generic/tlb.h b/base-mb/src/kernel/include/generic/tlb.h deleted file mode 100755 index fda7b6afd..000000000 --- a/base-mb/src/kernel/include/generic/tlb.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * \brief Generic Translation lookaside buffer interface - * \author Martin Stein - * \date 2010-11-08 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__GENERIC__TLB_H_ -#define _KERNEL__INCLUDE__GENERIC__TLB_H_ - -#include -#include - -namespace Kernel { - - template - class Tlb_tpl : public DEV_T - { - - private: - - typedef typename DEV_T::Entry_id Entry_id; - - Entry_id _current_entry_id; - - static Entry_id const fixed_entry_id_1 = 0; - static Entry_id const fixed_entry_id_2 = 1; - - void _next_entry_id() - { - _current_entry_id++; - if (_current_entry_id >= DEV_T::max_entry_id()) { - _current_entry_id = 0; - } - } - - public: - - typedef Paging::Virtual_page Virtual_page; - typedef Paging::Physical_page Physical_page; - typedef Paging::Resolution Resolution; - - Tlb_tpl() : _current_entry_id(0) { } - - /** - * Add resolution to the tlb (not persistent) - */ - void add(Resolution* r) - { - if (!r->valid()) { - printf("Error in Kernel::Tlb::add, invalid page\n"); - } - - while (1) { - if (!fixed(_current_entry_id)) { break; } - else { _next_entry_id(); } - } - - if(DEV_T::set_entry(_current_entry_id, - r->physical_page.address(), r->virtual_page.address(), - r->virtual_page.protection_id(), - Paging::size_log2_by_physical_page_size[r->physical_page.size()], - r->physical_page.permissions() == Paging::Physical_page::RW || - r->physical_page.permissions() == Paging::Physical_page::RWX, - r->physical_page.permissions() == Paging::Physical_page::RX || - r->physical_page.permissions() == Paging::Physical_page::RWX)) - { - PERR("Writing to TLB failed"); - } - _next_entry_id(); - } - - /** - * Add fixed resolution to the tlb (persistent till overwritten by - * fixed resolution) - */ - void add_fixed(Resolution* r1, Resolution* r2) - { - if(DEV_T::set_entry(fixed_entry_id_1, - r1->physical_page.address(), r1->virtual_page.address(), - r1->virtual_page.protection_id(), - Paging::size_log2_by_physical_page_size[r1->physical_page.size()], - r1->physical_page.permissions() == Paging::Physical_page::RW || - r1->physical_page.permissions() == Paging::Physical_page::RWX, - r1->physical_page.permissions() == Paging::Physical_page::RX || - r1->physical_page.permissions() == Paging::Physical_page::RWX)) - { - PERR("Writing to TLB failed"); - } - - if(DEV_T::set_entry(fixed_entry_id_2, - r2->physical_page.address(), r2->virtual_page.address(), - r2->virtual_page.protection_id(), - Paging::size_log2_by_physical_page_size[r2->physical_page.size()], - r2->physical_page.permissions() == Paging::Physical_page::RW || - r2->physical_page.permissions() == Paging::Physical_page::RWX, - r2->physical_page.permissions() == Paging::Physical_page::RX || - r2->physical_page.permissions() == Paging::Physical_page::RWX)) - { - PERR("Writing to TLB failed"); - } - } - - bool fixed(Entry_id i) { - return (i == fixed_entry_id_1) || (i == fixed_entry_id_2); - } - - void flush(Virtual_page *base, unsigned size); - }; - - typedef Tlb_tpl Tlb; - - /** - * Pointer to kernels static translation lookaside buffer - */ - Tlb * tlb(); -} - - -template -void Kernel::Tlb_tpl::flush(Virtual_page *base, unsigned size) -{ - addr_t area_base = base->address(); - addr_t area_top = area_base + size; - - for (Entry_id i=0; i <= DEV_T::MAX_ENTRY_ID; i++) { - - if (fixed(i)) { continue; } - - Cpu::addr_t page; - Protection_id pid; - unsigned size_log2; - - if(DEV_T::get_entry(i, page, pid, size_log2)) { - PERR("Reading TLB entry failed"); - } - if (base->protection_id() != pid) { continue; } - - if(page < area_top && (page + (1< area_base) { - DEV_T::clear_entry(i); - } - } -} - - -#endif /* _KERNEL__INCLUDE__GENERIC__TLB_H_ */ diff --git a/base-mb/src/kernel/include/generic/verbose.h b/base-mb/src/kernel/include/generic/verbose.h deleted file mode 100755 index a2a86cdec..000000000 --- a/base-mb/src/kernel/include/generic/verbose.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * \brief Macros for errors, warnings, debugging - * \author Martin stein - * \date 2010-06-22 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KERNEL__INCLUDE__VERBOSE_H_ -#define _KERNEL__INCLUDE__VERBOSE_H_ - -/* kernel includes */ -#include - -/* OS includes */ -#include -#include - -using Genode::printf; - -namespace Kernel { - - using namespace Cpu; - - /** - * Halt all executions (uninteruptable endless loop) - */ - void halt(); - - unsigned word_width(); - - /** - * Implementing verbose helper methods - */ - namespace Verbose { - - enum { - TRACE_KERNEL_PASSES = 0, - TRACE_ALL_THREAD_IDS = 1, - TRACE_ALL_PROTECTION_IDS = 1, - TRACE_ALL_SYSCALL_IDS = 1, - TRACE_ALL_EXCEPTION_IDS = 1, - TRACE_ALL_IRQ_IDS = 1 - }; - - Kernel::Thread_id const trace_these_thread_ids[]= { 0 }; - - Kernel::Protection_id const trace_these_protection_ids[] = { - Roottask::PROTECTION_ID, Kernel::INVALID_PROTECTION_ID }; - - Kernel::Syscall_id const trace_these_syscall_ids[] = { INVALID_SYSCALL_ID }; -// TLB_LOAD , -// TLB_FLUSH , -// THREAD_CREATE, -// THREAD_KILL , -// THREAD_SLEEP , -// THREAD_WAKE , -// THREAD_YIELD , -// THREAD_PAGER , -// IPC_REQUEST , -// IPC_SERVE , -// PRINT_CHAR , -// PRINT_INFO , - - Kernel::Exception_id const trace_these_exception_ids[] = { INVALID_EXCEPTION_ID }; -// FAST_SIMPLEX_LINK , -// UNALIGNED , -// ILLEGAL_OPCODE , -// INSTRUCTION_BUS , -// DATA_BUS , -// DIV_BY_ZERO_EXCEPTON , -// FPU , -// PRIVILEGED_INSTRUCTION, -// INTERRUPT , -// EXTERNAL_NON_MASKABLE_BREAK, -// EXTERNAL_MASKABLE_BREAK , -// DATA_STORAGE , -// INSTRUCTION_STORAGE , -// DATA_TLB_MISS , -// INSTRUCTION_TLB_MISS, - - /* - * Tracing for specific kernel-entry causes can be configured in - * 'platform.cc'. - */ - bool trace_current_kernel_pass(); - - void begin__trace_current_kernel_pass(); - - void inline indent(unsigned int const &i); - } -} - - -void Kernel::Verbose::indent(unsigned int const &indent) -{ - for (unsigned int i = 0; i < indent; i++) - _prints_chr1(' '); -} - - -#endif /* _KERNEL__INCLUDE__VERBOSE_H_ */ diff --git a/base-mb/src/kernel/include/petalogix_s3adsp1800_mmu/platform/platform.h b/base-mb/src/kernel/include/petalogix_s3adsp1800_mmu/platform/platform.h deleted file mode 100755 index 9d959ec73..000000000 --- a/base-mb/src/kernel/include/petalogix_s3adsp1800_mmu/platform/platform.h +++ /dev/null @@ -1,729 +0,0 @@ -/* - * \brief Implementations for kernels platform class - * \author Martin Stein - * \date 2010-10-01 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__PETALOGIX_S3ADSP1800_MMU__PLATFORM__PLATFORM_H_ -#define _INCLUDE__PETALOGIX_S3ADSP1800_MMU__PLATFORM__PLATFORM_H_ - -/* Device includes */ -#include -#include -#include - -/* Kernel includes */ -#include -#include -#include -#include - - -/* - * Asm labels where to enter an irq/exception/syscall from userland, and vice - * versa the userland from inside the kernel - */ -extern Kernel::word_t _syscall_entry; -extern Kernel::word_t _exception_entry; -extern Kernel::word_t _interrupt_entry; -extern Kernel::word_t _userland_entry; -extern Kernel::word_t _atomic_ops_begin; -extern Kernel::word_t _atomic_ops_end; -extern Kernel::addr_t _call_after_kernel; - -namespace Kernel { - - enum { - PLATFORM__TRACE = 1, - PLATFORM__VERBOSE = 0, - PLATFORM__VERBOSE__THREAD_TRACING = 1, - - PLATFORM_THREAD__ERROR = 1, - PLATFORM_THREAD__WARNING = 1, - PLATFORM_THREAD__VERBOSE = 0, - - PLATFORM_IRQ__VERBOSE = 0, - PLATFORM_EXCEPTION__VERBOSE = 0, - PLATFORM_SYSCALL__VERBOSE = 0, - - WORD_WIDTH_LOG2 = 5, - BYTE_WIDTH_LOG2 = 3 - }; - - class Platform_thread; - class Platform; - - - /** - * Get kernel's static platform representation - */ - Platform* platform(); - - - /** - * Platform specific execution context - */ - struct Exec_context - { - typedef Kernel::Protection_id Protection_id; - typedef Kernel::word_t word_t; - - /** - * Type constraints - */ - enum{ - WORD_WIDTH_LOG2 = Kernel::WORD_WIDTH_LOG2, - BYTE_WIDTH_LOG2 = Kernel::BYTE_WIDTH_LOG2, - WORD_SIZE = 1 << (WORD_WIDTH_LOG2-BYTE_WIDTH_LOG2) }; - - /** - * Blocking types - */ - enum{ - NO_BLOCKING = 0, - IRQ_BLOCKING = 1, - EXCEPTION_BLOCKING = 2, - SYSCALL_BLOCKING = 3, - BLOCKING_TYPE_RANGE = 4 - }; - - /** - * Register constraints - */ - enum { - /* rmsr */ - RMSR_BE_LSHIFT = 0, RMSR_BE_MASK = 1 << RMSR_BE_LSHIFT, - RMSR_IE_LSHIFT = 1, RMSR_IE_MASK = 1 << RMSR_IE_LSHIFT, - RMSR_C_LSHIFT = 2, RMSR_C_MASK = 1 << RMSR_C_LSHIFT, - RMSR_BIP_LSHIFT = 3, RMSR_BIP_MASK = 1 << RMSR_BIP_LSHIFT, - RMSR_FSL_LSHIFT = 4, RMSR_FSL_MASK = 1 << RMSR_FSL_LSHIFT, - RMSR_ICE_LSHIFT = 5, RMSR_ICE_MASK = 1 << RMSR_ICE_LSHIFT, - RMSR_DZ_LSHIFT = 6, RMSR_DZ_MASK = 1 << RMSR_DZ_LSHIFT, - RMSR_DCE_LSHIFT = 7, RMSR_DCE_MASK = 1 << RMSR_DCE_LSHIFT, - RMSR_EE_LSHIFT = 8, RMSR_EE_MASK = 1 << RMSR_EE_LSHIFT, - RMSR_EIP_LSHIFT = 9, RMSR_EIP_MASK = 1 << RMSR_EIP_LSHIFT, - RMSR_PVR_LSHIFT = 10, RMSR_PVR_MASK = 1 << RMSR_PVR_LSHIFT, - RMSR_UM_LSHIFT = 11, RMSR_UM_MASK = 1 << RMSR_UM_LSHIFT, - RMSR_UMS_LSHIFT = 12, RMSR_UMS_MASK = 1 << RMSR_UMS_LSHIFT, - RMSR_VM_LSHIFT = 13, RMSR_VM_MASK = 1 << RMSR_VM_LSHIFT, - RMSR_VMS_LSHIFT = 14, RMSR_VMS_MASK = 1 << RMSR_VMS_LSHIFT, - RMSR_CC_LSHIFT = 31, RMSR_CC_MASK = 1 << RMSR_CC_LSHIFT, - - /* resr */ - RESR_EC_LSHIFT = 0, RESR_EC_MASK = 0x1F<> RESR_EC_LSHIFT; } - }; -} - - -extern Kernel::Exec_context* _userland_context; - - -namespace Kernel { - - /** - * Platform representation - */ - class Platform : public Kernel_entry::Listener - { - public: - - /** - * General configuration - */ - enum { - ATOMIC_OPS_PAGE_SIZE_LOG2 = DEFAULT_PAGE_SIZE_LOG2, - KERNEL_ENTRY_SIZE_LOG2 = DEFAULT_PAGE_SIZE_LOG2 - }; - - /** - * Verbose, errors, warnings - */ - enum { - VERBOSE__CONSTRUCTOR = PLATFORM__VERBOSE, - VERBOSE__ENTER_USERLAND = PLATFORM__VERBOSE - }; - - /** - * General platform constraints - */ - enum { - WORD_WIDTH_LOG2 = Kernel::WORD_WIDTH_LOG2, - BYTE_WIDTH_LOG2 = Kernel::BYTE_WIDTH_LOG2, - BYTE_WIDTH = 1 << BYTE_WIDTH_LOG2, - WORD_WIDTH = 1 << WORD_WIDTH_LOG2, - WORD_SIZE = 1 << (WORD_WIDTH_LOG2-BYTE_WIDTH_LOG2), - - WORD_HALFWIDTH = WORD_WIDTH >> 1, - - WORD_LEFTHALF_MASK = ~0 << WORD_HALFWIDTH , - WORD_RIGHTHALF_MASK = ~WORD_LEFTHALF_MASK - }; - - typedef uint32_t word_t; - typedef uint32_t Register; - - private: - - Kernel::Tlb _tlb; - - /** - * Processor specific - */ - enum { - ASM_IMM = 0xb0000000, - ASM_BRAI = 0xb8080000, - ASM_RTSD = 0xb6000000, - ASM_NOP = 0x80000000, - - SYSCALL_ENTRY = 0x00000008, - INTERRUPT_ENTRY = 0x00000010, - EXCEPTION_ENTRY = 0x00000020 - }; - - void _initial_tlb_entries() - { - using namespace Paging; - - Physical_page::size_t atomic_ops_pps, kernel_entry_pps; - - if (Physical_page::size_by_size_log2( - atomic_ops_pps, ATOMIC_OPS_PAGE_SIZE_LOG2) || - Physical_page::size_by_size_log2( - kernel_entry_pps, KERNEL_ENTRY_SIZE_LOG2)) - { - printf("Error in Kernel::Platform::_initial_tlb_entries"); - return; - }; - - Physical_page atomic_ops_pp((addr_t)&_atomic_ops_begin, - atomic_ops_pps, Physical_page::RX); - - Virtual_page atomic_ops_vp(atomic_ops_pp.address(), - UNIVERSAL_PROTECTION_ID); - - Resolution atomic_ops_res(&atomic_ops_vp, &atomic_ops_pp); - - Physical_page kernel_entry_pp((addr_t)0, kernel_entry_pps, - Physical_page::RX); - - Virtual_page kernel_entry_vp(kernel_entry_pp.address(), - UNIVERSAL_PROTECTION_ID); - - Resolution kernel_entry_res(&kernel_entry_vp, &kernel_entry_pp); - - tlb()->add_fixed(&atomic_ops_res, &kernel_entry_res); - } - - /** - * Initialize the ability to enter userland - */ - inline void _init_userland_entry() { - _call_after_kernel=(addr_t)&_userland_entry; } - - /** - * Fill in jump to CPU's 2-word-width exception entry - */ - inline void _init_exception_entry() - { - *(word_t*)EXCEPTION_ENTRY = - ASM_IMM | ((word_t)&_exception_entry & WORD_LEFTHALF_MASK) >> WORD_HALFWIDTH; - - *(word_t*)(EXCEPTION_ENTRY + WORD_SIZE) = - ASM_BRAI | ((word_t)&_exception_entry & WORD_RIGHTHALF_MASK); - } - - /** - * Fill in jump to CPU's 2-word-width syscall entry - */ - inline void _init_syscall_entry() - { - *(word_t*)SYSCALL_ENTRY = - ASM_IMM | ((word_t)&_syscall_entry & WORD_LEFTHALF_MASK) >> WORD_HALFWIDTH; - - *(word_t*)(SYSCALL_ENTRY + WORD_SIZE) = - ASM_BRAI | (word_t) &_syscall_entry & WORD_RIGHTHALF_MASK; } - - /** - * Fill in jump to CPU's 2-word-width interrupt entry - */ - inline void _init_interrupt_entry() - { - *((word_t*) INTERRUPT_ENTRY) = - ASM_IMM | ((word_t)&_interrupt_entry & WORD_LEFTHALF_MASK) >> WORD_HALFWIDTH; - - *((word_t*)(INTERRUPT_ENTRY + WORD_SIZE)) = - ASM_BRAI | (word_t) &_interrupt_entry & WORD_RIGHTHALF_MASK; - } - - public: - - /** - * Constructor - */ - Platform(); - - bool is_atomic_operation(void* ip) - { - enum { - SIZE = (1 << ATOMIC_OPS_PAGE_SIZE_LOG2), - SIZE_WORDS = SIZE/sizeof(word_t) - }; - - static word_t *const _first_atomic_op = &_atomic_ops_begin; - static word_t *const _last_atomic_op = - _first_atomic_op + (SIZE_WORDS-1); - - return ((ip >=_first_atomic_op) & (ip <=_last_atomic_op)); - } - - /** - * Set execution context loaded at next userland entry - */ - inline int userland_context(Exec_context* c) - { - _userland_context = c; - _userland_context__verbose__set(c); - return 0; - } - - /** - * Lock the platforms execution ability to one execution context - */ - inline void lock(Exec_context *c){ userland_context(c); } - - /** - * Set return address register - * - * It is essential that this function is always inline! - */ - inline int return_address(addr_t a) - { - asm volatile("add r15, %0, r0"::"r"((Register)a):); - return 0; - } - - /** - * Halt whole system - */ - inline void halt() { asm volatile ("bri 0"); }; - - /** - * Get the platforms general IRQ-controller - */ - inline Irq_controller * const irq_controller(); - - /** - * Get the timer that is reserved for kernels schedulinge - */ - inline Scheduling_timer * const timer(); - - Tlb *tlb() { return &_tlb; }; - - protected: - - void _on_kernel_entry__trace__thread_interrupts(); - - void _on_kernel_entry__verbose__called() - { - if (PLATFORM__VERBOSE) - printf("Kernel::Platform::_on_kernel_entry\n"); - } - - void _on_kernel_entry(); - - void _userland_context__verbose__set(Exec_context* c) - { - if (!PLATFORM__VERBOSE) return; - if (_userland_context) { - printf("Kernel::Platform::_userland_context, new userland context c=0x%8X, printing contents", (uint32_t)_userland_context); - c->print_content(2); - } else - printf("Kernel::Platform::_userland_context, no userland context"); - - printf("\n"); - } - }; - - - class Platform_blocking - { - protected: - - typedef Kernel::Exec_context Context; - typedef Kernel::Platform_thread Owner; - - Owner* _owner; - Context* _context; - - public: - - /** - * Constructor - */ - Platform_blocking(Owner* o, Context* c) - : _owner(o), _context(c) {} - }; - - - /** - * Platform-specific IRQ - */ - class Platform_irq : public Platform_blocking, public Irq - { - public: - - /** - * Constructor - */ - Platform_irq(Owner* o, Context* c) : Platform_blocking(o,c) {} - - void block(); - - protected: - - void _block__verbose__success() - { - if (PLATFORM_IRQ__VERBOSE) - printf("Platform_irq::block(), _id=%i\n", _id); - } - }; - - - class Platform_exception : public Platform_blocking, public Exception - { - protected: - - Protection_id protection_id(); - addr_t address(); - bool attempted_write_access(); - - public: - - /** - * Constructor - */ - Platform_exception(Owner* o, Context* c) : Platform_blocking(o, c) { } - - void block(Exec_context * c); - }; - - - class Platform_syscall : public Platform_blocking, public Syscall - { - public: - - /** - * Constructor - */ - Platform_syscall(Owner *o, Context *c, Source *s) : - Platform_blocking(o,c), - Syscall(&c->r30, &c->r29, &c->r28, - &c->r27, &c->r26, &c->r25, - &c->r24, &c->r30, s) - { } - - void block(); - - protected: - - void _block__verbose__success() - { - if (PLATFORM_IRQ__VERBOSE) - printf("Platform_syscall::block(), _id=%i\n", _id); - } - }; - - - /** - * Platform-specific thread implementations - */ - class Platform_thread - { - typedef Kernel::Blocking Blocking; - - enum { - INITIAL_RMSR = 1 << Exec_context::RMSR_PVR_LSHIFT - | 1 << Exec_context::RMSR_UMS_LSHIFT - | 1 << Exec_context::RMSR_VMS_LSHIFT, - - INITIAL_BLOCKING_TYPE = Exec_context::NO_BLOCKING - }; - - Platform_irq _irq; - Platform_exception _exception; - Platform_syscall _syscall; - - Exec_context _exec_context; - - /* if not zero, this thread is blocked */ - Blocking* _blocking; - - public: - - bool timer_interrupted() - { - return false; - } - - void yield_after_atomic_operation() { _exec_context.r31 = 1; } - - void unblock() { _blocking = 0; } - - typedef Kernel::Protection_id Protection_id; - - Platform_thread() : - _irq(this, &_exec_context), - _exception(this, &_exec_context), - _syscall(this, &_exec_context, 0), - _exec_context(this), - _blocking(0) - { } - - Platform_thread(addr_t ip, - addr_t sp, - Protection_id pid, - Syscall::Source *sc) - : - _irq(this, &_exec_context), - _exception(this, &_exec_context), - _syscall(this, &_exec_context, sc), - _exec_context(this), - _blocking(0) - { - _exec_context.rpc = ip; - _exec_context.r1 = sp; - _exec_context.rpid = pid; - _exec_context.blocking_type= INITIAL_BLOCKING_TYPE; - _exec_context.rmsr = INITIAL_RMSR; } - - enum { BLOCK__ERROR = 1, - BLOCK__WARNING = 1}; - - /** - * Get thread blocked if there is a blocking at execution context - */ - void on_kernel_entry() - { - using Kernel::Exec_context; - - switch (_exec_context.blocking_type) { - - case Exec_context::NO_BLOCKING: - _blocking = 0; - break; - - case Exec_context::IRQ_BLOCKING: - _irq.block(); - _blocking = &_irq; - break; - - case Exec_context::EXCEPTION_BLOCKING: - _exception.block(&_exec_context); - _blocking = &_exception; - break; - - case Exec_context::SYSCALL_BLOCKING: - _syscall.block(); - _blocking = &_syscall; - break; - - default: - _block__error__unknown_blocking_type(); - } - - _block__verbose__success(); - } - - Protection_id protection_id() { - return (Protection_id)_exec_context.rpid; } - - addr_t instruction_pointer() { - return (addr_t)_exec_context.rpc; } - - Exec_context* exec_context() { - return &_exec_context; } - - Exec_context* unblocked_exec_context() - { - Exec_context* result=&_exec_context; - - if (_blocking) { - if (!_blocking->unblock()) - result = 0; - else - _blocking = 0; - } - return result; - } - - void call_argument_0(word_t value){ - _exec_context.r5=value;} - - void bootstrap_argument_0(word_t value){ - _exec_context.r31=value;} - - void print_state() { - _exec_context.print_content(2); - printf("\n"); - }; - - Exception *exception() { return &_exception; } - Syscall *syscall() { return &_syscall; } - Irq *irq() { return &_irq; } - - protected: - - void _block__error__unknown_blocking_type() - { - if (!PLATFORM_THREAD__ERROR) - return; - - printf("Error in Kernel::Platform_thread::block: " - "unknown blocking_type=%i, printing state\n", - _exec_context.blocking_type); - - _exec_context.print_content(2); - printf("halt\n"); - halt(); - } - - void _block__warning__no_blocking() - { - if (!PLATFORM_THREAD__WARNING) - return; - - printf("Warning Kernel::Platform_thread::_no_blocking called\n"); - halt(); - } - - void _block__verbose__success() - { - if (!PLATFORM_THREAD__VERBOSE) - return; - - printf("Kernel::Platform_thread::block, blocked " - "this=0x%p, blocking_type=%i\n", - this, _exec_context.blocking_type); - } - }; -} - - -Kernel::Irq_controller * const Kernel::Platform::irq_controller() -{ - using namespace Xilinx; - static Irq_controller _ic = Irq_controller(Xps_intc::Constr_arg(Cpu::XPS_INTC_BASE)); - return &_ic; -} - - -Kernel::Scheduling_timer * const Kernel::Platform::timer() -{ - using namespace Xilinx; - static Scheduling_timer _st = Scheduling_timer(SCHEDULING_TIMER_IRQ, - (addr_t)SCHEDULING_TIMER_BASE); - return &_st; -} - - -#endif /* _INCLUDE__PETALOGIX_S3ADSP1800_MMU__PLATFORM__PLATFORM_H_ */ - diff --git a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/atomic.s b/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/atomic.s deleted file mode 100755 index cedd2448d..000000000 --- a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/atomic.s +++ /dev/null @@ -1,93 +0,0 @@ -/* - * \brief Simulated Atomic Operations on Xilinx Microblaze - * \author Martin Stein - * \date 2010-08-30 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -.global _atomic_cmpxchg - - -/** - * the virtual area to the following code is interrupt save and - * executable-only in virtual mode. the code have to be position - * independent, so it can be linked to the according virtual area - * in any image that is executed above kernel to import the labels. - * it is bothsides aligned - so that no common functions could gain - * interruptsave status because it were linked inside this page too - */ -.section ".Atomic_ops" -.global _atomic_ops_begin -.align 12 -_atomic_ops_begin: - -/** - * Atomic compare and exchange, see cmpxchg - * - * should only be used wrapped by cmpxchg - * otherwise this operation may won't behave as wished - * and leads to unnesscessary yielding of thread! - * - * Parameters dest, cmp_val, new_val and *dest are assumed in r30, r29, r28 and r27 - * R15 is assumed to hold return pointer - * Return value is stored in r28 - */ -_atomic_cmpxchg: - - xor r29, r29, r27 /* diff=cmp_val-*dest */ - bnei r29, _atomic_cmpxchg_notequal_1 /* if(!diff) { */ - swi r28, r30, 0 /* *dest=new_val */ - _atomic_cmpxchg_notequal_1: /* } */ - or r28, r0, r0 /* result=0 */ - bnei r29, _atomic_cmpxchg_notequal_2 /* if(!diff) { */ - addi r28, r0, 1 /* result=1 */ - _atomic_cmpxchg_notequal_2: /* } */ - -/* idle a while in interrupt save state, enable this for testing atomicity of atomic ops */ -/* - addi r29, r0, 0x04000000 - _atomic_cmpxchg_idle: - addi r29, r29, -1 - bnei r29, _atomic_cmpxchg_idle -*/ - - beqi r31, _atomic_cmpxchg_yield_return /* if(interrupt occured) { */ - bri _atomic_syscall_yield /* yield thread */ - _atomic_cmpxchg_yield_return: /* }else{ */ - rtsd r15, +2*4 /* return to nonatomic */ - or r0, r0, r0 /* } */ - - -/** - * Yield Thread (for atomic ops, if interrupt has occured during execution) - */ -_atomic_syscall_yield: - - /* backup registers */ - addik r1, r1, -2*4 - swi r15, r1, +0*4 - swi r31, r1, +1*4 - - /* set syscall type (see include/kernel/syscalls.h) */ - addi r31, r0, 7 - - /* jump to cpus syscall-handler if it's enabled */ - brki r15, 0x8 - or r0, r0, r0 - - /* recover & return */ - lwi r15, r1, +0*4 - lwi r31, r1, +1*4 - addik r1, r1, +2*4 - bri _atomic_cmpxchg_yield_return - -.global _atomic_ops_end -.align 12 -_atomic_ops_end: - diff --git a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/crt0.s b/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/crt0.s deleted file mode 100755 index 9dcf377e7..000000000 --- a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/crt0.s +++ /dev/null @@ -1,47 +0,0 @@ -/* - * \brief Startup code for programs on microblaze - * \author Martin Stein - * \date 21.06.2010 - */ - -.extern _main - -.global _main_utcb_addr - - -.macro _INIT_MAIN_UTCB - swi r31, r0, _main_utcb_addr -.endm - - -.macro _INIT_MAIN_STACK - la r1, r0, _main_stack_base -.endm - - -/* _BEGIN_ELF_ENTRY_CODE */ -.global _start -.section ".Elf_entry" -_start: - - _INIT_MAIN_UTCB - _INIT_MAIN_STACK - - bralid r15, _main - or r0, r0, r0 - - /* _ERROR_NOTHING_LEFT_TO_CALL_BY_CRT0 */ - brai 0x99000001 - - -/* _BEGIN_READABLE_WRITEABLE */ -.section ".bss" - - .align 4 - _main_utcb_addr: .space 1*4 - .align 4 - _main_stack_top: .space 1024*1024 - _main_stack_base: - - - diff --git a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/crt0_kernel.s b/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/crt0_kernel.s deleted file mode 100755 index ea275c5bd..000000000 --- a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/crt0_kernel.s +++ /dev/null @@ -1,94 +0,0 @@ -/* - * \brief Startup code for kernel main routine on microblaze - * \author Martin Stein - * \date 2010-06-21 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* - * To be compatible to crt0.s for common programs, - * the following labels are used for roottasks main-thread - */ -.global _main_utcb_addr - -/* - * Here you can denote an instruction pointer to - * call after kernel execution returns (e.g. userland entry) - */ -.global _call_after_kernel - -/* top of kernel stack is used when we have to reset the kernel - * context, for example when we enter the kernel from userland - */ -.global _kernel_stack_top - -/* kernel returns to this label after execution - */ -.global _exit_kernel - -/* pointer to kernel main routine */ -.extern _kernel - - - -/******************************* - ** Macros for _start routine ** - *******************************/ - -.macro _CALL_AFTER_KERNEL__USES_R3_R15 - lwi r3, r0, _call_after_kernel - beqi r3, _no_call_after_kernel - addi r15, r0, _exit_call_after_kernel-2*4 - bra r3 - - _exit_call_after_kernel: - _no_call_after_kernel: -.endm - - -.macro _CALL_KERNEL__USES_R15 - addi r1, r0, _kernel_stack_top - addi r15, r0, _exit_kernel-2*4 - brai _kernel - or r0, r0, r0 - _exit_kernel: -.endm - - - -/******************** - ** _start_routine ** - ******************** - - -/* linker links this section to kernelbase + offset 0 */ - -/* _BEGIN_ELF_ENTRY_CODE */ -.global _start -.section ".Elf_entry" -_start: - - _CALL_KERNEL__USES_R15 - _CALL_AFTER_KERNEL__USES_R3_R15 - - /* ERROR_NOTHING_LEFT_TO_CALL_BY_CRT0 */ - brai 0x99000001 - - -/* _BEGIN_READABLE_WRITEABLE */ -.section ".bss" - - .align 4 - _main_utcb_addr: .space 4*1 - .align 4 - _call_after_kernel: .space 4*1 - .align 4 - _kernel_stack_base: .space 1024*1024 - _kernel_stack_top: - diff --git a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/kernel_entry.s b/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/kernel_entry.s deleted file mode 100755 index d4b660253..000000000 --- a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/kernel_entry.s +++ /dev/null @@ -1,260 +0,0 @@ -/** - * Enter the kernel through interrupt, exception or syscall - * saves userland context state to execution context denoted at _userland_context - * - * \author Martin Stein - * \date 2010-10-06 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - - -/* We have to know wich userland context was the last that was executed */ -.extern _userland_context - -/* We have to use the initial stack pointer of kernel to - * provide an execution context for every kernel entrance -*/ -.extern _kernel_stack_top - -/* Pointer to kernels handler routine for userland blockings */ -.extern _kernel -.extern _kernel_exit - -/* We have to use these labels when initializing cpu's entries */ -.global _syscall_entry -.global _exception_entry -.global _interrupt_entry - - - -.macro _MAY_BE_VERBOSE_KERNEL_ENTRY -/* - _PRINT_CONTEXT - _PRINT_ASCII_STOP -*/ -.endm - - -.macro _MAY_BE_VERBOSE_VARIABLES -/* - _PRINT_CONTEXT__VARIABLES - _PRINT_HEX32__VARIABLES - _PRINT_HEX8__VARIABLES - _PRINT_ASCII_SPACE__VARIABLES - _PRINT_ASCII_BREAK__VARIABLES - _PRINT_ASCII_RUN__VARIABLES - _PRINT_ASCII_STOP__VARIABLES -*/ -.endm - - -.macro _IF_BRANCH_WAS_BLOCKING_CAUSE__USES_R15 - mfs r15, resr - andi r15, r15, 0x00001000 - beqi r15, _end_if_branch_was_blocking_cause -.endm - - -.macro _SET_PRESTORED_RPC_TO_BRANCH_TARGET__USES_R15 - mfs r15, rbtr - swi r15, r0, _prestored_rpc -.endm - - -.macro _PRESTORE_CONTEXT_AT_INTERRUPT__USES_R1_R14_R15 - swi r14, r0, _prestored_rpc - swi r1, r0, _prestored_r1 - swi r15, r0, _prestored_r15 -.endm - - -.macro _BLOCKING_TYPE_IS_INTERRUPT__USES_R3_R15 - addi r3, r0, 1 - lwi r15, r0, _userland_context - - /* _SAVE_BLOCKING_TYPE_TO_CONTEXT__USES_R3_R15 */ - swi r3, r15, 37*4 -.endm - - -.macro _PRESTORE_CONTEXT_AT_EXCEPTION__USES_R1_R15_R17 - swi r17, r0, _prestored_rpc - swi r1, r0, _prestored_r1 - swi r15, r0, _prestored_r15 - - _IF_BRANCH_WAS_BLOCKING_CAUSE__USES_R15 - - _SET_PRESTORED_RPC_TO_BRANCH_TARGET__USES_R15 - - _end_if_branch_was_blocking_cause: -.endm - - -.macro _BLOCKING_TYPE_IS_EXCEPTION__USES_R3_R15 - addi r3, r0, 2 - lwi r15, r0, _userland_context - - /* _SAVE_BLOCKING_TYPE_TO_CONTEXT__USES_R3_R15 */ - swi r3, r15, 37*4 -.endm - - -.macro _PRESTORE_CONTEXT_AT_SYSCALL__USES_R1_R15 - swi r1, r0, _prestored_r1 - swi r0, r0, _prestored_r15 - swi r15, r0, _prestored_rpc -.endm - - -.macro _BLOCKING_TYPE_IS_SYSCALL__USES_R3_R15 - addi r3, r0, 3 - lwi r15, r0, _userland_context - - /* _SAVE_BLOCKING_TYPE_TO_CONTEXT__USES_R3_R15 */ - swi r3, r15, 37*4 -.endm - - -.macro _BACKUP_PRESTORED_CONTEXT__USES_R2_TO_R31 - lwi r15, r0, _userland_context - - /* _SAVE_R2_TO_R13_TO_CONTEXT__USES_R2_TO_R13_R15 */ - swi r2, r15, 2*4 - swi r3, r15, 3*4 - swi r4, r15, 4*4 - swi r5, r15, 5*4 - swi r6, r15, 6*4 - swi r7, r15, 7*4 - swi r8, r15, 8*4 - swi r9, r15, 9*4 - swi r10, r15, 10*4 - swi r11, r15, 11*4 - swi r12, r15, 12*4 - swi r13, r15, 13*4 - - /* _SAVE_R18_TO_R31_TO_CONTEXT__TO_R15_R18_TO_R31 */ - swi r18, r15, 18*4 - swi r19, r15, 19*4 - swi r20, r15, 20*4 - swi r21, r15, 21*4 - swi r22, r15, 22*4 - swi r23, r15, 23*4 - swi r24, r15, 24*4 - swi r25, r15, 25*4 - swi r26, r15, 26*4 - swi r27, r15, 27*4 - swi r28, r15, 28*4 - swi r29, r15, 29*4 - swi r30, r15, 30*4 - swi r31, r15, 31*4 - - /* _SAVE_RPID_TO_CONTEXT__USES_R3_R15 */ - mfs r3, rpid - swi r3, r15, 36*4 - - /* _SAVE_RMSR_TO_CONTEXT__USES_R3_R15 */ - mfs r3, rmsr - swi r3, r15, 33*4 - - /* _SAVE_RESR_TO_CONTEXT__USES_R3_R15 */ - mfs r3, resr - swi r3, r15, 35*4 - - /* _SAVE_REAR_TO_CONTEXT__USES_R3_R15 */ - mfs r3, rear - swi r3, r15, 34*4 - - /* _SAVE_PRESTORED_R1_R15_RPC_TO_CONTEXT__USES_R3_R15 */ - lwi r3, r0, _prestored_r1 - swi r3, r15, 1*4 - lwi r3, r0, _prestored_r15 - swi r3, r15, 15*4 - lwi r3, r0, _prestored_rpc - swi r3, r15, 32*4 -.endm - - -.macro _CALL_KERNEL__USES_R1_R15 - addi r1, r0, _kernel_stack_top - addi r15, r0, _exit_kernel-2*4 - - brai _kernel - or r0, r0, r0 -.endm - - -/* _BEGIN_READABLE_EXECUTABLE */ -.section ".text" - - _interrupt_entry: - - _MAY_BE_VERBOSE_KERNEL_ENTRY - - _PRESTORE_CONTEXT_AT_INTERRUPT__USES_R1_R14_R15 - _BACKUP_PRESTORED_CONTEXT__USES_R2_TO_R31 - _BLOCKING_TYPE_IS_INTERRUPT__USES_R3_R15 - - _CALL_KERNEL__USES_R1_R15 - /* Kernel execution with return pointer set to _kernel_exit */ - - _end_interrupt_entry: - - - - - _exception_entry: - - _MAY_BE_VERBOSE_KERNEL_ENTRY - - _PRESTORE_CONTEXT_AT_EXCEPTION__USES_R1_R15_R17 - _BACKUP_PRESTORED_CONTEXT__USES_R2_TO_R31 - _BLOCKING_TYPE_IS_EXCEPTION__USES_R3_R15 - - _CALL_KERNEL__USES_R1_R15 - /* Kernel execution with return pointer set to _kernel_exit */ - - _end_exception_entry: - - - - - _syscall_entry: - - _MAY_BE_VERBOSE_KERNEL_ENTRY - - _PRESTORE_CONTEXT_AT_SYSCALL__USES_R1_R15 - _BACKUP_PRESTORED_CONTEXT__USES_R2_TO_R31 - _BLOCKING_TYPE_IS_SYSCALL__USES_R3_R15 - - _CALL_KERNEL__USES_R1_R15 - /* Kernel execution with return pointer set to _kernel_exit */ - - _end_syscall_entry: - - - - -/* _BEGIN_READABLE_WRITEABLE */ -.section ".bss" - - .global _current_context_label - .align 4 - _current_context_label: .space 1*4 - - /* _VARIABLES_TO_WRITE_EXEC_CONTEXT */ - .align 4 - _prestored_r1: .space 4 - .align 4 - _prestored_r15: .space 4 - .align 4 - _prestored_rpc: .space 4 - - _MAY_BE_VERBOSE_VARIABLES - - diff --git a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/platform.cc b/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/platform.cc deleted file mode 100644 index 44d906312..000000000 --- a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/platform.cc +++ /dev/null @@ -1,205 +0,0 @@ -/* - * \brief Platform implementations - * \author Martin stein - * \date 2010-10-01 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Platform includes */ -#include -#include - -/* Kernel includes */ -#include -#include -#include - - -extern unsigned int _current_context_label; -using namespace Kernel; -using namespace Cpu; - - -void Platform::_on_kernel_entry() -{ - _on_kernel_entry__verbose__called(); - _on_kernel_entry__trace__thread_interrupts(); - _userland_context->holder->on_kernel_entry(); - platform()->userland_context(0); -} - - -Platform::Platform() -{ - _initial_tlb_entries(); - _init_userland_entry(); - _init_interrupt_entry(); - _init_syscall_entry(); - _init_exception_entry(); -} - - -void Platform_syscall::block() -{ - _id = (Syscall_id)_context->r31; - _block__verbose__success(); -} - - -void Platform_exception::block(Exec_context * c) -{ - _id = (Exception_id)((_context->resr & Context::RESR_EC_MASK) >> Context::RESR_EC_LSHIFT); -} - - -void Platform_irq::block() -{ - _id = platform()->irq_controller()->get_irq(); - -} - - -Protection_id Platform_exception::protection_id() { - return _owner->protection_id(); } - - -addr_t Platform_exception::address(){ return (addr_t)_context->rear; } - - -bool Platform_exception::attempted_write_access(){ - return (_context->resr & Exec_context::RESR_ESS_DATA_TLB_MISS_S_MASK); } - - -static bool _trace_current_kernel_pass; - -void Verbose::begin__trace_current_kernel_pass() -{ - enum { - TRACED_PROTECTION_IDS = - sizeof(trace_these_protection_ids)/ - sizeof(trace_these_protection_ids[0]), - TRACED_THREAD_IDS= - sizeof(trace_these_thread_ids)/ - sizeof(trace_these_thread_ids[0]), - TRACED_EXCEPTION_IDS= - sizeof(trace_these_exception_ids)/ - sizeof(trace_these_exception_ids[0]), - TRACED_SYSCALL_IDS= - sizeof(trace_these_syscall_ids)/ - sizeof(trace_these_syscall_ids[0]) - }; - - - if (!Verbose::TRACE_KERNEL_PASSES || !_userland_context) { - _trace_current_kernel_pass = false; - return; - } - - if (!TRACE_ALL_THREAD_IDS) { - for (unsigned int i = 0;; i++) { - if (i >= TRACED_THREAD_IDS) { - _trace_current_kernel_pass = false; - return; - } - if (trace_these_thread_ids[i] == (Thread_id)_current_context_label) - break; - } - } - - if (!TRACE_ALL_PROTECTION_IDS) { - for (unsigned int i=0;; i++) { - if (i>=TRACED_PROTECTION_IDS) { - _trace_current_kernel_pass = false; - return; - } - if (trace_these_protection_ids[i] - == (Protection_id)_userland_context->rpid) { - _trace_current_kernel_pass = true; - _prints_chr1('\n'); - return; - } - } - } - - if (_userland_context->blocking_type == Exec_context::IRQ_BLOCKING - && !TRACE_ALL_IRQ_IDS) { - - _trace_current_kernel_pass = false; - return; - } - - if (_userland_context->blocking_type == Exec_context::EXCEPTION_BLOCKING - && !TRACE_ALL_EXCEPTION_IDS) { - - for (unsigned int i=0;; i++) { - - if (i >= TRACED_EXCEPTION_IDS) { - _trace_current_kernel_pass = false; - return; - } - if (trace_these_exception_ids[i] == - (Exception_id)_userland_context->exception_cause()) { - - _trace_current_kernel_pass = true; - _prints_chr1('\n'); - return; - } - } - } - - if (_userland_context->blocking_type == Exec_context::EXCEPTION_BLOCKING - && !TRACE_ALL_EXCEPTION_IDS) { - - for (unsigned int i = 0;; i++) { - if (i >= TRACED_EXCEPTION_IDS) { - _trace_current_kernel_pass = false; - return; - } - if (trace_these_exception_ids[i] == (Exception_id)_userland_context->r31) { - _trace_current_kernel_pass=true; - _prints_chr1('\n'); - return; - } - } - } - _trace_current_kernel_pass = false; -} - - -bool Kernel::Verbose::trace_current_kernel_pass() -{ - return _trace_current_kernel_pass; -} - - -void Platform::_on_kernel_entry__trace__thread_interrupts() -{ - if (!PLATFORM__TRACE) return; - if (!Verbose::trace_current_kernel_pass()) return; - - _prints_str0("block("); - _prints_hex2((char)_userland_context->rpid); - _prints_str0(":"); - _prints_hex8(_userland_context->rpc); - _prints_str0(":"); - _prints_hex2((char)_userland_context->blocking_type); - - char subtype=0; - if (_userland_context->blocking_type == Exec_context::IRQ_BLOCKING){ - subtype=(char)platform()->irq_controller()->next_irq(); - } else if (_userland_context->blocking_type == Exec_context::EXCEPTION_BLOCKING){ - subtype=(char)_userland_context->resr; - } else if (_userland_context->blocking_type == Exec_context::SYSCALL_BLOCKING){ - subtype=(char)_userland_context->r31; - } - - _prints_str0(":"); - _prints_hex2(subtype); - _prints_str0(") "); -} diff --git a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/userland_entry.s b/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/userland_entry.s deleted file mode 100755 index 3e129854b..000000000 --- a/base-mb/src/kernel/platforms/petalogix_s3adsp1800_mmu/userland_entry.s +++ /dev/null @@ -1,280 +0,0 @@ -/* - * \brief Userland entry - * \author Martin Stein - * \date 2010-10-05 - * - * Enter the userland via '_userland_entry' with execution context denoted in - * '_userland_context' - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -.global _userland_entry -.global _userland_context - -.global _kernel_timer_ctrl -.global _kernel_timer_ctrl_start - - -.macro _START_KERNEL_TIMER - swi r30, r0, _start_kernel_timer__buf_0 - swi r31, r0, _start_kernel_timer__buf_1 - - lwi r30, r0, _kernel_timer_ctrl - lwi r31, r0, _kernel_timer_ctrl_start - swi r31, r30, 0 - - lwi r30, r0, _start_kernel_timer__buf_0 - lwi r31, r0, _start_kernel_timer__buf_1 -.endm - - -.macro _START_KERNEL_TIMER__VARIABLES - .align 4 - _start_kernel_timer__buf_0: - .space 1*4 - .align 4 - _start_kernel_timer__buf_1: - .space 1*4 -.endm - - -.macro _MAY_BE_VERBOSE_USERLAND_ENTRY -/* - _PRINT_CONTEXT - _PRINT_ASCII_RUN -*/ -.endm - - -.macro _MAY_BE_VERBOSE_VARIABLES -/* - _PRINT_CONTEXT__VARIABLES - _PRINT_HEX32__VARIABLES - _PRINT_HEX8__VARIABLES - _PRINT_ASCII_SPACE__VARIABLES - _PRINT_ASCII_BREAK__VARIABLES - _PRINT_ASCII_RUN__VARIABLES - _PRINT_ASCII_STOP__VARIABLES -*/ -.endm - - -.macro _PREPARE_CONTEXT__USES_R2_TO_R31 - lwi r15, r0, _userland_context - - /* _PRELOAD_R1_R15_RPC_FROM_CONTEXT__USES_R3_R15 */ - lwi r3, r15, 1*4 - swi r3, r0, _preloaded_r1 - lwi r3, r15, 15*4 - swi r3, r0, _preloaded_r15 - lwi r3, r15, 32*4 - swi r3, r0, _preloaded_rpc - - /* _LOAD_RPID_FROM_CONTEXT__USES_R3_R15 */ - lwi r3, r15, 36*4 - mts rpid, r3 - - /* _SYNCHRONIZING_OP */ - bri 4 - - /* _LOAD_RMSR_FROM_CONTEXT__USES_R3_R4_R15 */ - lwi r3, r15, 33*4 - mts rmsr, r3 - - /* _SYNCHRONIZING_OP */ - bri 4 - - /* _LOAD_R2_TO_R13_FROM_CONTEXT__USES_R2_TO_R13_R15 */ - lwi r2, r15, 2*4 - lwi r3, r15, 3*4 - lwi r4, r15, 4*4 - lwi r5, r15, 5*4 - lwi r6, r15, 6*4 - lwi r7, r15, 7*4 - lwi r8, r15, 8*4 - lwi r9, r15, 9*4 - lwi r10, r15, 10*4 - lwi r11, r15, 11*4 - lwi r12, r15, 12*4 - lwi r13, r15, 13*4 - - /* _LOAD_R18_TO_R31_FROM_CONTEXT__TO_R15_R18_TO_R31 */ - lwi r18, r15, 18*4 - lwi r19, r15, 19*4 - lwi r20, r15, 20*4 - lwi r21, r15, 21*4 - lwi r22, r15, 22*4 - lwi r23, r15, 23*4 - lwi r24, r15, 24*4 - lwi r25, r15, 25*4 - lwi r26, r15, 26*4 - lwi r27, r15, 27*4 - lwi r28, r15, 28*4 - lwi r29, r15, 29*4 - lwi r30, r15, 30*4 - lwi r31, r15, 31*4 -.endm - - -.macro _EXEC_PREPARED_CONTEXT_CASE_INTERRUPT - lwi r14, r0, _preloaded_rpc - lwi r1, r0, _preloaded_r1 - lwi r15, r0, _preloaded_r15 - - _MAY_BE_VERBOSE_USERLAND_ENTRY - _START_KERNEL_TIMER - - rtid r14, 0 - or r0, r0, r0 -.endm - - -.macro _EXEC_PREPARED_CONTEXT_CASE_EXCEPTION - lwi r1, r0, _preloaded_r1 - lwi r17, r0, _preloaded_rpc - lwi r15, r0, _preloaded_r15 - - _MAY_BE_VERBOSE_USERLAND_ENTRY - _START_KERNEL_TIMER - - rted r17, 0 - or r0, r0, r0 -.endm - - -.macro _EXEC_PREPARED_CONTEXT_CASE_SYSCALL - lwi r1, r0, _preloaded_r1 - lwi r15, r0, _preloaded_rpc - - _MAY_BE_VERBOSE_USERLAND_ENTRY - _START_KERNEL_TIMER - - rtbd r15, 8 - or r0, r0, r0 -.endm - - -.macro _EXEC_PREPARED_CONTEXT_CASE_INITIAL - - lwi r14, r0, _preloaded_rpc - lwi r1, r0, _preloaded_r1 - lwi r15, r0, _preloaded_r15 - - /* _ENABLE_EXCEPTIONS */ - msrset r0, 0x100 - - /*_SYNCHRONIZING_OP */ - bri 4 - - _START_KERNEL_TIMER - - rtid r14, 0 - or r0, r0, r0 -.endm - - -.macro _SWITCH_USERLAND_BLOCKING_TYPE__USES_R3_R15 - lwi r15, r0, _userland_context - - /* _LOAD_BLOCKING_TYPE_FROM_CONTEXT__USES_R3_R15 */ - lwi r3, r15, 37*4 -.endm - - -.macro _CASE_INITIAL__USES_R4_R3 - xori r4, r3, 0 - bnei r4, _end_case_initial -.endm - - -.macro _CASE_INTERRUPT__USES_R4_R3 - xori r4, r3, 1 - bnei r4, _end_case_interrupt -.endm - - -.macro _CASE_EXCEPTION__USES_R4_R3 - xori r4, r3, 2 - bnei r4, _end_case_exception -.endm - - -.macro _CASE_SYSCALL__USES_R4_R3 - xori r4, r3, 3 - bnei r4, _end_case_syscall -.endm - - -/* _BEGIN_READABLE_EXECUTABLE */ -.section ".text" - - _userland_entry: - _SWITCH_USERLAND_BLOCKING_TYPE__USES_R3_R15 - _CASE_INTERRUPT__USES_R4_R3 - - _PREPARE_CONTEXT__USES_R2_TO_R31 - _EXEC_PREPARED_CONTEXT_CASE_INTERRUPT - /* userland execution */ - - _end_case_interrupt: - _CASE_EXCEPTION__USES_R4_R3 - - _PREPARE_CONTEXT__USES_R2_TO_R31 - _EXEC_PREPARED_CONTEXT_CASE_EXCEPTION - /* userland execution */ - - _end_case_exception: - _CASE_SYSCALL__USES_R4_R3 - - _PREPARE_CONTEXT__USES_R2_TO_R31 - _EXEC_PREPARED_CONTEXT_CASE_SYSCALL - /* userland execution */ - - _end_case_syscall: - _CASE_INITIAL__USES_R4_R3 - - _PREPARE_CONTEXT__USES_R2_TO_R31 - _EXEC_PREPARED_CONTEXT_CASE_INITIAL - /* userland execution */ - - _end_case_initial: - _case_default: - - /* _ERROR_UNKNOWN_USERLAND_BLOCKING_TYPE */ - brai 0x99000003 - - /* system halted */ - - _end_case_default: - _end_switch_userland_blocking_type: - _end_userland_entry: - - -/* _BEGIN_READABLE_WRITEABLE */ -.section ".bss" - - .align 4 - _kernel_timer_ctrl: .space 1*4 - .align 4 - _kernel_timer_ctrl_start: .space 1*4 - _START_KERNEL_TIMER__VARIABLES - - /* _VARIABLES_TO_READ_EXEC_CONTEXT */ - .align 4 - _preloaded_r1: .space 4 - .align 4 - _preloaded_r15: .space 4 - .align 4 - _preloaded_rpc: .space 4 - - _MAY_BE_VERBOSE_VARIABLES - - .align 4 - _userland_context: .space 1*4 - diff --git a/base-mb/src/platform/_main_helper.h b/base-mb/src/platform/_main_helper.h deleted file mode 100644 index 5e2d2a78f..000000000 --- a/base-mb/src/platform/_main_helper.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Martin Stein - * \date 2010-09-13 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SRC__PLATFORM___MAIN_HELPER_H_ -#define _SRC__PLATFORM___MAIN_HELPER_H_ - -#include -#include -#include -#include - -using namespace Genode; - -extern Genode::Native_utcb* _main_utcb_addr; -extern Genode::Native_thread_id _main_thread_id; - - -Native_utcb* main_thread_utcb() { return _main_utcb_addr; } - - -static void main_thread_bootstrap() -{ - /* - * main thread has no Thread_base but he gets some informations about - * itself deposited by the programs parent - */ - - /* - * If we're another mainthread than that of core we overwrite the - * utcb-address with that one genode takes by convention for mainthreads on - * microblaze - */ - int volatile pid; - asm volatile ("mfs %0, rpid" : "=r"(pid) : :); - if (pid!=Roottask::PROTECTION_ID) { - _main_utcb_addr = (Native_utcb*)((Native_config::context_area_virtual_base() - + Native_config::context_area_virtual_size()) - - sizeof(Native_utcb)); - } - - _main_thread_id=*((Native_thread_id*)main_thread_utcb()); -} - -#endif /* _SRC__PLATFORM___MAIN_HELPER_H_ */ diff --git a/base-mb/src/platform/genode.ld b/base-mb/src/platform/genode.ld deleted file mode 100755 index c140c02d9..000000000 --- a/base-mb/src/platform/genode.ld +++ /dev/null @@ -1,115 +0,0 @@ -/* - * \brief Linker script for Genode programs - * \author Christian Helmuth - * \date 2006-04-12 - */ - -/* - * Copyright (C) 2006-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -ENTRY(_start) - -PHDRS -{ - ro PT_LOAD FLAGS(5); - rw PT_LOAD FLAGS(6); -} - -SECTIONS -{ - . = 0x90000000; - _program_image_begin = .; - _executable_readable_begin = .; - - .text : { - *(.Atomic_ops) - - . = ALIGN(1<<12); - *(.Elf_entry) - *(.text .text.* .gnu.linkonce.t.*) - *(.fini) - *(.rodata .rodata.* .gnu.linkonce.r.*) - - . = ALIGN(1<<3); - _ctors_start = .; - KEEP (*(.ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.init_array)) /* list of constructors specific for ARM eabi */ - _ctors_end = .; - _dtors_start = .; - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - _dtors_end = .; - - } : ro = 0x90909090 - - /* Linux: exception section for uaccess mechanism */ - __ex_table : { *(__ex_table) } - - .eh_frame_hdr : { *(.eh_frame_hdr) } - _executable_readable_end = .; - - . = ALIGN(1<<12); - _writable_readable_begin = .; - - .data : SUBALIGN(1<<12) { - /* - * Leave space for parent capability parameters at start of data - * section. The protection domain creator is reponsible for storing - * sane values here. - */ - _parent_cap = .; - _parent_cap_thread_id = .; - LONG(0xffffffff); - _parent_cap_local_name = .; - LONG(0xffffffff); - - *(.data .data.* .gnu.linkonce.d.*) - } : rw - - /* exception frames for C++ */ - .eh_frame : { - __eh_frame_start__ = .; - KEEP (*(.eh_frame)) - LONG(0) - } : rw - - .init_array : { - __init_array_start = .; - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - __init_array_end = .; - } - - .gcc_except_table : { KEEP(*(.gcc_except_table)) } - .dynamic : { *(.dynamic) } - - /* .ARM.exidx is sorted, so has to go in its own output section */ - __exidx_start = .; - .ARM.exidx : { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } - __exidx_end = .; - - .ARM.extab : { - *(.ARM.extab*) - } : rw - - .bss : { - *(.bss .bss.* .gnu.linkonce.b.* COMMON) - } - - /* end of program image -- must be after last section */ - _writeable_readable_end = .; - _program_image_end = .; - - /DISCARD/ : { - *(.note) - *(.note.ABI-tag) - *(.comment) - } -} diff --git a/base-mb/src/test/hello/main.cc b/base-mb/src/test/hello/main.cc deleted file mode 100644 index 446fcf0c7..000000000 --- a/base-mb/src/test/hello/main.cc +++ /dev/null @@ -1,23 +0,0 @@ -/* - * \brief Hello world - * \author Norman Geske - * \date 2011-02-22 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -using namespace Genode; - -int main(int argc, char **argv) -{ - printf("Hello world!\n"); - return 0; -} diff --git a/base-mb/src/test/hello/target.mk b/base-mb/src/test/hello/target.mk deleted file mode 100644 index 2505d5ffa..000000000 --- a/base-mb/src/test/hello/target.mk +++ /dev/null @@ -1,3 +0,0 @@ -TARGET = hello -SRC_CC = main.cc -LIBS = base diff --git a/base/include/base/thread.h b/base/include/base/thread.h index 469dacae5..3eff6a0d2 100644 --- a/base/include/base/thread.h +++ b/base/include/base/thread.h @@ -230,9 +230,6 @@ namespace Genode { */ void _deinit_platform_thread(); - /* hook only used for microblaze kernel */ - void _init_context(Context* c); - protected: /** diff --git a/base/mk/global.mk b/base/mk/global.mk index e9eac825b..7be10f3b8 100644 --- a/base/mk/global.mk +++ b/base/mk/global.mk @@ -119,8 +119,8 @@ CC_ADA_OPT += $(CC_OLEVEL) $(CC_WARN) # Linker options # # Use '-gc-sections' by default but allow a platform to disable this feature by -# defining 'LD_GC_SECTIONS' empty. This is needed for the microblaze tool chain -# (gcc version 4.11 and binutils version 2.16), which happens to produce broken +# defining 'LD_GC_SECTIONS' empty. This is needed for older tool chains (gcc +# version 4.11 and binutils version 2.16), which happen to produce broken # code when '-gc-sections' is enabled. # LD_OPT_GC_SECTIONS ?= -gc-sections diff --git a/doc/challenges.txt b/doc/challenges.txt index 2ddbf2a38..8f36d4859 100644 --- a/doc/challenges.txt +++ b/doc/challenges.txt @@ -386,15 +386,6 @@ Platforms The goal of this project is to evaluate how small the Linux kernel can get when used as a microkernel. -:Support for the Genode FPGA Graphics SoC platform: - - With Genode 11.02, we introduced the first version of native support for the - MicroBlaze softcore CPU. With this foundation laid, we can proceed with - bringing GUI-based interactive Genode applications to FPGA-based SoC - platforms. As target SoC design, we aspire to use the open-source IP cores - provided by the - [http://genode-labs.com/products/fpga-graphics - Genode FPGA graphics project]. - :Support for the HelenOS/SPARTAN kernel: [http://www.helenos.org - HelenOS] is a microkernel-based multi-server OS diff --git a/tool/builddir/etc/build.conf.mb_ml507 b/tool/builddir/etc/build.conf.mb_ml507 deleted file mode 100644 index a614cd23e..000000000 --- a/tool/builddir/etc/build.conf.mb_ml507 +++ /dev/null @@ -1,2 +0,0 @@ -REPOSITORIES = $(GENODE_DIR)/base-mb -RUN_OPT += --qemu qemu-mb_s3a_starter_kit diff --git a/tool/builddir/etc/build.conf.mb_s3a_starter_kit b/tool/builddir/etc/build.conf.mb_s3a_starter_kit deleted file mode 100644 index a614cd23e..000000000 --- a/tool/builddir/etc/build.conf.mb_s3a_starter_kit +++ /dev/null @@ -1,2 +0,0 @@ -REPOSITORIES = $(GENODE_DIR)/base-mb -RUN_OPT += --qemu qemu-mb_s3a_starter_kit diff --git a/tool/create_builddir b/tool/create_builddir index d19d7528c..ed5206e7b 100755 --- a/tool/create_builddir +++ b/tool/create_builddir @@ -26,7 +26,6 @@ usage: @echo " 'nova_x86_32'" @echo " 'nova_x86_64'" @echo " 'codezero_vpb926'" - @echo " 'mb_s3a_starter_kit'" @echo " 'hw_panda'" @echo " 'hw_vea9x4'" @echo " 'hw_pbxa9'" @@ -182,12 +181,6 @@ foc_imx53:: codezero_vpb926:: @echo "CODEZERO_DIR = $(GENODE_DIR)/base-codezero/contrib" > $(BUILD_DIR)/etc/codezero.conf -mb_s3a_starter_kit:: - @echo "SPECS = genode mb_s3a_starter_kit" > $(BUILD_DIR)/etc/specs.conf - -mb_ml507:: - @echo "SPECS = genode mb_ml507" > $(BUILD_DIR)/etc/specs.conf - hw_pbxa9:: @echo "SPECS = genode hw_pbxa9" > $(BUILD_DIR)/etc/specs.conf