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.
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.