How to exec one kernel from inside another ?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
sawdust
Member
Member
Posts: 51
Joined: Thu Dec 20, 2007 4:04 pm

How to exec one kernel from inside another ?

Post by sawdust »

How do I exec one kernel from inside another ? e.g. I'm running say, pyros 1.0 and have binary of another version, say 2.0 kernel in a known location in the had disk.
A small driver copies that image and puts it in some memory location. Now if I want to exec the 2.0 kernel so that it takes complete control and starts to run, what should be done? Any help is appreciated.
Thanks in advance. [-o<
itisiuk
Member
Member
Posts: 98
Joined: Mon Mar 24, 2008 1:46 pm

Re: How to exec one kernel from inside another ?

Post by itisiuk »

sounds like a virtual machine if im not mistaken.
and by that u may want to look at the source code for qemu or bochs or something like that.
User avatar
Adek336
Member
Member
Posts: 129
Joined: Thu May 12, 2005 11:00 pm
Location: Kabaty, Warszawa
Contact:

Re: How to exec one kernel from inside another ?

Post by Adek336 »

No, I think he means aborting kernel_1 and booting kernel_2. Well I believe you'd need a function, say, kexec, which you make sure is in a memory place which will not be overwritten by kernel_2 and make sure that GDT will not be overwritten, same for IDT or turn off interrupts, then copy the kernel to the place it expects to be and do a jmp or something.
There are some complications as kernel_2 may expect hardware to be in an after-boot state so you might need to set the hardware to that state before passing control to kernel_2.
itisiuk
Member
Member
Posts: 98
Joined: Mon Mar 24, 2008 1:46 pm

Re: How to exec one kernel from inside another ?

Post by itisiuk »

soz my bad, i misunderstood what you ment.

for this you could map the new kernel into a region of mem using paging the load the effective address of new kernel into a register then jmp to that location.
1:1 mapping is probably best for this.
e.g.

lea eax, [newlocation]
jmp eax

and as Adek336 has said, you need to make sure the old kernel has setup the hardware state required by the new kernel.
i.e if paging is turned off when the new kernel 1st starts to run then youll need to make sure you turn paging off before you run the new kernel.
sawdust
Member
Member
Posts: 51
Joined: Thu Dec 20, 2007 4:04 pm

Re: How to exec one kernel from inside another ?

Post by sawdust »

:x My gmail was sending the replies to Spam :x.

As Adek336 said, I want to abort kernel_1 and jump and execute kernel_2. Yes. Hardware is already setup. I would want to load new GDT and IDT with new ISRs. I want to serve Interrupt services from kernel_2.
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Re: How to exec one kernel from inside another ?

Post by lukem95 »

overwrite the original kernel image on the HDD, then reboot
~ Lukem95 [ Cake ]
Release: 0.08b
Image
sawdust
Member
Member
Posts: 51
Joined: Thu Dec 20, 2007 4:04 pm

Re: How to exec one kernel from inside another ?

Post by sawdust »

lukem95 wrote:overwrite the original kernel image on the HDD, then reboot
Nope!. I don't want to reboot. Only 'exec'
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Re: How to exec one kernel from inside another ?

Post by inflater »

A quick and dirty way:

1. Add into your second kernel a "EXIT" function, which does the same as in the part 4.
2. Run your first kernel and copy the whole kernel somewhere in free memory. Something like relocation, but don't free your first kernel's occupied memory. Now, jump to the relocated part.
3. In your first kernel's relocated part, load the second kernel at ORG, where the first kernel is loaded. Then, run the second kernel by CALLing
4. When the "EXIT" function is called in your second kernel, relocate the following "code-copying" routines somewhere in the free memory, then JMP to them. In there, load the first kernel from it's original relocation and copy it to the second kernel's ORG. Then run it by restoring the first kernel's EIP, which should point right after e.g. "call RunSecondKernel" - make sure your stack is alright.
5. In your first kernel, free the relocated space and the relocated "code-copying" routines. (Not necessary.)

In this example, I assume that the ORG of both kernels are the same.

I highly recommend that your kernels are in assembly though. :? C/C++ is too high level to do that.

I've added an example code, but it's untested.

Code: Select all

*** First kernel ****
call RelocateFirstKernel                          ;e.g. copy your first kernel to 0x100000
...
*** this is the Load second kernel function ****
LoadThe2ndKernel:
jmp LoadThe2ndKernel+0x100004            ;jump to the relocated part at address 0x100000 plus this label's offset
                                                        ;but SKIP the JMP opcode in the reloc part!!! thats because its 0x100004
....
*** this is where it should begin ***
call LoadTheSecondKernelFromHDD          ;e.g. load your second kernel to first's ORG, thus overwriting the first to save RAM
                                                        ;but no worries, since we are in the relocated part
call dword[FirstKernel_Org]                     ;call the first kernel's ORG to load the 2nd one
*** in the 2nd kernel at the beginning ****
mov esi,SecondKernel_CodeCopy
mov ecx,0x200
mov edi,0x200000                                 ;reserve 512 bytes of the code copying routines and relocate to the 2nd megabyte
rep movsb
...
*** the code copying routines, DO NOT execute them directly as you'll overwrite the 2nd kernel ***
...
SecondKernel_CodeCopy:
mov esi,0x100000                                ;load the first kernel from the relocated part (1st megabyte)
mov ecx,Size_of_your_first_kernel_in_bytes
mov edi,[FirstKernel_Org]
rep movsb
...
;MAKE SURE YOUR STACK ISN'T SCREWED HERE!
;EVERY PUSH, PUSHAD, PUSHA etc MUST HAVE CORRESPONDING POP, POPAD, POPA, etc. !!!
ret                                                    ;This should return right after the "call RunSecondKernel", if your stack contents are alright.
...
** Second kernel's EXIT function ****
jmp sys_code:0x200000                        ;sys_code is your CS selector
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
sawdust
Member
Member
Posts: 51
Joined: Thu Dec 20, 2007 4:04 pm

Re: How to exec one kernel from inside another ?

Post by sawdust »

inflater wrote:A quick and dirty way:

1. Add into your second kernel a "EXIT" function, which does the same as in the part 4.
2. Run your first kernel and copy the whole kernel somewhere in free memory. Something like relocation, but don't free your first kernel's occupied memory. Now, jump to the relocated part.
3. In your first kernel's relocated part, load the second kernel at ORG, where the first kernel is loaded. Then, run the second kernel by CALLing
4. When the "EXIT" function is called in your second kernel, relocate the following "code-copying" routines somewhere in the free memory, then JMP to them. In there, load the first kernel from it's original relocation and copy it to the second kernel's ORG. Then run it by restoring the first kernel's EIP, which should point right after e.g. "call RunSecondKernel" - make sure your stack is alright.
5. In your first kernel, free the relocated space and the relocated "code-copying" routines. (Not necessary.)

In this example, I assume that the ORG of both kernels are the same.
Thanks a lot for your time inflater :). I'll give this one a try and let you know.
iammisc
Member
Member
Posts: 269
Joined: Thu Nov 09, 2006 6:23 pm

