Autor Thema: Hallo erstmal und "Trying to execute code outside RAM or ROM"  (Gelesen 9154 mal)

Tele

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
Hallo Lowlevel-Forum!

Ich bin der Tele, 20 Jahre alt und Student. Ich hab bereits eine Ausbildung zum Informationstechnischen Assistenten hinter mir und jetzt studiere ich dual
Wirtschaftsinformatik. Ich interessiere mich schon lange für das Entwickeln von Betriebssystemen, insbesondere Linux hat es mir angetan.
Jetzt habe ich den Schritt gewagt und damit angefangen und, tja stehe direkt vor einem (für mich) unlösbaren Problems:

Ich habe fleissig das Tutorial verfolgt und bin jetzt beim Multitasking. Ich muss dazu sagen, dass ich mein Betriebssystem anhand anderer Tutorials bereits erweitert habe, so verfüge ich über einen GCC-Crosscompiler und eine (gaaaaaanz kleine) eigene libc Implementierung (stdio, etc.).

Leider spuckt mir Qemu ein "Trying to execute code outside RAM or ROM at 0x66000000" aus und da komme ich nicht weiter.
Ich habe alle Beiträge in diesem Forum bezüglich ähnlicher Fehler durch, half leider nichts. Lange Rede, kurzer Sinn: Ich erbitte euch um Hilfe und hier ist mein Code:

kernel.c
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>

#include <kernel/tty.h>
#include <kernel/gdt.h>
#include <kernel/idt.h>
#include <kernel/kbc.h>
#include <kernel/task.h>

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];

void task_a(void);
void task_b(void);

void kernel_early(void) {
terminal_init();

gdt_init();
kbc_init();

task_init_task(stack_a, user_stack_a, task_a, 0);
task_init_task(stack_b, user_stack_b, task_b, 1);
idt_init();
}

void kernel_main(void) {
printf("OSWAN has successfully booted\n");

while(1);
}

void task_a(void) {
while (1) {
putchar('A');
}
}

void task_b(void) {
while (1) {
putchar('B');
}
}

idt.c
#include <kernel/idt.h>
#include <kernel/gdt.h>
#include <kernel/kbc.h>
#include <kernel/syscl.h>
#include <kernel/ports.h>
#include <kernel/task.h>
#include <stdio.h>

#define IDT_FLAG_INTERRUPT_GATE 0xe
#define IDT_FLAG_PRESENT 0x80
#define IDT_FLAG_RING0 0x00
#define IDT_FLAG_RING3 0x60

#define IDT_NR_EXCEPTION_LAST   0x1f
#define IDT_NR_IRQ_FIRST 0x20
#define IDT_NR_IRQ_LAST 0x2f
#define IDT_NR_SOFTWARE 0x30

#define IDT_ENTRIES 256

// Exceptions
extern void intr_stub_0(void);
extern void intr_stub_1(void);
extern void intr_stub_2(void);
extern void intr_stub_3(void);
extern void intr_stub_4(void);
extern void intr_stub_5(void);
extern void intr_stub_6(void);
extern void intr_stub_7(void);
extern void intr_stub_8(void);
extern void intr_stub_9(void);
extern void intr_stub_10(void);
extern void intr_stub_11(void);
extern void intr_stub_12(void);
extern void intr_stub_13(void);
extern void intr_stub_14(void);
extern void intr_stub_15(void);
extern void intr_stub_16(void);
extern void intr_stub_17(void);
extern void intr_stub_18(void);

// IRQ
extern void intr_stub_32(void);
extern void intr_stub_33(void);
extern void intr_stub_34(void);
extern void intr_stub_35(void);
extern void intr_stub_36(void);
extern void intr_stub_37(void);
extern void intr_stub_38(void);
extern void intr_stub_39(void);
extern void intr_stub_40(void);
extern void intr_stub_41(void);
extern void intr_stub_42(void);
extern void intr_stub_43(void);
extern void intr_stub_44(void);
extern void intr_stub_45(void);
extern void intr_stub_46(void);
extern void intr_stub_47(void);

