Autor Thema: Multitasking in Ring-3  (Gelesen 14054 mal)

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« am: 12. April 2012, 19:55 »
Hi,

Nachdem ich jetzt das Multitasking in Ring 0 hinbekommen habe, wollte ich jetzt das genze nach ring 3 verschieben.
Nur leider kommen As bis zum nächsten Timerinterrupt und dann meldet qemu: fatal: trying to execute code outside RAM or ROM.(oder so ähnlich)

könnte da mal jemand drübergucken?

multitasking.c
#include <stdint.h>
#include "gdt.h"
#include "interrupt.h"
#include "cpu.h"
#include "console.h"

/* ---------- Globale Variablen ----------------------- */
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 cpu_state* task_states[2];
/* --------- Tasks ------------- */
void task_a(void){
  while(1){
    setColor(0x02);
    printf("A");
  }
}
void task_b(void){
  while(1){
    setColor(0x06);
    printf("B");
  }
}
/* ---------- Task initalisieren ---------------------- */
cpu_state* init_task(uint8_t *stack, uint8_t *user_stack, void *entry){
    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 = 0x1b /*0x18 | 0x03*/,
.ss = 0x23 /*0x20 | 0x03*/,

// IRQs einschalten
.eflags = 0x202,
    };
   
    cpu_state *state = (void*) (stack + 4096 - sizeof(new_state));
    *state = new_state;
   
    return state;
}
/* ---------- Multitasking initalisieren -------------- */
void init_multitasking(void){
    task_states[0] = init_task(stack_a, user_stack_a, task_a);
    task_states[1] = init_task(stack_b, user_stack_b, task_b);
    cpu_dump(task_states[0]);
    cpu_dump(task_states[1]);
}
/* ---------- Scheduler ------------------------------- */
cpu_state* schedule(cpu_state *cpu){
   
    // Alten zustand des Tasks sichern
    if(current_task >= 0){
task_states[current_task] = cpu;
    }
   
    // Nächsten Task auswählen
    current_task++;
    current_task %= num_tasks;
   
    // Neuen Task aktivieren
    cpu = task_states[current_task];
   
    return cpu;
}

timer_irq_handler.c
#include <stdint.h>

#include "cpu.h"
#include "gdt.h"
#include "multitasking.h"

static uint32_t tss[TSS_SIZE];

cpu_state* timer_irq_handler(cpu_state *cpu){
    cpu_state *new_cpu = schedule(cpu);
    tss[1] = (uint32_t) (new_cpu + 1);
   
    send_eoi(0);
    return new_cpu;
}

irq handler:
// Gemeinsamer interrupt handler
.extern common_intrpt_handler
.extern common_intrpt_handler_with_new_cpu
// IRQ - Handler
.extern timer_irq_handler
.extern keyboard_irq_handler

.macro irq_empty nr
.global int_handler\nr
int_handler\nr:
  iret
.endm

.macro irq nr isr
.global int_handler\nr
int_handler\nr:
  push $0
  push $\nr
  push $\isr
  jmp common_intrpt_handler
.endm

.macro irq_with_new_cpu nr isr
.global int_handler\nr
int_handler\nr:
  push $0
  push $\nr
  push $\isr
  jmp common_intrpt_handler_with_new_cpu
.endm

irq_with_new_cpu 0x20 timer_irq_handler
irq 0x21 keyboard_irq_handler
irq_empty 0x22
irq_empty 0x23
irq_empty 0x24
irq_empty 0x25
irq_empty 0x26
irq_empty 0x27
irq_empty 0x28
irq_empty 0x29
irq_empty 0x2A
irq_empty 0x2B
irq_empty 0x2C
irq_empty 0x2D
irq_empty 0x2E
irq_empty 0x2F

//Ende - handler.S

common handler:
.global common_intrpt_handler_with_new_cpu
common_intrpt_handler_with_new_cpu:
  // ISR nach eax legen
  pop %ebx
 
  push %ebp
  push %edi
  push %esi
  push %edx
  push %ecx
  push %ebx
  push %eax
 
  // Kernel-Datensegmente laden
  mov $0x10, %ax
  mov %ax, %ds
  mov %eax, %es
 
  // ISR aufrufen
  push %esp
  call *%ebx
  mov %eax, %esp //Neuen Stack laden
 
  // User-Datensegmente laden
  mov $0x23, %ax
  mov %ax, %ds
  mov %ax, %es
 
  // Neue cpu herstellen
  pop %eax
  pop %ebx
  pop %ecx
  pop %edx
  pop %esi
  pop %edi
  pop %ebp
 
  // Errorcode und Interruptnummer vom Stack nehmen
  add $8, %esp
  iret

