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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 $(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