Hi,
Candy wrote:Do you still have those HT files? Would very much like to do that myself if necessary.
I still have the original files, and will be "re-hacking" HT support into Bochs 2.2 Beta tomorrow. Part of the trouble is that to support HT you need 4 additional BIOS images which can't be compiled with 32 bit GCC. I'll get it all up on a web page to make it easy to download (including the extra BIOS images so you don't need to worry about BCC).
Candy wrote:Also, you have experience with osdev on multiprocessor stuff. Could you give a short overview of what went wrong and what common trips are?
I didn't have too much go wrong, aside from typical bugs that you get implementing anything. I'd suggest splitting "multi-CPU" support into several different areas:
- CPU detection (number of CPUs and features)
- IO APIC and local APIC support
- Starting the other CPUs
- re-entrancy (including IRQ support)
- CPU affinity (which is optional)
- scheduling
I was fairly lucky in that the boot sequence and OS design I had been using was relatively conducive to multi-CPU. Some things that helped where detecting CPU features and starting other CPUs within the real mode code (which made the "trampoline" code easy) and using a micro-kernel design where device drivers run as seperate processes (minimizes re-rentrancy concerns).
Detecting the number of present CPUs meant parsing both ACPI and MP specification tables. Detecting hyper-threading means detecting CPU features at the same time (the MP specification tables return information about physical CPUs only, while the ACPI tables return logical CPUs only).
The scheduler design I had been using needed major reworking to make it perform better (to reduce re-entrancy lock contention). The old scheduler used to select the next thread to run from all available ready-to-run threads, while the multi-CPU version needed seperate thread queues (one for each CPU). Placing a ready-to-run thread on one of the CPU's queues also involves a certain amount of load balancing.
For my OS each device driver is implemented as a normal process, where IRQ's are initially handled by the kernel and sent to the device driver as a message. This means that the device driver's code gets a message, handles it, gets another message, etc. I guess what I'm saying is that the messaging serializes everything for the device driver, so that the device driver itself doesn't need to worry about re-entrancy. This isn't quite true as I support multi-threaded processes, but it's the same problem that all multi-threaded processes have (and my OS makes this easier because there's "kernel space", "process space" and "thread space", where each thread has exclusive access to it's thread space).
[continued in next post]