gdt.c
#include <stdint.h>
#include "gdt.h"

/* ---------- Globale Variablen ----------------------- */
static uint64_t gdt[GDT_ENTRIES]; //Global Deskriptor Table
static uint32_t tss[TSS_SIZE] = {0, 0, 0x10}; //Task State Segment
/* ---------- Eintrag in die GDT setzen --------------- */
void set_gdt_entry(int i, uint32_t limit, uint32_t base, uint8_t access, uint8_t flags){
  gdt[i] = 0;
  //untere 32-Bit
  gdt[i] = (limit & 0x0ffff) | ((base & 0x0000ffff) << 16);
  //obere 32-Bit
  gdt[i] |=(
    ( (base & 0x00ff0000) >> 16 ) |
    ( access << 8 ) |
    ( flags << 16 ) |
    ( (limit & 0xf0000) << 4) |
    ( (base & 0xff000000) << 56 )
   ) * 0x100000000;
}
/* ---------- GDT Laden (GDTR ändern) ----------------- */
void load_gdt(void){
  struct {
    uint16_t size;
    uint64_t *pointer;
  } __attribute__((packed)) gdtp = {
    .size = GDT_ENTRIES * 8 - 1,
    .pointer = gdt,
  };
  asm volatile("lgdt %0" : : "m" (gdtp));//GDT Laden
}
/* ---------- GDT initalisieren ----------------------- */
void init_gdt(void){
 
  //Nulldeskriptor
    set_gdt_entry(0, 0, 0, 0, 0);

  //Kernel - Codesegment
    set_gdt_entry(1, 0xfffff, 0, //index, limit, base
GDT_CODESEG_RD | GDT_SEGMENT | GDT_RING0 | GDT_PRESENT,//Access-Byte
GDT_32_BIT  | GDT_4K_GRAN); //Flags
     
  //Kernel - Datensegment      
    set_gdt_entry(2, 0xfffff, 0,     //index, limit, base
GDT_DATASEG_WR | GDT_SEGMENT | GDT_RING0 | GDT_PRESENT,//Access-Byte
GDT_32_BIT  | GDT_4K_GRAN);       //Flags
     
  //Userspace - Codesegment    
    set_gdt_entry(3, 0xfffff, 0, //index, limit, base
GDT_CODESEG_RD | GDT_SEGMENT | GDT_RING3 | GDT_PRESENT,//Access-Byte
GDT_32_BIT  | GDT_4K_GRAN); //Flags
     
  //Userpsace - Datensegment      
    set_gdt_entry(4, 0xfffff, 0, //index, limit, base
GDT_DATASEG_WR | GDT_SEGMENT | GDT_RING3 | GDT_PRESENT,//Access-Byte
         GDT_32_BIT  | GDT_4K_GRAN); //Flags
   
  //Task State Segment
    set_gdt_entry(5, sizeof(tss)-1, (uint32_t) &tss, //index, limit, base
GDT_TSS | GDT_PRESENT | GDT_RING3, //Access-Byte
GDT_32_BIT  | GDT_4K_GRAN); //Flags

   // nach ss0 das Kernel Datensegment legen
    tss[2] = 0x10;
}
/* ---------- GDT schnell initalisieren --------------- */
void init_gdt_fast(void){
  gdt[0] = 0x0000000000000000;//Nulldeskriptor
  gdt[1] = 0x00FC9A000000FFFF;//Kernel - Codesegment
  gdt[2] = 0x00FC92000000FFFF;//Kernel - Datensegment
  gdt[3] = 0x00FCFA000000FFFF;//Userspace - Codesegment
  gdt[4] = 0x00FCF2000000FFFF;//Userpsace - Datensegment
//   gdt[5] = 0x0000000000000000;//Task State Segment
}
/* ---------- Segmenregister neuladen ----------------- */
void reload_segment_registers(void){
  asm volatile(
"ljmpl $0x08, $1f\n\t"
"1:\n\t"
        "mov $0x10, %eax\n\t"
        "mov %eax, %ds\n\t"
        "mov %eax, %es\n\t"
        "mov %eax, %fs\n\t"
        "mov %eax, %gs\n\t"
        "mov %eax, %ss\n\t"
  );
}
/* ---------- Taskregister neuladen ------------------- */
void reload_task_registers(void){
  asm volatile("ltr %%ax" : : "a" (5 << 3));
}

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 17. April 2012, 16:05 »
könnte es sein, dass sich jetzt der Fehler in der GDT bemerkbar macht?
Was mache ich da überhaupt für einen Fehler? (in set_gdt_entry)


