Lowlevel
Lowlevel => OS-Design => Thema gestartet von: jo2105 am 23. November 2012, 21:25
-
Ok, ich komme mal wieder nicht weiter^^
Ich habe in meinen Kernel Multitasking integriert, was nach einigen Hürden auch gut geklappt hat.
Seitdem ich aber in den Ring3 umgestiegen bin, startet QEMU einfach die ganze Zeit neu. :roll:
Das sind die Quellcodes:
#include "includes.h"
#define GDT_FLAG_DATASEGM 0x02
#define GDT_FLAG_CODESEGM 0x0a
#define GDT_FLAG_TSS 0x09
#define GDT_FLAG_SEGMENT 0x10
#define GDT_FLAG_RING0 0x00
#define GDT_FLAG_RING3 0x60
#define GDT_FLAG_PRESENT 0x80
#define GDT_FLAG_4K_GRAN 0x800
#define GDT_FLAG_32_BIT 0x400
#define GDT_ENTRIES 0x5
static uint64_t gdt[GDT_ENTRIES];
void init_gdt()
{
gdt_set_entry(0, 0, 0, 0);
gdt_set_entry(1, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT | GDT_FLAG_CODESEGM | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT);
gdt_set_entry(2, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT | GDT_FLAG_DATASEGM | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT);
gdt_set_entry(3, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT | GDT_FLAG_CODESEGM | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
gdt_set_entry(4, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT | GDT_FLAG_DATASEGM | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
gdt_set_entry(5, (uint32_t)tss, sizeof(tss), GDT_FLAG_TSS | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
load_gdt();
kprintf(P_GDT_LOADED);
}
void gdt_set_entry(int i, unsigned int base, unsigned int limit, int flags)
{
gdt[i] = limit & 0xffffLL;
gdt[i] |= (base & 0xffffffLL) << 16;
gdt[i] |= (flags & 0xffLL) << 40;
gdt[i] |= ((limit >> 16) & 0xfLL) << 48;
gdt[i] |= ((flags >> 8) & 0xffLL) << 52;
gdt[i] |= ((base >> 24) & 0xffLL) << 56;
}
void load_gdt()
{
struct {
uint16_t limit;
void * pointer;
} __attribute__((packed)) gdtp = {
.limit = GDT_ENTRIES * 8 - 1,
.pointer = gdt,
};
asm volatile("lgdt %0" : : "m" (gdtp));
asm volatile("ltr %%ax" : : "a" (5 << 3));
asm volatile("mov $0x10, %ax;"
"mov %ax, %ds;"
"mov %ax, %es;"
"mov %ax, %ss;"
"ljmp $0x8, $.1;"
".1:");
}
static uint8_t stack_a[4096];
static uint8_t stack_b[4096];
static uint8_t user_stack_a[4096];
static uint8_t user_stack_b[4096];
static int current_task = -1;
static int num_tasks = 2;
static struct cpu_state* task_states[2];
void init_taskmanager()
{
task_states[0] = init_task(stack_a, user_stack_a, task_a);
task_states[1] = init_task(stack_b, user_stack_b, task_b);
kprintf("Der Taskmanager wurde initialisiert\n");
}
struct cpu_state * init_task(uint8_t* stack, uint8_t* userstack, void* entry)
{
struct cpu_state task_cpu_state = {
.eax = 0,
.ebx = 0,
.ecx = 0,
.edx = 0,
.esi = 0,
.edi = 0,
.ebp = 0,
.esp = (uint32_t)userstack + 4096,
.eip = (uint32_t)entry,
.cs = 0x18 | 0x03,
.ss = 0x20 | 0x03,
.eflags = 0x202,
};
struct cpu_state* state = (void*) (stack + 4096 - sizeof(task_cpu_state));
*state = task_cpu_state;
kprintf("%x\n", state->eip);
return state;
}
struct cpu_state * schedule(struct cpu_state * cpu)
{
if(current_task >= 0) {
task_states[current_task] = cpu;
intr_common_handler:
//CPU-Stand sichern
push %ebp
push %edi
push %esi
push %edx
push %ecx
push %ebx
push %eax
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
push %esp
call handle_interrupts
mov %eax, %esp
mov $0x23, %ax
mov %ax, %ds
mov %ax, %es
pop %eax
pop %ebx
pop %ecx
pop %edx
pop %esi
pop %edi
pop %ebp
add $8, %esp
iret
#include "includes.h"
struct cpu_state * handle_interrupts(struct cpu_state * cpu)
{
struct cpu_state * new_cpu = cpu;
if(cpu->intr <= 0x1f) {
clear();
changeColor(0x1f);
kprintf("\n Das Betriebssystem hat ein Problem festgestellt und muss beendet werden.\n\n");
kprintf(" Interrupt:%v %d (Exception)\n", 15, (int)cpu->intr);
kprintf(" Fehlercode:%v %x\n\n", 15, cpu->error);
kprintf(" CPU zum Zeitpunkt des Interrupts:\n\n");
kprintf("\teax:%v %x%vebx:%v%x\n", 10, cpu->eax, 25, 32, cpu->ebx);
kprintf("\tecx:%v %x%vedx:%v%x\n", 10, cpu->ecx, 25, 32, cpu->edx);
kprintf("\tesi:%v %x%vedi:%v%x\n", 10, cpu->esi, 25, 32, cpu->edi);
kprintf("\tebp:%v %x%veip:%v%x\n", 10, cpu->ebp, 25, 32, cpu->eip);
kprintf("\tesp:%v %x\n", 10, cpu->esp);
kprintf("\tcs:%v %x%vss:%v%x\n", 10, cpu->cs, 25, 32, cpu->ss);
kprintf("\tFlags:%v %x\n", 10, cpu->eflags);
kprintf("\n Taste druecken um einen CPU-Reset auszufuehren...\n Mach dir keine Hoffnungen, ich komme wieder. :madcat:");
outb(0x64, 0xFE);
while(1) asm volatile("cli; hlt");
} else {
if(cpu->intr >= 0x20 && cpu->intr <= 0x2f) {
if(cpu->intr >= 0x28) {
outb(0xa0, 0x20);
} else {
outb(0x20, 0x20);
}
if(cpu->intr == 0x20) {
new_cpu = schedule(cpu);
tss[1] = (uint32_t)(new_cpu+1);
}
if(cpu->intr == 0x21) kb_irq_handler(cpu->intr);
}
}
return new_cpu;
}
Falls ihr noch irgendwelche QEMU Logs braucht, lasst es mich hören. :-D
-
Falls ihr noch irgendwelche QEMU Logs braucht, lasst es mich hören. :-D
Normalerweise immer das Log (ggf. auf Pastebin) posten.
Aber dein Problem hatten kürzlich erst ein paar andere: GDT_ENTRIES muss den Wert 6 haben.
-
Falls ihr noch irgendwelche QEMU Logs braucht, lasst es mich hören. :-D
Normalerweise immer das Log (ggf. auf Pastebin) posten.
Aber dein Problem hatten kürzlich erst ein paar andere: GDT_ENTRIES muss den Wert 6 haben.
Oh verdammt. :-D Das ist natürlich ein dummer Fehler.
Jetzt kriege ich folgenden Fehler:
qemu: fatal: Trying to execute code outside RAM or ROM at 0x66671058
EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000065
ESI=00000000 EDI=00000000 EBP=8b66670c ESP=ffffff84
EIP=66671058 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0000 00000000 00000000 00000000
GS =0000 00000000 00000000 00000000
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 001022c0 00000080 0000e910 DPL=3 TSS32-avl
GDT= 0010a040 0000002f
IDT= 0010a080 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=000007cf CCD=08708397 CCO=SUBL
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
Ich werde später noch die Logdatei posten.
-
Die CPU springt an eine Adresse, wo kein RAM mehr ist (0x66671058 ist bei etwa 1,6 GB). Das deutet auf einen kaputten Stack hin.
-
Die CPU springt an eine Adresse, wo kein RAM mehr ist (0x66671058 ist bei etwa 1,6 GB). Das deutet auf einen kaputten Stack hin.
Jop den Fehler hatte ich schon beim Multitasking im Ring0. Da lag es aber daran, dass ich noch keine Scrollfunktion hatte und der ganze Speicher und darüber hinaus mit a und b zu gemüllt wurden. :-D
Dann werde ich gleich mal auf die Fehlerjagd begeben.
-
http://pastebin.com/3eHU8170
Ich finde irgendwie nicht die Stelle, wo die CPU auf diese Adresse springt...
-
Der Wert ESP=ffffff84 in dem Dump lässt vermuten, dass ESP irgendwo auf 0 gesetzt wurde. Vermutlich funktioniert die schedule-Funktion nicht richtig.
-
Der Wert ESP=ffffff84 in dem Dump lässt vermuten, dass ESP irgendwo auf 0 gesetzt wurde. Vermutlich funktioniert die schedule-Funktion nicht richtig.
Ok. Es lag wohl daran, dass ich das tss Array falsch deklariert habe. Jetzt funktioniert es soweit. Allerdings kriege ich keine normale Exception, wenn ich asm("cli; hlt"); in einem der Tasks eingebe, sondern QEMU startet einfach neu...
/e: Das Problem lag am Interrupt Handler. Jetzt kriege ich zwar den Bluescreen, aber auch wenn die Tasks überhaupt nichts böses machen.
/e2: Ah ich habe nur dem cs einen falschen Wert mitgegeben. Jetzt klappt es.