Hi all.
I am now giving a try to the Genode OS framework. I like it's concepts and ideas and its elegant design, and maybe, will migrate to it eventually. -- I was developing an OS/2 clone based on Fiasco microkernel and l4env. Now they're discontinued. So, I must probably, migrate to something else. The most probable candidates are L4Re or Genode. I like Genode because of its kernel-neutrality (It can work on any L4 flavour, it is very attractive feature) and has interesting ideas regarding the scalability and capability to build a hierarchy of subsystems, minimising the application-specific Trusted Computing Bases.
So, as I understood, it abstracts the kernel specifics from a developer. But in some cases, it can be desirable to make some kernel-specific implementations. For example, Fiasco kernel based on l4v2 API has 'segments' feature which, for example, is actively used by L4Linux. We use this feature too. One of our objectives is a binary compatibility with existing OS/2 applications. And OS/2 application ABI includes a convention that FS register for Ring3 application, holds a selector of a structure named Thread Info Block. Though the application can obtain this structure by calling an DosGetInfoBlocks() API, the C startup code generated by many compilers, relies on the convention that FS must contain the TIB selector. So, if we try to implement this feature on L4, we must have the means to allocate GDT selectors and get the allocated selector. On Fiasco, this can be done by filling the registers in a special way and issuing a 'LLDT' instruction, or, by calling a fiasco_gdt_set() function, and get the allocated selector by fiasco_gdt_get_entry_offset() (which is the same, but through a 'l4sys' package). On Fiasco.OC, this can be done similar way (not through LLDT instruction, though).
My question is: Can be the underlying kernel determined under Genode, and then try doing kernel-specific things? Or, maybe, there is a more elegant way to do kernel-specific things?
Thanks in advance, valery.
PS: On Pistachio, as I heard, the application also can operate on GDT selectors, but this possibility has even more limitations. (It seems, only LDT selectors can be altered, but not GDT ones, or something)
Hi Valery,
thanks for your nice words about the Genode OS Framework.
My question is: Can be the underlying kernel determined under Genode, and then try doing kernel-specific things? Or, maybe, there is a more elegant way to do kernel-specific things?
There the three feasible approaches to integrate kernel-specific code: a separate repository that shadows parts of the other repositories, by using hack-ish preprocessor defines specified via the compiler command line (not recommended), or by using specialized libraries (highly recommended). I will shortly describe each of these ways.
When building, the Genode build system considers all directory trees specified as 'REPOSITORIES' in the '<build-dir>'/etc/build.conf' file. If two files with the same name are present in two repositories, the version of the foremost repository is picked. For example, let's assume you have a custom repository called 'yourrepo' and you want to customize the thread library normally described in 'base-foc/lib/mk/thread.mk', you can just create a custom version of the library description file 'yourrepo/lib/mk/thread.mk'. If the 'REPOSITORIES' declaration has 'yourrepo' listed in front of the 'base-foc' repository, your version will be picked up by the build system. The same shadowing mechanism applies to header files, which enables you to easily replace each original header that come with Genode with a specific version provided by 'yourrepo/include'. You can see this approach at work with the separation of generic base code (located at the 'base' repository) and platform-specific base code (located at the 'base-<platform>' repository). Because 'base-<platform>' is specified in front of 'base' in the 'REPOSITORIES' declaration, the platform-specific code is able to shadow generic code.
The second approach is specifying a '-DHAS_SPECIAL_FEATURE' definition at the compiler's command line and to wrap the kernel-specific code via classical preprocessor directives '#ifdef HAS_SPECIAL_FEATURE'-'#endif'. This is the typical solution as employed in most GNU projects. In principle, it can be used on Genode as well by introducing a new 'SPEC' (see Genode's getting-started documents for more details about the SPECS mechansism). All you need is creating a new file 'yourrepo/mk/spec-your_special_feature.mk'. In this file, extend the compiler arguments by 'CC_OPT += -DHAS_SPECIAL_FEATURE'. Now, you can enable the special feature in your build directory by manually extending the 'SPECS' variable in your '<build-dir>/etc/specs.conf' file: 'SPECS += has_special_feature'. This tells the build system to look for a file called 'spec-your_special_feature.mk' in all 'mk' subdirectories of all repositories. Hence, it will pick up your file with your 'CC_OPT' extension. However, I recommend to avoid '#ifdef'-'#endif' customizations because this facilitates the intermixing of platform-dependent with generic code, leading to code that is hard to maintain and difficult to test.
The actually recommended way is to encapsulate the specialized code in a dedicated library that implements a common interface. For example, at 'os/include/blit/blit.h', you find an interface for a 2D blitting function. There exist two implementations of this interface, a generic version and a version specialized for x86 using MMX instructions. The library description file of the generic version is located at 'os/lib/mk/blit.mk'. So if a program wants to use the blit interface, it just specifies 'LIBS += blit'. Normally, the build system will then process the 'blit.mk' file. However, there exists a second version at 'os/lib/mk/x86_32/blit.mk'. If the 'SPECS' variable defined at the build directory contains 'x86_32', the build system will automatically look in a subdirectory called 'x86_32' within each 'lib/mk' directory for specialized versions. This is a fairly generic mechanism - specialized code is provided by a specialized library that implements a generic interface. At build time, the definition of the 'SPECS' variable tells the build system where to look for specialized library description files. In your particular case, when building for Fiasco.OC, the 'SPECS' variable already contains 'foc'. So you can have a Fiasco.OC specific library implementation by simply providing a 'mk/foc/yourlib.mk' file.
Best regards Norman
On Sat, 05 Mar 2011 21:03:16 +0100, Norman Feske wrote:
Hi Valery,
There the three feasible approaches to integrate kernel-specific code: a separate repository that shadows parts of the other repositories, by using hack-ish preprocessor defines specified via the compiler command line (not recommended), or by using specialized libraries (highly recommended). I will shortly describe each of these ways.
...
Hi, Norman, thanks for your thorough answer. I expected that there is some API's or variables, like those in the Kernel Interface Page, and to check them at the runtime. But doing that at compile time is even better. Also, the build system feature with customising through SPECS is cool, it's like doing OOP with make :) An approach with REPOSITORIES is also nice, but several trees for one program maybe so much.
WBR, valery
PS: maybe, offtopic, but I'm in trouble a bit. -- I compiled Genode for Linux, but when starting Core, it cannot initialize a framebuffer device, writes that /dev/fb0 file doesn't exist and that I need to specify the FRAMEBUFFER variable or enable fbdev. I tried to load 'fbdev' module with modprobe, but such a module doesn't exist.
Sorry if it's a common FAQ, but I didn't worked with framebuffer device on Linux before that. What I must do to enable framebuffer? Need I load some driver?
l4-hackers@os.inf.tu-dresden.de