LG micha
« Letzte Änderung: 17. April 2012, 16:12 von micha »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 17. April 2012, 19:20 »
Ja, die GDT-Einträge setzt du nicht richtig.

  //obere 32-Bit
  gdt[i] |=(
    ( (base & 0x00ff0000) >> 16 ) |
    ( access << 8 ) |
    ( flags << 16 ) |
    ( (limit & 0xf0000) << 4) |
    ( (base & 0xff000000) << 56 )
   ) * 0x100000000;
Die oberen 4 Bits von Limit (Bits 16 bis 19, also limit & 0xf0000) müssen an die Bitpositionen 16 bis 19 des oberen Worts. Siehe Grafik hier: http://www.lowlevel.eu/wiki/GDT#Struktur Also bleiben die an der selben Stelle. Das heißt kein Shift um 4 nötig.

Dann müssen die oberen 8 Bits von base (Bits 24 bis 31, also base & 0xff000000) an die Bitpositionen 24 bis 31 des oberen Worts. Also bleiben die auch an der selben Stelle. Das heißt kein Shift um 56 nötig. Außerdem wäre der Shift zusammen mit der Multiplikation ein Shift um 56+32=88 Bits ...

Ob das das Problem löst, weiß ich nicht.
Dieser Text wird unter jedem Beitrag angezeigt.

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 17. April 2012, 19:43 »
Nunja. Nur das wirds wohl nicht allein gewesen sein. Es gibt also auch noch andere Fehler.
Immerhin springt er jetzt nicht mehr irgendwo hin und versucht irgendeinen Quatsch auszuführen.....er startet neu.
Liegt das dann an dem TSS? Das sollte doch eigentlich stimmen.?
« Letzte Änderung: 17. April 2012, 19:45 von micha »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 17. April 2012, 19:53 »
Die Flags für den TSS-Deskriptor sehen nach Copy&Paste aus. Da sollteste noch mal gucken.
Dieser Text wird unter jedem Beitrag angezeigt.

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 17. April 2012, 19:59 »
Also im Wiki-Artikel TSS steht da nix über die Flags in der GDT.
hab auch mal mit 0 in den Flags probiert: kein Unterschied

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 17. April 2012, 20:05 »
Probier mal 0x89. Die 8 ist das present flag und die 9 ist der in http://www.lowlevel.eu/wiki/TSS erwähnte type.
Dieser Text wird unter jedem Beitrag angezeigt.

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 18. April 2012, 14:26 »
keine Änderung  :-(
qemu startet auch schon beim neuladen der Segmentregister neu

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 20. April 2012, 14:37 »
Also jetzt nochmal zur Zusammenfassung.

Mein Problem liegt jetzt in der GDT.
der Code:
gdt.c
#include <stdint.h>
#include "gdt.h"

//Acessbyte
#define GDT_PRESENT 0x80
#define GDT_SEGMENT 0x10
#define GDT_RING0   0x00
#define GDT_RING3   0x60
#define GDT_CODESEG_NR 0x00
#define GDT_CODESEG_RD 0x0A
#define GDT_DATASEG_RD 0x00
#define GDT_DATASEG_WR 0x02
#define GDT_TSS        0x09

//Flags
#define GDT_4K_GRAN 0x08
#define GDT_32_BIT  0x04

/* ---------- Globale Variablen ----------------------- */
static uint64_t gdt[GDT_ENTRIES]; //Global Deskriptor Table
static uint32_t tss[TSS_SIZE] = {0, 0, 0x10}; //Task State Segment
/* ---------- Eintrag in die GDT setzen --------------- */
void set_gdt_entry(int i, uint32_t limit, uint32_t base, uint8_t access, uint8_t flags){
  gdt[i] = 0;
  //untere 32-Bit
  gdt[i] = (limit & 0x0ffff) | ((base & 0x0000ffff) << 16);
  //obere 32-Bit
  gdt[i] |=(
    ( (base & 0x00ff0000) >> 16 ) |
    ( access << 8 ) |
    ( flags << 16 ) |
    ( limit & 0xf0000 ) |
    ( base & 0xff000000 )
   ) * 0x100000000;
}
/* ---------- GDT Laden (GDTR ändern) ----------------- */
void load_gdt(void){
  struct {
    uint16_t size;
    uint64_t *pointer;
  } __attribute__((packed)) gdtp = {
    .size = GDT_ENTRIES * 8 - 1,
    .pointer = gdt,
  };
  asm volatile("lgdt %0" : : "m" (gdtp));//GDT Laden
}
/* ---------- GDT initalisieren ----------------------- */
void init_gdt(void){
 
  //Nulldeskriptor
    set_gdt_entry(GDT_ENTRY_NULL, 0, 0, 0, 0);

  //Kernel - Codesegment
    set_gdt_entry(GDT_ENTRY_KERNEL_CODE, 0xfffff, 0, //index, limit, base
GDT_CODESEG_RD | GDT_SEGMENT | GDT_RING0 | GDT_PRESENT,//Access-Byte
GDT_32_BIT  | GDT_4K_GRAN); //Flags
     
  //Kernel - Datensegment      
    set_gdt_entry(GDT_ENTRY_KERNEL_DATA, 0xfffff, 0, //index, limit, base
GDT_DATASEG_WR | GDT_SEGMENT | GDT_RING0 | GDT_PRESENT,//Access-Byte
GDT_32_BIT  | GDT_4K_GRAN);       //Flags
     
  //Userspace - Codesegment    
    set_gdt_entry(GDT_ENTRY_USER_CODE, 0xfffff, 0, //index, limit, base
GDT_CODESEG_RD | GDT_SEGMENT | GDT_RING3 | GDT_PRESENT,//Access-Byte
GDT_32_BIT  | GDT_4K_GRAN); //Flags
     
  //Userpsace - Datensegment      
    set_gdt_entry(GDT_ENTRY_USER_DATA, 0xfffff, 0, //index, limit, base
GDT_DATASEG_WR | GDT_SEGMENT | GDT_RING3 | GDT_PRESENT,//Access-Byte
         GDT_32_BIT  | GDT_4K_GRAN); //Flags
   
  //Task State Segment
    set_gdt_entry(GDT_ENTRY_TSS, sizeof(tss)-1, (uint32_t) &tss,//index, limit, base
GDT_TSS | GDT_PRESENT | GDT_RING3, //Access-Byte
0); //Flags

   // nach ss0 das Kernel Datensegment legen
    tss[2] = 0x10;
}
/* ---------- GDT schnell initalisieren --------------- */
void init_gdt_fast(void){
  gdt[0] = 0x0000000000000000;//Nulldeskriptor
  gdt[1] = 0x00FC9A000000FFFF;//Kernel - Codesegment
  gdt[2] = 0x00FC92000000FFFF;//Kernel - Datensegment
  gdt[3] = 0x00FCFA000000FFFF;//Userspace - Codesegment
  gdt[4] = 0x00FCF2000000FFFF;//Userpsace - Datensegment
  set_gdt_entry(5, sizeof(tss)-1, (uint32_t) &tss, //index, limit, base
GDT_TSS | GDT_PRESENT | GDT_RING3, //Access-Byte
0); //Flags

   // nach ss0 das Kernel Datensegment legen
    tss[2] = 0x10;
}

/* -------Ende gdt.c ------*/

Um unnötige Fragen zu vermeiden: Ich verwende nicht init_gdt_fast sondern init_gdt!!


Wo steckt jetzt mein Fehler, dass Qemu beim beladen der Segmentregister neustertet? ( relaod_segment_registers(void) )
??? :?
Bzw. Warum startet Qemu nicht neu, wenn ich diese (falsche) Funktion verwende?:
/* ---------- Eintrag in die GDT setzen --------------- */
void set_gdt_entry(int i, uint32_t limit, uint32_t base, uint8_t access, uint8_t flags){
  gdt[i] = 0;
  //untere 32-Bit
  gdt[i] = (limit & 0x0ffff) | ((base & 0x0000ffff) << 16);
  //obere 32-Bit
  gdt[i] |=(
    ( (base & 0x00ff0000) >> 16 ) |
    ( access << 8 ) |
    ( flags << 16 ) |
    ( (limit & 0xf0000) << 4) |
    ( base & 0xff000000 )
   ) * 0x100000000;
}

Micha

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 22. April 2012, 17:17 »
So. Das Problem mit der GDT habe ich jetzt nicht mehr (die Flags müssen um 20 geschoben werden).   :-)