Re: How to exec one kernel from inside another ?

Post by iammisc »

linux has a similar mechanism to this called kexec. Why don't you research how linux does that?
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Re: How to exec one kernel from inside another ?

Post by inflater »

Who cares about linux?
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
User avatar
Adek336
Member
Member
Posts: 129
Joined: Thu May 12, 2005 11:00 pm
Location: Kabaty, Warszawa
Contact:

Re: How to exec one kernel from inside another ?

Post by Adek336 »

nobody but we care about kexec
sawdust
Member
Member
Posts: 51
Joined: Thu Dec 20, 2007 4:04 pm

Re: How to exec one kernel from inside another ?

Post by sawdust »

I did the following
first_kernel ORG = 0x200000 (@ 2MB)
second_kernel ORG = 0x39b00000 (begins at last 100MB of 1GB)
With the following code, I got an exception 'Invalid Opcode - code 0'. I was assuming that with jmp to the second_kernel's ORG, it should start executing.
Any help would be greatly appreciated. [-o< #-o

Code: Select all

static uint32_t _secondKernelEntry;
void cmain(unsigned long magic, multiboot_info_t *mbinfo)
{

    Elf32_Ehdr* ehdr;
    unsigned char *secondKernelImage = (unsigned char *)0x39b00000;
    
..........

// This function reads 256 sectors (128 KB) to memory area secondKernelImage
readSectors(startSector,sectorCount);
......
....

// cast the 2nd kernel image to elf header
    ehdr = (Elf32_Ehdr *)(secondKernelImage);
// get entry point of kernel_2
    _secondKernelEntry = ehdr->e_entry;
    printf("elf entry=0x%x\n",_secondKernelEntry);

    __asm__ __volatile__(
        "   cld	\n\t"
        "   pushl    %esi\n\t"
        "   pushl    %edi\n\t"
        "   pushl    %ebx\n\t"
        "   pushl    %eax\n\t"
        "   push     %gs\n\t"
        "   push     %fs\n\t"
        "   push     %ds\n\t"
        "   push     %es\n\t"

        "   leal    _secondKernelEntry ,%eax\n\t"
        "   jmp     *(%eax)\n\t"              /*'call' gives GPF */

        "   pop      %es\n\t"
        "   pop      %fs\n\t"
        "   pop      %gs\n\t"
        "   popl     %eax\n\t"
        "   popl     %ebx\n\t"
        "   popl     %edi\n\t"
        "   popl     %esi\n\t"
    );

printf ("should not come here");
........
.......
    return; 
}


User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Re: How to exec one kernel from inside another ?

Post by inflater »

Try to set both ORG's the same. And also I'm not really sure about ELF, I suggest to use binary format. Plus, running it in inline assembly is not a good idea, too.
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
JJeronimo
Member
Member
Posts: 202
Joined: Wed Oct 18, 2006 3:29 pm

Re: How to exec one kernel from inside another ?

Post by JJeronimo »

itisiuk wrote:and as Adek336 has said, you need to make sure the old kernel has setup the hardware state required by the new kernel.
i.e if paging is turned off when the new kernel 1st starts to run then youll need to make sure you turn paging off before you run the new kernel.
IMHO makes much more sense inventing a "hot load" protocol for the kernel.

This could include a special entry point for hot boots (or a special boot-time parameter so that the kernel knows it's being executed from inside a running system), that would skip paging and memory initialization. Additional information could also be passed, such as addresses for kernel structures and stuff alike.
*Skipping* driver initialization seems to be the difficult part. However, if a hot-swappable kernel fails to support this, the entire feature can become in part void (because the advantage of a kexec-like feature is precisely avoiding the delays introduced by system reboots).
Here, a microkernel has the advantage of allowing to fastly replace the micro-kernel (which needs minimal initialization, because it is micro :-) ), and then replace the servers one-at-a-time, thus allowing for +/- continuous system responsiveness.

The problem is that some drivers may need to re-initialize it's hardware, and others may not need. Also, the same problem arises if you change e.g. the memory management structure's layout. The trick could be controlling this in a drive-by-drive fashion, and forbidding "hot swaps" if a critical kernel structure was modified.

I don't know how linux kexec works and never tried to use it.

JJ
Post Reply