// System Call
extern void intr_stub_48(void);

static long long unsigned int idt[IDT_ENTRIES];

static void idt_set_entry(int i, void (*fn)(), unsigned int selector, int flags) {
unsigned long int handler = (unsigned long int)fn;

idt[i] = handler & 0xffffLL;
idt[i] |= (selector & 0xffffLL) << 16;
idt[i] |= (flags & 0xffLL) << 40;
idt[i] |= ((handler >> 16) & 0xffffLL) << 48;
}

static void pic_init(void) {

/* Initialize Master-PIC */
/* ICW (Initializazion Control Word) 1-4 */
// Initial command
outb(0x20, 0x11);
// Interrupt NR for IRQ 0
outb(0x21, 0x20);
// Slave-PIC at IRQ 2
outb(0x21, 0x04);
// ICW 4 0x01 is set for PC's
outb(0x21, 0x01);

/* Initialize Slave-PIC */
/* ICW (Initializazion Control Word) 1-4 */
// Initial command
outb(0xa0, 0x11);
// Interrupt NR for IRQ 8
outb(0xa1, 0x28);
// Slave-PIC at IRQ 2
outb(0xa1, 0x02);
// ICW 4 0x01 is set for PC's
outb(0xa1, 0x01);

// Activate all IRQ's for Master and Slave
outb(0x20, 0x0);
outb(0xa0, 0x0);
}