Allerdings hab ich jetzt ein anders problem:
   Wenn ich mein Userspace-Codesegment auf ring-0 setze (das Segment für die Tasks) und in meinem init_task .cs auf 0x18 statt
   0x1b setzte funktioniert das Multitasking , aber nur in Ring-0.
   In Ring-3 geht das genze nicht: es kommt dann der Fehler von qemu: fatal: trying to execute code outside RAM or ROM at 0x...
   d.h. er springt irgendwo hin.

könnt ihr mir da helfen?

« Letzte Änderung: 22. April 2012, 17:24 von micha »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 26. April 2012, 22:07 »
Du könntest dir mal das Log von QEMU anschauen. Auch sind der Zustand der IDT und eventuell der GDT (und Segmentregister) interessant. Ansonsten könnte es auch ein Problem bei der Initialisierung des TSS bzw. Task Registers geben.
Dieser Text wird unter jedem Beitrag angezeigt.

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 27. April 2012, 17:21 »
Mit meinem Wissen kann ich da nicht viel über den Sprung ins nichts herauslesen.
Das ist vielleicht was für die Experten

SMM: enter
EAX=00000001 EBX=80000b58 ECX=00000000 EDX=00000cfc
ESI=000e5cbd EDI=0003802d EBP=00000cf8 ESP=00006f00
EIP=000e7a31 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 00cf9b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000fce38 00000037
IDT=     000fdcf0 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=000e5c90 CCD=00000001 CCO=LOGICB 
EFER=0000000000000000
SMM: after RSM
EAX=00000001 EBX=80000b58 ECX=00000000 EDX=00000cfc
ESI=000e5cbd EDI=0003802d EBP=00000cf8 ESP=00006f00
EIP=000e7a31 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     000fce38 00000037
IDT=     000fdcf0 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000000 CCD=ffffff9c CCO=EFLAGS 
EFER=0000000000000000
     0: v=21 e=0000 i=0 cpl=0 IP=0008:001022fd pc=001022fd SP=0010:00107f40 EAX=000000ed
