http://bugs.winehq.org/show_bug.cgi?id=31279
--- Comment #10 from Charles Davis cdavis@mymail.mines.edu 2012-07-22 20:39:13 CDT --- (In reply to comment #9)
Hello,
--- quote --- Interesting. It looks like the address it's trying to read is before the IDT even starts:
003e:trace:int:emulate_instruction mov idt,xxx (0x7c2f0008, base=0x7c31b000, limit=0x1006) at 0x54287f
Why would that be? There are two others before it:
003e:trace:int:emulate_instruction mov idt,xxx (0x7c2f0008, base=0x7c2f0000, lim it=0x1004) at 0x54287f 003e:trace:int:emulate_instruction mov idt,xxx (0x7c2f0018, base=0x7c2f0000, lim it=0x1004) at 0x542884 --- quote ---
The limits look very strange (invalid). Maybe this is an OSX specific thing, I'm not familiar with that OS. Can you compile and execute this short C program:
--- snip sidt.c --- #include <stdio.h>
struct { unsigned short limit; unsigned int base; } __attribute__ ((packed)) idtr;
int main(int argc, char **argv) { asm ("sidt %0" : "=m" (idtr)); printf("IDTR base at 0x%X\n",(int)idtr.base); printf("IDTR limit 0x%X\n",(int)idtr.limit); return 0; } --- snip sidt.c ---
Sure enough, every time I run this program, I get a different result.
That last digit in the limit is strange, but it doesn't seem to be a problem in practice. I haven't had any IDT-related panics :). I suspect it's got something to do with the number of the CPU that owns that particular IDT. So far I've seen 1000h, 1002h, 1004h, and 1006h. I have four physical cores, so that makes sense.
One thing that comes to my mind is that IDT's are per CPU core. If the IDT addresses are different between cores and the thread is migrated to different cores in between two "sidt" calls then this kind of thing (IDT base change) might happen.
You could try:
$ taskset -c 0 ./sidt $ taskset -c 1 ./sidt $ taskset -c 2 ./sidt $ taskset -c 3 ./sidt
and see if the IDT bases are the same to rule out such kind of problem.
Unfortunately, I just remembered that it's not generally possible to force a thread onto one particular CPU on Mac OS. (So, there's no 'taskset' command. I believe that's a Linux-ism anyway.) The best one can do on Mac OS is put your threads in an "affinity group", whereby your threads are tagged with a number; then the scheduler runs the threads on whatever CPUs are closest to each other in terms of memory locality (at least, that's how it's supposed to work). (This of course makes it impossible to sanely implement Windows-style thread affinity handling on Mac OS, which kinda makes me mad. Maybe I should start using Linux...)
By the way, in case you're wondering, using the affinity tag API is no help. I still see four different base/limit combinations.
This also means that forcing the NTOSKRNL thread onto a particular CPU is out.
EDIT: You actually had the same idea while I was writing this ;-)
Regards