LLVM JIT on a Baremetal x86 Machine !!!

Dear All,

I have tested a few examples of LLVM-JIT Framework on Linux x86 Machine.
So generating functions on the fly and then executing them is OK on linux i.e. i686-pc-linux-gnu

My question is:

Can we use the LLVM-JIT on a baremetal x86 machine ? Actually my target is a virtual machine, and I need some dynamic code generation support. I intend to use LLVM-JIT (if possible) for this purpose.

Furthermore if it is possible, then how much effort would be required ? And where should I start looking for doing this kind of port.

Thanks for your help.

Hi Mian,

I have actually done this. I wrote a safe bytecode which compiles down to
LLVM IR, and had baremetal applications running using it.

Code here:
http://www.quokforge.org/projects/horizon/repository/revisions/master/show/h
orizon/Baremetal

My method was to compile for hosted linux, then modify the resulting code to
run baremetal. For me, this involved rewriting "syscall" instructions to
"int $X" as everything was running in supervisor mode and "syscall" only
works from user mode.

Apart from that there's just a load of stubs to implement. Pretty easy
really.

Cheers,

James

Hi Mian,

Looking at the runlog, everything seems fine until LLVM attempts to use lseek() on a file.

You see the PANIC because Horizon hasn't implemented lseek yet.

Obviously the version of GlibC I was using does not use lseek in that circumstance, but yours does. You just need to implement lseek :slight_smile:

Cheers,

James

Hi James,

I have two questions for you.

Firstly, what is the role of 'module' in init.cc? I can see that its being treated like it is a 'bytecode' file, as we open it and then pass it to the ByteCoder and eventually construct llvm module from it.

Like In file init.cc, line:121
     FILE *stream = fopen("/module", "rb");
     ...
     fread(c, 1, sz, stream);
     ...
     Bytecoder bc(std::cout, c, sz, &errors);
     ...

The Open SysCall returns a pointer to the 'Special File' that was created in 'InitialiseSpecialFiles':
In file SpecialFile.cc, line:204, its defined as a special file:
     static SpecialModule modl("/module");
     s_files[3] = &modl;

Is this 'module' somehow related to 'KERNEL_HBC' that we specified earlier ?
If yes then how I am getting the size of this special file to be zero, whereas the size of my 'hello_world.hbc' is 225 bytes.
If no, then what is it ?

Secondly You have mentioned on the Horizon wiki:
"The build process will produce a version of horizon statically linked with code that provides enough of a UNIX environment for LLVM and libstdc++ to function"

Could you please shed some more light on this aspect (Some links, if possible), on how you have accomplished this ?
I am not an expert in these aspects, your help in this regard will be highly appreciated.

run.log (4.21 KB)

SpecialFile.cc (10.1 KB)

syscallHandlers.cc (11.8 KB)

Hi,

First question: "/module" is mapped to a special file that reads a kernel module passed in by the bootloader. Much like GRUB, kiwi's bootloader loads a kernel and can load one or more extra files into memory. These are passed to the kernel.

The horizon kernel expects one file, which it makes accessible at "/module". This should be set up to be whatever you set KERNEL_HBC to be.

Second question: The program is statically compiled on the host system against the host C and C++ libraries. Then, it is patched slightly to change linux syscall instructions to "int 0xff" instructions, which get trapped at runtime.

At build time it reads your linux kernel headers to find what syscall numbers map to what syscalls, and emulates a subset of the linux kernel. This is how the C standard library etc works.

Cheers,

James

Hi James,

Thanks again for bearing with me, you have been very helpful.

I have got the problem fixed. In fact I needed to override the 'LSeek' implementation of SpecialFile in SpecialModule class as well.
The log for the working example is attached, just as a reference.

Now one more thing, when the build system creates the ISO9660 CD-ROM Image, it executes the following commands:

mkdir -p /tmp/hzn/boot
mkdir -p /tmp/hzn/kiwi/modules
cp /altamaha/home3/hamayun/workspace/horizon/horizon/Baremetal/boot/cdboot.img /tmp/hzn/boot
cp embedded /tmp/hzn/kiwi/kernel
cp /altamaha/home3/hamayun/workspace/horizon/code-samples/hello_world.hbc /tmp/hzn/kiwi/modules/hbc
mkisofs -quiet -J -R -l -b boot/cdboot.img -V Horizon\ CD-ROM -boot-load-size 4 -boot-info-table -no-emul-boot -o cd.img /tmp/hzn

In the third line above, the file "cdboot.img" is being copied. Is this only a bootloader or does it also contain an OS Kernel ? (Like for example the kernel of kiwi os)
And where can I find the sources to this "cdboot.img" file ? I mean if I need to modify/recreate this file, how can I do that.

Best Regards,
Hamayun

run.log (7.3 KB)

Hi,

Glad you got it working! :slight_smile:

The image contains the kiwi bootloader and any files it needs - that's it. It was generated by building kiwi-os, which is a hobby operating system written by Alex Smith (http://kiwi.alex-smith.me.uk/).

Cheers,

James