EAX=000000ed EBX=0002c100 ECX=00000410 EDX=00000060
ESI=0002c276 EDI=0002c27b EBP=00107f78 ESP=00107f40
EIP=001022fd EFL=00000202 [-------] 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 =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 001041a0 0000007f 0000e900 DPL=3 TSS32-avl
GDT=     0010c8c0 0000002f
IDT=     00108000 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000008 CCD=00107f30 CCO=SUBL   
EFER=0000000000000000
     1: v=21 e=0000 i=0 cpl=0 IP=0008:00102091 pc=00102091 SP=0010:00107fb0 EAX=00000000
EAX=00000000 EBX=0002c100 ECX=00000410 EDX=00000060
ESI=0002c276 EDI=0002c27b EBP=00107fc8 ESP=00107fb0
EIP=00102091 EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 001041a0 0000007f 0000e900 DPL=3 TSS32-avl
GDT=     0010c8c0 0000002f
IDT=     00108000 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000008 CCD=00107fa0 CCO=SUBL   
EFER=0000000000000000
     2: v=21 e=0000 i=0 cpl=0 IP=0008:001022fd pc=001022fd SP=0010:00107f40 EAX=000000f3
EAX=000000f3 EBX=0002c100 ECX=00000410 EDX=00000060
ESI=0002c276 EDI=0002c27b EBP=00107f78 ESP=00107f40
EIP=001022fd EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 001041a0 0000007f 0000e900 DPL=3 TSS32-avl
GDT=     0010c8c0 0000002f
IDT=     00108000 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000008 CCD=00107f30 CCO=SUBL   
EFER=0000000000000000
     3: v=21 e=0000 i=0 cpl=0 IP=0008:001020b1 pc=001020b1 SP=0010:00107fb0 EAX=00000000
