Page 1 of 1
Should a kernel start as 32 bit or 64 bit first?
Posted: Sun Dec 16, 2012 10:06 pm
by zeitue
I'm writing a new kernel after losing my last one 3 years ago.
I have a 64 bit machine now an X86-64. My last kernel ran on X86 32 bit machine.
what is it better to start writing 32 bit or 64?
[EDIT: Colours removed by Brendan[/EDIT]
Re: Should a kernel start as 32 bit or 64 bit first?
Posted: Mon Dec 17, 2012 7:08 am
by thepowersgang
Ow, ow, ow. Please don't use colours (it's in the rules)
That said, it depends what you're doing. Long mode (64-bit x86) does give you a cleaner architecture, and more space to play with, but 32-bit is smaller and has a simpler paging structure (being two levels instead of four).
Note that you can run a modern (long-mode capable) processor in protected mode (so there's no need to switch to 64-bit to support your processor)
Re: Should a kernel start as 32 bit or 64 bit first?
Posted: Mon Dec 17, 2012 10:09 am
by Brendan
Hi,
zeitue wrote:what is it better to start writing 32 bit or 64?
Normally you'd design then implement then test; and during the implement or test phase you might find out the design needs changing a little. These small design changes are easy to do if nothing relies on that code yet.
If you design, implement and test each piece for a 64-bit kernel and end up with a lot of code that relies on all those pieces, and then try to implement a 32-bit kernel that shares some of the same design; then you might find out that some of the design needs some changes and the changes are hard to do because they break existing code. For a simple example, you might design the kernel's API to assume SSE exists and have to redesign the kernel API when you figure out that SSE doesn't exist on some 32-bit CPUs.
In the same way; if you design, implement and test each piece for a 32-bit kernel you could end up with the same problem. For a simple example, you might decide that a "process ID" is actually a 32-bit pointer to a "process control block" in kernel space; and when your 32-bit applications are run on a 64-bit kernel the 32-bit pointer would need to be a 64-bit pointer and all the 32-bit applications get broken.
Note: I'm not saying these types of problems are extremely likely; but I am saying the probability of having problems like this is greater than zero.
To reduce the chance of these types of problems, I normally implement the 32-bit kernel and 64-bit kernel at the same time.
Cheers,
Brendan
Re: Should a kernel start as 32 bit or 64 bit first?
Posted: Mon Dec 17, 2012 10:16 am
by bluemoon
Agree with Brendan. It may be a bit more difficult to start both architectures, but once you "break the wall" you'll find that less than 5% of the code is actually sensitive to 32/64-bit.
PS. If you want a 64-bit kernel able to execute BOTH 64-bit and 32-bit application it's far more complicated - but not everyone need to do that without "backward compatibility concerns".
Re: Should a kernel start as 32 bit or 64 bit first?
Posted: Mon Dec 17, 2012 5:46 pm
by zeitue
@thepowersgang sorry about the colors I did not see it in the rules the first time I read them.
@thepowersgang @Brendan @bluemoon thank you for the replies.
so what your're saying is I should try to do the 32 bit and 64 bit versions at the same time.
start out hard and not have to tons of complications later.
thanks I'll try to do them at the same time.
as a final question could a 32 bit kernel running on an X86-64, run 64 bit programs or is that not possible?
Re: Should a kernel start as 32 bit or 64 bit first?
Posted: Mon Dec 17, 2012 7:14 pm
by Brendan
Hi,
zeitue wrote:as a final question could a 32 bit kernel running on an X86-64, run 64 bit programs or is that not possible?
At a minimum:
- the interrupt handlers for all IRQs, exceptions, etc (and SYSCALL entry/exit if used) must be 64-bit code (but may be 64-bit code that calls the 32-bit kernel)
- the IDT needs to be different
- the paging code needs to be different
- the code that does task switches needs to be different (more registers, etc to save/load)
- half the exception handlers need to be different (task gates replaced with IST for double fault, NMI, machine check; page fault handler and debugging exception handler need to handle 64-bit virtual addresses; etc).
- half the IPI handlers need to be different
- any code that relied on virtual8086 mode would need to be changed (maybe use software emulation instead)
By the time you've changed everything that has to be changed about half a micro-kernel would've been rewritten; and everything in the 32-bit kernel that wasn't rewritten/replaced (including device drivers, etc if it was a monolithic kernel) is probably portable code that could've been recompiled as 64-bit with little change anyway.
Mostly, it's sort of possible a little bit, but doesn't make sense (unless the kernel is monolithic and incapable of running 32-bit drivers on a 64-bit kernel and most of the code is written in assembly and can't simply be recompiled as 64-bit).
Cheers,
Brendan
Re: Should a kernel start as 32 bit or 64 bit first?
Posted: Mon Dec 17, 2012 7:21 pm
by zeitue
Thanks, Brendan, this makes perfect sense.
Brendan wrote:Hi,
zeitue wrote:as a final question could a 32 bit kernel running on an X86-64, run 64 bit programs or is that not possible?
At a minimum:
- the interrupt handlers for all IRQs, exceptions, etc (and SYSCALL entry/exit if used) must be 64-bit code (but may be 64-bit code that calls the 32-bit kernel)
- the IDT needs to be different
- the paging code needs to be different
- the code that does task switches needs to be different (more registers, etc to save/load)
- half the exception handlers need to be different (task gates replaced with IST for double fault, NMI, machine check; page fault handler and debugging exception handler need to handle 64-bit virtual addresses; etc).
- half the IPI handlers need to be different
- any code that relied on virtual8086 mode would need to be changed (maybe use software emulation instead)
By the time you've changed everything that has to be changed about half a micro-kernel would've been rewritten; and everything in the 32-bit kernel that wasn't rewritten/replaced (including device drivers, etc if it was a monolithic kernel) is probably portable code that could've been recompiled as 64-bit with little change anyway.
Mostly, it's sort of possible a little bit, but doesn't make sense (unless the kernel is monolithic and incapable of running 32-bit drivers on a 64-bit kernel and most of the code is written in assembly and can't simply be recompiled as 64-bit).
Cheers,
Brendan
Re: Should a kernel start as 32 bit or 64 bit first?
Posted: Tue Dec 18, 2012 8:09 am
by rdos
Brendan wrote:
the IDT needs to be different
Typically, 64-bit mode needs it's own IDT
Brendan wrote:
the paging code needs to be different
Not really. If the 32-bit OS uses PAE-mode, the page tables can be shared. There need to be a new 64-bit pagefault handler, which must be able to handle the new 64-bit addresses, and the legacy 32-bit OS addresses.
Brendan wrote:
the code that does task switches needs to be different (more registers, etc to save/load)
True.
Brendan wrote:
half the exception handlers need to be different (task gates replaced with IST for double fault, NMI, machine check; page fault handler and debugging exception handler need to handle 64-bit virtual addresses; etc).
There needs to be both 32-bit and 64-bit handlers. The stack-layout for 64-bit handlers is different.
Brendan wrote:
half the IPI handlers need to be different
Typically only the entry and exit code need to be different.
Brendan wrote:
any code that relied on virtual8086 mode would need to be changed (maybe use software emulation instead)
Or if these tasks run in protected mode instead of long mode. Similarilly, legacy 32-bit applications / OS code can also be run in protected mode rather than in long mode legacy mode, but this requires multiple IDT-handlers.
Brendan wrote:
By the time you've changed everything that has to be changed about half a micro-kernel would've been rewritten; and everything in the 32-bit kernel that wasn't rewritten/replaced (including device drivers, etc if it was a monolithic kernel) is probably portable code that could've been recompiled as 64-bit with little change anyway.
Not so. There is no need to rewrite the old 32-bit interface. Rather, you just add the 64-bit interface on top of the 32-bit interface. Then you need no extra time to be able to run 32-bit applications, and no new emulations.
Re: Should a kernel start as 32 bit or 64 bit first?
Posted: Tue Dec 18, 2012 8:24 am
by rdos
zeitue wrote:
as a final question could a 32 bit kernel running on an X86-64, run 64 bit programs or is that not possible?
Absolutely. I'm almost at that stage now. There are some non-trivial design issues, like how the 32-bit kernel can access the full address space, how pointers passed from 64-bit to the 32-bit kernel are remapped to the low 4G.
I've solved it like this:
- The 32-bit kernel can only access the page tables of the first 4G (and thus can only access the first 4G).
- Remappings of pointers from 64-bit code are done in the syscall procedure (in long mode)
- The 64-bit support code (monitor) is placed at a unity-mapped location (0x110000) so it can switch modes easily
- There is a separate IDT for 64-bit that is loaded on mode-switches to long mode
- GDT is shared, and is not reloaded in long-mode
- The scheduler is extended to be able to switch mode and load/save 64-bit state by calling the 64-bit monitor
- The full page table mappings are mapped in the last PML4 entry
- 64-bit processes cannot access the first and last PML4 entry, (so it cannot corrupt OS data and code) and the code needs to be located somewhere in the middle.
- The remapping buffers are placed in the typical 32-bit application space between 0.5-3.5G
- Long mode has it's own page fault handler that duplicates 32-bit OS functionality + handles long mode faults and always uses the 64-bit page table alias
- Long mode defines new IRQ stubs that calls the same (32-bit) handlers as protected mode
- A few special IPIs are duplicated in long mode, and calls the same handles as protected mode
- Code patching (which does diferent patches) and other traps are duplicated in long mode which allows 64-bit code to transparently use 32-bit syscalls