void idt_init(void) {
struct {
unsigned short int limit;
void* base;
} __attribute__((packed)) idtp = {
.limit = IDT_ENTRIES * 8 - 1,
.base = idt,
};

pic_init();

idt_set_entry(0,  intr_stub_0,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(1,  intr_stub_1,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(2,  intr_stub_2,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(3,  intr_stub_3,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(4,  intr_stub_4,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(5,  intr_stub_5,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(6,  intr_stub_6,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(7,  intr_stub_7,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(8,  intr_stub_8,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(9,  intr_stub_9,  0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(10, intr_stub_10, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(11, intr_stub_11, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(12, intr_stub_12, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(13, intr_stub_13, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(14, intr_stub_14, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(15, intr_stub_15, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(16, intr_stub_16, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(17, intr_stub_17, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(18, intr_stub_18, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);

idt_set_entry(32, intr_stub_32, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(33, intr_stub_33, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(34, intr_stub_34, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(35, intr_stub_35, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(36, intr_stub_36, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(37, intr_stub_37, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(38, intr_stub_38, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(39, intr_stub_39, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(40, intr_stub_40, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(41, intr_stub_41, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(42, intr_stub_42, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(43, intr_stub_43, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(44, intr_stub_44, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(45, intr_stub_45, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(46, intr_stub_46, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);
idt_set_entry(47, intr_stub_47, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING0 | IDT_FLAG_PRESENT);

idt_set_entry(48, intr_stub_48, 0x8, IDT_FLAG_INTERRUPT_GATE | IDT_FLAG_RING3 | IDT_FLAG_PRESENT);

// load the adress of idtp to register the IDT in the CPU
asm volatile("lidt %0" : : "m" (idtp));

// set the Interrupt Flag (if) in the cpu
asm volatile("sti");
}

struct cpu_state* idt_handle_interrupt(struct cpu_state* cpu) {
struct cpu_state* new_cpu = cpu;
uint32_t intr = cpu->intr;

if (intr <= IDT_NR_EXCEPTION_LAST) {
printf("Exception %d! System halt\n", intr);

// cli unsets the Interrupt Flag (if) in the cpu so interrupts are ignored.
// hlt halts until an interrupt occures.
// cli and hlt are used together to hang the kernel
while (1) { asm volatile("cli; hlt"); }
}
else if (intr >= IDT_NR_IRQ_FIRST && intr <= IDT_NR_IRQ_LAST) {

if (intr == 0x20) {
new_cpu = task_schedule(cpu);
tss[1] = (uint32_t)(new_cpu + 1);

//printf("%d, %d, %d\n", cpu->intr, cpu->esp, cpu->eip);

//while (1) { asm volatile("cli; hlt"); }
}

// IRQ 1 is Keyboard. Handle control to kbc
if (intr == IDT_NR_IRQ_FIRST + 1) {
kbc_handle_key();
}

// EOI (End Of Interrupt)
// Tells the pic the interrupt has been handled successfully.
// If this isn't send, we wont receive further hardware interrupts.
if (intr >= 0x28) {
// EOI for Slave-PIC
outb(0xa0, 0x20);
}
// EOI for Master-PIC
outb(0x20, 0x20);
}
// Software Interrupt. Handle control to syscl
else if (intr == IDT_NR_SOFTWARE) {
syscl_handle_interrupt(cpu);
}
else {
printf("Unknown Interrupt! System halt\n");
while (1) { asm volatile("cli; hlt"); }
}

return new_cpu;
}

gdt.c
#include <kernel/gdt.h>
#include <kernel/tss.h>
#include <stdint.h>

#define GDT_FLAG_DATASEG 0x02
#define GDT_FLAG_CODESEG 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 0x800
#define GDT_FLAG_32_BIT 0x400

#define GDT_ENTRIES 6
static uint64_t gdt[GDT_ENTRIES];

static 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 gdt_init(void) {
struct {
uint16_t limit;
void* base;
} __attribute__((packed)) gdtp = {
.limit = GDT_ENTRIES * 8 - 1,
.base = gdt,
};

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);

asm volatile("lgdt %0" : : "m" (gdtp));

asm volatile(
"mov $0x10, %ax;"
"mov %ax, %ds;"
"mov %ax, %es;"
"mov %ax, %ss;"
"ljmp $0x8, $.1;"
".1:"
);

// load Task Register
asm volatile("ltr %%ax" : : "a" (5 << 3));
}

intr_stub.S
//  Macro function for non-exception stubs
//  pushes zero and stub nr on stack
//  jumps into intr_common_handler
.macro intr_stub nr
.global intr_stub_\nr
intr_stub_\nr:
    pushl $0
    pushl $\nr
    jmp intr_common_handler
.endm

//  Macro function for exception stubs
//  pushes exception nr and stub nr on stack
//  jumps into intr_common_handler
.macro intr_stub_error_code nr
.global intr_stub_\nr
intr_stub_\nr:
    pushl $\nr
    jmp intr_common_handler
.endm

//  Some exceptions have an additional error code
//  for this exceptions, the intr_stub_error_code macro is used
//  other stubs pushes instead zero of the stack
intr_stub 0
intr_stub 1
intr_stub 2
intr_stub 3
intr_stub 4
intr_stub 5
intr_stub 6
intr_stub 7
intr_stub_error_code 8
intr_stub 9
intr_stub_error_code 10
intr_stub_error_code 11
intr_stub_error_code 12
intr_stub_error_code 13
intr_stub_error_code 14
intr_stub 15
intr_stub 16
intr_stub_error_code 17
intr_stub 18

// IRQs
intr_stub 32
intr_stub 33
intr_stub 34
intr_stub 35
intr_stub 36
intr_stub 37
intr_stub 38
intr_stub 39
intr_stub 40
intr_stub 41
intr_stub 42
intr_stub 43
intr_stub 44
intr_stub 45
intr_stub 46
intr_stub 47

// Syscall
intr_stub 48

//  c function from idt.h
.extern idt_handle_interrupt
intr_common_handler:
    // Save cpu registers
    push %ebp
    push %edi
    push %esi
    push %edx
    push %ecx
    push %ebx
    push %eax

    mov $0x10, %ax
    mov %ax, %ds
    mov %ax, %es

    // Call c function handler
    push %esp
    call idt_handle_interrupt
    mov %eax, %esp

    mov $0x23, %ax
    mov %ax, %ds
    mov %ax, %es
     
    // load cpu register
    pop %eax
    pop %ebx
    pop %ecx
    pop %edx
    pop %esi
    pop %edi
    pop %ebp

    // pop error code and interrupt nr from stack
    add $8, %esp

    iret

task.c
#include <kernel/task.h>

static int current_task = -1;
static int num_tasks = 2;
static struct cpu_state* task_states[2];

void task_init_task(uint8_t* stack, uint8_t* user_stack, void* entry, unsigned int nr) {
    struct cpu_state new_state = {
        .eax = 0,
        .ebx = 0,
        .ecx = 0,
        .edx = 0,
        .esi = 0,
        .edi = 0,
        .ebp = 0,
        .esp = (uint32_t) user_stack + 4096,
        .eip = (uint32_t) entry,
 
        /* Ring-3-Segmentregister */
        .cs  = 0x18 | 0x03,
        .ss  = 0x20 | 0x03,
 
        /* IRQs einschalten (IF = 1) */
        .eflags = 0x200,
    };
 
    /*
     * Den angelegten CPU-Zustand auf den Stack des Tasks kopieren, damit es am
     * Ende so aussieht als waere der Task durch einen Interrupt unterbrochen
     * worden. So kann man dem Interrupthandler den neuen Task unterschieben
     * und er stellt einfach den neuen Prozessorzustand "wieder her".
     */
    struct cpu_state* state = (void*) (stack + 4096 - sizeof(new_state));
    *state = new_state;
 
    task_states[nr] = state;
}
 
/*
 * Gibt den Prozessorzustand des naechsten Tasks zurueck. Der aktuelle
 * Prozessorzustand wird als Parameter uebergeben und gespeichert, damit er
 * beim naechsten Aufruf des Tasks wiederhergestellt werden kann
 */
struct cpu_state* task_schedule(struct cpu_state* cpu) {
    /*
     * Wenn schon ein Task laeuft, Zustand sichern. Wenn nicht, springen wir
     * gerade zum ersten Mal in einen Task. Diesen Prozessorzustand brauchen
     * wir spaeter nicht wieder.
     */
    if (current_task >= 0) {
        task_states[current_task] = cpu;
    }
 
    /*
     * Naechsten Task auswaehlen. Wenn alle durch sind, geht es von vorne los
     */
    current_task++;
    current_task %= num_tasks;
 
    /* Prozessorzustand des neuen Tasks aktivieren */
    cpu = task_states[current_task];
 
    return cpu;
}

So das wärs dann soweit (sofern ich nichts vergessen habe).
Ich freue mich auf eine schöne Zeit hier im Forum!

Grüße,
Der Tele
I'm in love with /dev/null

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 14. August 2015, 21:57 »
Erstmal auch nochmal im Forum ein Willkommen. :)

Leider spuckt mir Qemu ein "Trying to execute code outside RAM or ROM at 0x66000000" aus und da komme ich nicht weiter.
Das bedeutet, dass dein Code auf irgendeine Weise nach 0x66000000 gesprungen ist, wo sich leider nichts befindet, und damit auch nicht der Code, zu dem du eigentlich springen wolltest.

Die erste Frage, du die beantworten musst, ist die folgende: Ist das Problem, dass die Adresse nicht stimmt, oder ist die Adresse richtig und du erwartest eigentlich, dass dort etwas ist? Ich gehe mal vorläufig davon aus, dass die Adresse nicht beabsichtigt war.

Dann wäre der nächste Schritt herauszufinden, wie du dort gelandet bist. Die Erfahrung sagt, dass es meistens das iret ist, das falsch springt, weil der Stack in irgendeiner Form kaputt ist. Um das herauszufinden, könntest du entweder den gdb-Stub benutzen und einen Breakpoint in der zweiten Hälfte von intr_common_handler setzen und singlesteppen, oder du könntest qemu -d in_asm benutzen und dir damit alle Instruktionen ausgeben lassen, die qemu übersetzt. In der Regel erwischst du damit die letzte sinnvolle Instruktion.

Wenn du dann bestätigt hast, dass es das iret ist (oder auch, wenn du einen anderen Schuldigen gefunden hast), kannst du an passender Stelle (z.B. am Ende deines Interrupthandlers) Debugcode einbauen, der dir den Stackinhalt ausgibt. Alternativ kannst du, wenn du gdb benutzt, vor der Ausführung der problematischen Instruktion auch im Debugger den aktuellen Speicher-/Registerzustand anschauen.

(Ich hoffe, du bist mir nicht böse, dass ich deinen Code erstmal nicht näher angeschaut habe. Aber ich glaube, dir ist mehr geholfen, wenn du lernst, wie man so etwas debuggt statt dass dir jemand sagt, wo der Fehler steckt.)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Tele

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 15. August 2015, 09:53 »
Vielen Dank für Deine Rückmeldung!

Habe jetzt qemu mitloggen lassen, werde aber nicht schlau aus dem Log:
Servicing hardware INT=0x20
----------------
IN:
0x00100814:  sub    $0x8,%esp
0x00100817:  push   %edx
0x00100818:  push   $0x102510
0x0010081d:  call   0x100e70
Scheint erstmal richtig zu sein. Der Hardware Interrupt vom Timer kommt schonmal. Dannach exlodiert qemu dann.
Schreibe ich eine Logausgabe so:
if (intr == 0x20) {
new_cpu = task_schedule(cpu);
tss[1] = (uint32_t)(new_cpu + 1);

printf("%d, %d, %d\n", cpu->intr, cpu->esp, cpu->eip);

while (1) { asm volatile("cli; hlt"); }
}
Hält qemu wie erwartet an, ich bekomme aber kein Hardware Int im Log?
Eine Frage: Wie schaffe ich es, dass qemu sich nicht schließt nachdem er crashed? Sonst sehe ich meine printf's nicht. Oder anders, gibt es die Möglichkeit, dass qemu den Bildschirminhalt in eine Datei umleitet?

Grüße,

Der Tele
I'm in love with /dev/null

xenos1984

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 16. August 2015, 07:57 »
Wenn du QEMU den Parameter -debugcon file:output.txt mitgibst und deinen Bildschirminhalt im Kernel zusätzlich Zeichen für Zeichen mittels out an Port 0xe9 schreibst, findest du ihn hinterher in der Datei output.txt. Ich habe dafür z.B. in meiner putchar-Funktion, die ein Zeichen auf den Bildschirm schreibt, so ein "out %al,%dx" drin.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 16. August 2015, 15:47 »
Eine Frage: Wie schaffe ich es, dass qemu sich nicht schließt nachdem er crashed?
Das sollte gehen, wenn du beim Aufruf in der Kommandozeile -no-reboot -no-shutdown übergibst.
Dieser Text wird unter jedem Beitrag angezeigt.

Tele

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 16. August 2015, 20:37 »
Vielen Dank für Eure Antworten!

Nach etlichem herumprobieren habe ich das Problem gefunden:
Ich habe nicht wie im Tutorial vorgegeben gdt und idt in eine Datei gepackt, sondern in zwei getrennte Dateien. Das hatte zur Folge, dass ich das TSS auch in beiden Dateien brauchte.
Daher habe ich eine weitere Date tss.h hinzugefügt, welche lediglich das TSS enthält. Da war der Fehler. Anscheinend ließ sich dies nicht in beide Dateien einfügen.

Jetzt habe ich gdt und idt in eine Datei, ebenso das TSS eingepackt und siehe da, meine Tasks laufen auf Ring 3  :-D
Hat jemand von Euch eine Erklärung dafür, dass sich das TSS so verhalten hat?
I'm in love with /dev/null

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 16. August 2015, 21:36 »
Ich glaube, die tss.h hattest du nicht gepostet, sicher kann ich also nicht sagen, was du angestellt hast.

Wenn ich raten soll hast du das tss als static deklariert und deswegen zwei unterschiedliche tss-Variablen in idt.c und gdt.c bekommen. Der richtige Ansatz wäre, es in einer von beiden C-Dateien zu definieren und im Header nur eine extern-Deklaration zu haben.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Tele

  • Beiträge: 13
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 20. August 2015, 12:55 »
Vielen Dank Kevin, richtig geraten. Die Sache mit dem Static  :-D
Wieder etwas dazugelernt
I'm in love with /dev/null

 

Einloggen