EAX=00000000 EBX=0002c100 ECX=00000410 EDX=00000060
ESI=0002c276 EDI=0002c27b EBP=00107fc8 ESP=00107fb0
EIP=001020b1 EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 001041a0 0000007f 0000e900 DPL=3 TSS32-avl
GDT=     0010c8c0 0000002f
IDT=     00108000 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000008 CCD=00107fa0 CCO=SUBL   
EFER=0000000000000000
     4: v=21 e=0000 i=0 cpl=0 IP=0008:001022fd pc=001022fd SP=0010:00107f40 EAX=000000f4
EAX=000000f4 EBX=0002c100 ECX=00000410 EDX=00000060
ESI=0002c276 EDI=0002c27b EBP=00107f78 ESP=00107f40
EIP=001022fd EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 001041a0 0000007f 0000e900 DPL=3 TSS32-avl
GDT=     0010c8c0 0000002f
IDT=     00108000 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000008 CCD=00107f30 CCO=SUBL   
EFER=0000000000000000
     5: v=20 e=0000 i=0 cpl=0 IP=0008:001019cf pc=001019cf SP=0010:00107f90 EAX=00000001
EAX=00000001 EBX=0002c100 ECX=000006e0 EDX=000003d5
ESI=0002c276 EDI=0002c27b EBP=00107fc8 ESP=00107f90
EIP=001019cf EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 001041a0 0000007f 0000e900 DPL=3 TSS32-avl
GDT=     0010c8c0 0000002f
IDT=     00108000 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=0010caa0 CCO=EFLAGS 
EFER=0000000000000000
     6: v=20 e=0000 i=0 cpl=3 IP=001b:001013ba pc=001013ba SP=0023:0010b814 EAX=00000372
EAX=00000372 EBX=00000371 ECX=000b8000 EDX=000b8371
ESI=00000000 EDI=00000000 EBP=0010b84c ESP=0010b814
EIP=001013ba EFL=00000202 [-------] CPL=3 II=0 A20=1 SMM=0 HLT=0
ES =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
CS =001b 00000000 ffffffff 00cffa00 DPL=3 CS32 [-R-]
SS =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
DS =0023 00000000 ffffffff 00cff300 DPL=3 DS   [-WA]
FS =0000 00000000 00000000 00000000
GS =0000 00000000 00000000 00000000
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 001041a0 0000007f 0000e900 DPL=3 TSS32-avl
GDT=     0010c8c0 0000002f
IDT=     00108000 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000085 CCD=fffff472 CCO=EFLAGS 
EFER=0000000000000000
qemu: fatal: Trying to execute code outside RAM or ROM at 0x665b6620

EAX=00000010 EBX=00000371 ECX=000b8000 EDX=000b8371
ESI=00000000 EDI=00000000 EBP=0010b84c ESP=ffffffc0
EIP=665b6620 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 001041a0 0000007f 0000e900 DPL=3 TSS32-avl
GDT=     0010c8c0 0000002f
IDT=     00108000 000007f7
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000085 CCD=fffff472 CCO=EFLAGS 
EFER=0000000000000000
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

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 27. April 2012, 17:50 »
qemu: fatal: Trying to execute code outside RAM or ROM at 0x665b6620

EAX=00000010 EBX=00000371 ECX=000b8000 EDX=000b8371
ESI=00000000 EDI=00000000 EBP=0010b84c ESP=ffffffc0
EIP=665b6620 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0

Die interessanten Werte sind hier EIP (das ja auch in der Fehlermeldung erwähnt wird) und ESP. Der Wert in EIP sieht aus wie Maschinencode, was ich so interpretieren würde, dass in deinem Kernel (natürlich unbeabsichtigt) irgendwie ein ret ausgeführt wird, während der Stack Pointer auf Code zeigt. Dazu passt der Wert in ESP, der in einen Bereich zeigt, an dem das BIOS gemappt ist.

Meine Theorie dazu ist, dass irgendwo ESP mit 0 geladen wurde, und danach ein paar POPs/rets ausgeführt wurden. Du solltest also die Taskerzeugung, den Taskwechsler und den Scheduler genauer anschauen. Insbesondere solltest du versuchen rauszukriegen, ob der Task zu dem gewechselt wird, überhaupt gültig ist.
Dieser Text wird unter jedem Beitrag angezeigt.

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 28. April 2012, 14:56 »
möglicherweise liegt das garnicht am Multitasking.

Wenn ich das aktivieren des neuen Tasks (cpu = task_states[current_task];) rusnehme und an das ende von init dies
while(1){
    gets();
    puts("\n");
  }
