Hallo,
nachdem ich mein OS nochmal von vorne angefangen habe, hänge ich nun wiedermal beim Multitasking am Wechsel in den Userspace.
Das komische ist, das mein Bluescreen nichtmal aufgerufen wird, obwohl er ansonsten funktioniert. Stattdessen stürzt QEMU ab.
Hier die Ausgaben von QEMU:
qemu: fatal trying to execute code outside RAM or ROM at 0x2e532074
EAX=00000000 EBX=32303032 ECX=00000000 EDX=00000000
ESI=6e614d20 EDI=6b617264 EBP666f5365 ESP=ffffff18
EIP=2e532074 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300
CS =0008 00000000 ffffffff 00cf9a00
SS =0010 00000000 ffffffff 00cf9300
DS =0010 00000000 ffffffff 00cf9300
FS =0000 00000000 00000000 00000000
GS =0000 00000000 00000000 00000000
LDT=0000 00000000 0000ffff 00008200
TR =0028 00103020 00000080 0000e910
GDT= 00104000 00000037
IDT= 001080c0 000007ff
CR0=60000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=0000007c CCD=00000000 CCO=LOGICL
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0-7 (alle gleich) = 0000000000000000 0000
XMM00-07 (alle gleich) = 00000000000000000000000000000000
meine GDT:
struct {uint16_t limit;
void* pointer;
} __attribute__((packed)) gdtp = {
.limit = GDT_ENTRIES * 8 - 1,
.pointer = gdt,
};
// GDT-Eintraege aufbauen
gdt_set_entry(0, 0, 0, 0);
gdt_set_entry(1, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
GDT_FLAG_CODESEG | GDT_FLAG_4K | GDT_FLAG_PRESENT);
gdt_set_entry(2, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
GDT_FLAG_DATASEG | GDT_FLAG_4K | GDT_FLAG_PRESENT);
gdt_set_entry(3, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
GDT_FLAG_CODESEG | GDT_FLAG_4K | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
gdt_set_entry(4, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
GDT_FLAG_DATASEG | GDT_FLAG_4K | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
gdt_set_entry(5, (uint32_t) tss, sizeof(tss),
GDT_FLAG_TSS | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
// GDT neu laden
asm volatile("lgdt %0" : : "m" (gdtp));
// Segmentregister neu laden, damit die neuen GDT-Eintraege auch wirklich
// benutzt werden
asm volatile("mov $0x10, %ax;"
"mov %ax, %ds;"
"mov %ax, %es;"
"mov %ax, %ss;"
"ljmp $0x8, $.1;"
".1:");
// Taskregister neu laden
asm volatile("ltr %%ax" : : "a" (5 << 3));
init_multitasking():
task_states[0] = init_task(stack_a, user_stack_a, task_a);
task_states[1] = init_task(stack_b, user_stack_b, task_b);
irq_common_stub:
; CPU-Zustand sichern
push ebp
push edi
push esi
push edx
push ecx
push ebx
push eax
; Kernel-Datensegmente laden
mov ax, 0x10
mov ds, ax
mov es, ax
; Handler aufrufen
push esp
call interrupt_handler
mov esp, eax
; User-Datensegmente laden
mov ax, 0x23
mov ds, ax
mov es, ax
; CPU-Zustand wiederherstellen
pop eax
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
; Fehlercode und Interruptnummer vom Stack nehmen
add esp, 8
; Ruecksprung zum unterbrochenen Code
iret
Wenn ihr nochwas braucht, bitte bescheid sagen.
Bevor die Frage kommt, in meinem alten Kernel hatte ich nur Ring0 Multitasking