I downloaded the bochs source, and began modifying it - making it print more details when the bogus SS is loaded. I found out that it's loaded with a value that's totally outside the TSS, which means it's looking at a wrong TSS. I inspected the bochs code that loads the SS from the TSS, and from that it was obvious I'd have some retarded bug with my GDT setup.
This was actually one of the very rare occasions I made use of the 'openness' of an open-source software package. Obviously it's a nice thing to have with developer-oriented tools and applications. Thank God bochs builds in under a minute. (Binutils, I'm looking at you! [grin])
Anyway, back to the bug. My TSS setup was like so:
// TSS descriptor
segment_descriptor_t& tss_descriptor = m_gdt_entries[TSS_SEGMENT_DESCRIPTOR_INDEX];
memory_set(&tss_descriptor, 0, sizeof(segment_descriptor_t));
tss_descriptor.limit_0_15 = sizeof(tss_t) - 1;
tss_descriptor.base_address_0_23 = reinterpret_cast
(&tss) & 0xFFFF;
(&tss) >> 24) & 0xFF;
tss_descriptor.segment_type = TSS_SEGMENT_TYPE;
tss_descriptor.ring = 0;
tss_descriptor.is_present = 1;
tss_descriptor.granularity = GRANULARITY_BYTE;
In case you haven't spotted it, the problem is in the base_address. The base_address is split into 2 fields; one is 24-bit wide, the other is 8-bit wide. I was taking only the first 16-bits when filling the first field [dead]. That meant the CPU was reading from a memory address that is significantly lower than the actual TSS address.
So yeah, now I have proper kernel-space to user-space switching and back. Yay!
Throughout this week, I intend to:
- Write thread synchronization objects
- Write basic process management code
- Write a basic system call interface
- Implement separate address spaces for different processes (I'm currently using a flat protected memory model where only accesses to out-of-physical-bounds memory addresses are intercepted).
- Move the keyboard and mouse drivers to user-space
- Write a better user-space test shell (I already have one running in kernel-space)
That's probably too much for one week, but who knows.
This is more of a reminder to myself:
Things that can make it into the next entry:
- Keyboards are not only evil, but retarded too
- I hate to admit it, but gVIM is better than I thought
- Window managers are unnecessarily heavy (e.g. gnome vs xfce)
- Rox filer is cool
- Linux distros still suck at usability and stability
- Color schemes: Black on lightyellow is awesome
- Automake and Autoconf...the day I understand what they're about is the day I die.
- CodeWarrior 9 for the PalmOS is torture
- PalmOS 5 is torture
- Palm devices are torture
- C++ is torture
- So is assembly
- I think I love and hate C++ templates in the same time.
- Long live the 'typename' keyword.
- Writing a correct generic linked list implementation is NOT as easy as one might think
- Testing it isn't easy either
- STLPort std::list tests are not as exhaustive as I thought. In fact, they're more like a joke. Unless I missed something.
- Backward compatibility sucks equally for hardware and software.
- Unit-testing OS components is hard.
- Automating the tests is even harder.
- Debugging OSes is hard too.
- Floppy disks are the most unreliable pieces of junk EVER.
- I bought a new chair.
- And a new keyboard.
- And a new mouse.
- Dual keyboard setups are cool.
- And so is "Little Fighters 2".
- D-Link middle-east routers and switches suck. Probably Ethernet adapters too. A combination of an ethernet adapter, switch, and router is bound to drive you crazy.
- Green tea is way cooler than red tea. Not sure how it compares to coffee, though.
- I think I just had a brain haemorrhage.
- Haemorrhage (also hemorrhage) is such an interesting word. It almost defies correct spelling.