setzte, kann man folgendes beobachten:
  • wenn man ein Zeichen eingibt, geht alles
  • wenn man zwei Zeichen eingibt geht alles
  • wenn man drei Zeichen eingibt geht alles
  • wenn man vier Zeichen eingibt kommt Invalid Opcode
  • wenn man fünf und mehr eingibt kommt das problem wie beim Multitasking(trying to execute code outside RAM or ROM...)

Das image ist im Anhang

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 05. May 2012, 14:11 »
Okay. Das Merkwürdige Problem mit der Tastatureingabe hab ich jetzt gelöst. (ich habe den Rückgabewert von gets nicht beachtet)

Es steht aber immernoch das Problem mit den Ringen:
* in Ring-0 funktioniert das Multitasking
* in Ring-3 funktioniert es nicht. :-(

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 10. May 2012, 14:36 »
Zitat
Meine Theorie dazu ist, dass irgendwo ESP mit 0 geladen wurde, und danach ein paar POPs/rets ausgeführt wurden. Du solltest also die Taskerzeugung, den Taskwechsler und den Scheduler genauer anschauen. Insbesondere solltest du versuchen rauszukriegen, ob der Task zu dem gewechselt wird, überhaupt gültig ist.

Frage: kann so ein Fehler nur in Assembler passieren oder geht das auch mit C?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 10. May 2012, 15:19 »
Wenn du die Aufteilung C/Assembler so machst wie das Tutorial, dann ist der Fehler höchstwahrscheinlich im C-Teil und wird höchstwahrscheinlich im Assembler-Teil sichtbar.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 21. May 2012, 18:29 »
Ich hab die GDT & IDT jetzt neu mit der geschickteren Variante über structs implementiert. Also daran liegts nicht.
Ich denke der Fehler müsste dann ist den Stubs liegen, eigentlich ist doch alles richtig.?!
// handle_interrupt aus common_handler.c
.extern handle_interrupt

.macro int_stub nr
.global int_handler\nr
int_handler\nr:
    push $0
    push $\nr
    jmp common_intr_handler
.endm

//Exeptions haben extra-stubs
// (siehe: kernel/interrupt/handler/exeption/handler.S)

//IRQs
int_stub 0x20
// 0x21: direct call
int_stub 0x22
int_stub 0x23
int_stub 0x24
int_stub 0x25
int_stub 0x26
int_stub 0x27
int_stub 0x28
int_stub 0x29
int_stub 0x2A
int_stub 0x2B
int_stub 0x2C
int_stub 0x2D
int_stub 0x2E
int_stub 0x2F

//Syscalls
int_stub 0x30

common_intr_handler:
  push %ebp
  push %edi
  push %esi
  push %edx
  push %ecx
  push %ebx
  push %eax
 
  // Kernel-Datensegmente laden
  mov $0x10, %ax
  mov %ax, %ds
  mov %ax, %es
 
  // ISR aufrufen
  push %esp
  call handle_interrupt
  mov %eax, %esp //Neuen Stack laden
 
  // User-Datensegmente laden
  mov $0x23, %ax
  mov %ax, %ds
  mov %ax, %es
 
  // Neue cpu herstellen
  pop %eax
  pop %ebx
  pop %ecx
  pop %edx
  pop %esi
  pop %edi
  pop %ebp
 
  // Errorcode und Interruptnummer vom Stack nehmen
  add $8, %esp
  iret
Wo könnten andere Fehler/Ursachen für den Sprung sein?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 21. May 2012, 19:43 »
Der ganze Prozessorzustand der hier geladen wird (mit den pops und am Ende u.a. esp mit iret), kommt ja aus der struct task oder wie die bei dir heißt. Wenn dein C-Code diese struct irgendwie falsch befüllt oder beim Taskswitch irgendwie kaputtmacht, dann lädt der eigentlich korrekte Assemblercode natürlich falsche Werte. Ich würde an deiner Stelle vor dem Taskswitch ein paar Debugausgaben machen, die diese Felder in der struct task ausgeben.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 24. May 2012, 18:02 »
Das Problem liegt ja nicht darin, dass die Struktur falsch befüllt wird, sonder dass wenn ich in meinen Tasks cs auf 0x1b setze funktioniert es nicht mehr. Mit 0x08 gehts.
Ist das verständlicher?

 

Einloggen