Live data from Hacker News

Kernel 101 – Let’s write a Kernel

arjunsreedharan.org

81–90 of 104 posts

Re: Kernel 101 – Let’s write a Kernel

#81
post #77

This seems like a good start but it's worth noting that it isn't guaranteed to work correctly. The problem is that the control is passed to C code with no stack space set up. It works out of pure luck because the compiler has decided to keep all variables in registers and changing your C compiler flags might make this fail in interesting ways. Another thing that is missing is clearing the .BSS section before passing…

> Another thing that is missing is clearing the .BSS section before passing control to the C code. It's not used at the moment, though. The Multiboot standard says that the boot loader will clear the .bss section for you - in section 3.1.3: "bss_end_addr Contains the physical address of the end of the bss segment. The boot loader initializes this area to zero" I don't know what GRUB does if you rely on that fact it c…

> The Multiboot standard says that the boot loader will clear the .bss section for you - in section 3.1.3: "bss_end_addr Contains the physical address of the end of the bss segment. The boot loader initializes this area to zero"

Ok, good to know.

It certainly doesn't do that unless you tell it to (using the address tag), and this example (nor my hobby kernel) use that.

So the BSS must be cleared or the bootloader told to do so.

Re: Kernel 101 – Let’s write a Kernel

#82

I got this running on qemu by cannibalizing a tiny bit of code from xv6 ( http://pdos.csail.mit.edu/6.828/2012/xv6.html ) to replace the GRUB dependency. After cloning and building mkernel according to its instructions: $ git clone git://pdos.csail.mit.edu/xv6/xv6.git $ cd xv6 $ make Now you should be able to run xv6 by itself: $ path-to-qemu/x86_64-softmmu/qemu-system-x86_64 -serial mon:stdio -hdb fs.img xv6.img -m…

> I got this running on qemu by cannibalizing a tiny bit of code from xv6 to replace the GRUB dependency.

This thing doesn't depend on GRUB, per se. It requires a multiboot protocol compliant bootloader, and QEMU and Bochs emulator have one built-in.

All you need to do is:

    qemu-system-i386 -kernel kernel
This was mentioned in the last lines of the OP, perhaps they were added after you read it.

Re: Kernel 101 – Let’s write a Kernel

#83

If anybody is doing this, let me share some words of advice based on experience. Please use a virtual machine instead of doing this on your primary machine. You eliminate the risk of messing up your machine. Also, if you setup the VM properly, you get a debugger.

It's still important to test on physical hardware though, perhaps on an old spare machine you don't care about if you want to be cautious, as the virtual machines do not perfectly emulate real hardware. For example, QEMU initializes memory to all zeroes, whereas on a real system it's typically all ones, which led to some interesting bugs in my OS on real hardware where I had forgotten to zero out some memory.

Re: Kernel 101 – Let’s write a Kernel

#84

Very cool. I personally (as a developer without a CS background) find these sorts of posts wonderfully interesting, even if this kernel, as pointed out in this thread, lacks a lot of what a normal kernel does. I'd love to see one of these for a compiler!

I highly recommend http://www.hokstad.com/compiler/ ; it talks about writing a compiler in a way that makes sense to me - writing it the way you write any other program, rather than throwing you straight in with lexers and parsers and never justifying why we need to do things this way.

Re: Kernel 101 – Let’s write a Kernel

#86
post #81

Earlier quoted context omitted.

> Another thing that is missing is clearing the .BSS section before passing control to the C code. It's not used at the moment, though. The Multiboot standard says that the boot loader will clear the .bss section for you - in section 3.1.3: "bss_end_addr Contains the physical address of the end of the bss segment. The boot loader initializes this area to zero" I don't know what GRUB does if you rely on that fact it c…

> The Multiboot standard says that the boot loader will clear the .bss section for you - in section 3.1.3: "bss_end_addr Contains the physical address of the end of the bss segment. The boot loader initializes this area to zero" Ok, good to know. It certainly doesn't do that unless you tell it to (using the address tag), and this example (nor my hobby kernel) use that. So the BSS must be cleared or the bootloader tol…

I've just checked the GRUB source code and I think it will clear the .bss section even if it's loading an ELF file.

grub-core/loader/multiboot_elfxx.c has a function named grub_multiboot_load_elf32/64 which actually loads the segments of the ELF file. A segment has two fields defining its size: filesz (which is the amount of bytes to copy from the file) and memsz (which is its actual size once loaded). If memsz is greater than filesz, it zeroes the trailing bytes:

  if (phdr(i)->p_filesz p_memsz)
    grub_memset ((grub_uint8_t *) source + phdr(i)->p_filesz, 0,
      phdr(i)->p_memsz - phdr(i)->p_filesz);
The .bss section is placed by the linker at the end of a segment and increases memsz by the size of it (but not filesz, to avoid having to place lots of pointless zeroes in the ELF file) - for example this is one of the segments from my kernel's ELF file, which contains the .bss section at the end:

  LOAD off    0x0000000000020000 vaddr 0xffffffff8011f000 paddr 0x000000000011f000 align 2**12
       filesz 0x0000000000004be0 memsz 0x0000000000017678 flags rw-
Here you can see memsz is 0x17678 bytes and filesz is smaller at 0x4be0 bytes. The difference between them is the size of the .bss section.

grub_multiboot_load_elf32/64 is called in the case when the address tag is not present, so the .bss section will be cleared by GRUB in this case as well.

Re: Kernel 101 – Let’s write a Kernel

#87
post #79
post #24

Can anyone give me an idea how much different this would be for 64bit? Do I just change the nasm directive to `bits 64`?

> Can anyone give me an idea how much different this would be for 64bit? Do I just change the nasm directive to `bits 64`? A lot different. You can see the boot code of my x86_64 hobby kernel project [1]. The reason is that GRUB/Multiboot protocol is actually doing most of the machine initialization, but it can only set up 32 bit mode. 64 bit mode is missing partly because standardizing the Multiboot protocol is drag…

This makes me really sad. 32bit mode x86 assembly is such a mess compared to amd64 -- I guess it's a good excuse to work with qemu and arm, if nothing else ;-)

Re: Kernel 101 – Let’s write a Kernel

#88

Why C? I'm just curious if another language can be used. (c++, go, rust).

C is (pretty) easy to use as a structured, portable assembler (eg: you get loops, easy-to-use variables, which you don't have in assembly) -- and easy to interface with assembly.

Pascal might be another good alternative -- as it also doesn't require a run-time. I don't think go will ever (officially) support this kind of thing, rust most likely will.

For an example of something that's not C, have a look at Marte OS, implemented in ADA:

http://marte.unican.es/

Re: Kernel 101 – Let’s write a Kernel

#89
post #84

Very cool. I personally (as a developer without a CS background) find these sorts of posts wonderfully interesting, even if this kernel, as pointed out in this thread, lacks a lot of what a normal kernel does. I'd love to see one of these for a compiler!

I highly recommend http://www.hokstad.com/compiler/ ; it talks about writing a compiler in a way that makes sense to me - writing it the way you write any other program, rather than throwing you straight in with lexers and parsers and never justifying why we need to do things this way.

Glad you like it... I'm hoping to push out the next part later this week, and I've got a few more drafts queued up that "just" needs some proofreading.

Working on getting it to the point where it can fully compile itself now, and hope to get there over the couple of months.

Re: Kernel 101 – Let’s write a Kernel

#90
post #5

I'm not exactly Linus Torvalds but I'm pretty sure a program that prints one line of text is not "a kernel". :)

Let me rephrase. This is _bootstrap code_ for something that might someday be a kernel. It could also be bootstrap code for something else, a game perhaps. But right now it's nothing else.
Post reply on HN