feat: description GDT++, ajout pagination 4k/4m

This commit is contained in:
Nicolas Hordé 2018-10-02 02:16:14 +02:00
parent e137749be8
commit 62bd72dfe0
10 changed files with 172 additions and 75 deletions

View File

@ -109,10 +109,22 @@ Commandes de compilation de COS2000
* ```make test64``` lance l'émulation QEMU en 64 bits sur disque dur UEFI
* ```make clean``` supprime les fichers compilés
Pour tester fait donc un simple ```make test``` qui compilera et émulera le système directement.
#### Utilisation
##### Sur un ordinateur émulé
Pour tester l'OS en émulation taper donc la commande ```make test``` qui compilera avant de lancer Qemu.
##### Sur un ordinateur physique
Il faut d'abord copier l'image sur une clé (Attention l'opération effacera le contenu de la clé) :
```dd if=./final/harddisk.img.final of=/dev/sdx bs=1M``` (ou sdx est votre périphérique)
Bootez sur votre clé en mode bios (legacy). Il est possible que des dysfonctionnement apparaissent sur des machine x86_64 (en cours de résolution).
##### Usage de COS2000
Pour l'instant quelques commandes seulement sont disponibles:
* REBOOT redémarre le PC,

View File

@ -1,19 +1,43 @@
#include <types.h>
/* Ordre imposé par SYSENTER */
#define SEL_KERNEL_CODE 0x8 /* selecteur code du kernel */
#define SEL_KERNEL_STACK 0x10 /* selecteur pile du kernel */
#define SEL_USER_CODE 0x18 /* selecteur code utilisateur */
#define SEL_USER_STACK 0x20 /* selecteur pile utilisateur */
#define SEL_KERNEL_DATA 0x28 /* selecteur data du kernel */
#define SEL_USER_DATA 0x30 /* selecteur data utilisateur */
#define SEL_KERNEL_CODE 0x8 /* Selecteur code du kernel */
#define SEL_KERNEL_STACK 0x10 /* Selecteur pile du kernel */
#define SEL_USER_CODE 0x18 /* Selecteur code utilisateur */
#define SEL_USER_STACK 0x20 /* Selecteur pile utilisateur */
#define SEL_KERNEL_DATA 0x28 /* Selecteur data du kernel */
#define SEL_USER_DATA 0x30 /* Selecteur data utilisateur */
#define SEL_TSS 0x38 /* selecteur TSR */
#define SEL_TSS 0x38 /* Selecteur TSR */
#define STACK_OFFSET 0xFFFF /* adresse de la pile du kernel */
#define GDT_SIZE 0x8 /* Nombre de descripteurs */
#define SIZEGDT 0x8 /* nombre de descripteurs */
#define BASEGDT 0x00000800 /* addr de la GDT */
/* Drapeau des descripteurs GDT */
#define GRANULARITY_4K 0b00001000 /* Granularité alignement 4096 octet*/
#define GRANULARITY_1B 0b00000000 /* Granularité alignement 1 octet */
#define OPSIZE_32B 0b00000100 /* Taille opérandes 32 bits*/
#define OPSIZE_16B 0b00000000 /* Taille opérandes 16 bits*/
#define SYS_AVAILABLE 0b00000001 /* Disponible pour le système (à définir)*/
#define SEG_ACCESSED 0b00000001 /* Segment accédé (code ou data) */
#define SEG_DATA 0b00000000 /* Segment de données */
#define SEG_CODE 0b00001000 /* Segment de données */
#define SEG_READ_WRITE 0b00000010 /* Segment lecture-ecriture (data) */
#define SEG_EXPAND_DOWN 0b00000100 /* Segment avec expand-down (data) */
#define SEG_READ 0b00000010 /* Segment lecture (code) */
#define SEG_CONFORMING 0b00000100 /* Segment conforming (code) */
#define SEG_PRESENT 0b10000000 /* Segment défini (obligatoire) */
#define SEG_RING0 0b00000000 /* Segment anneau 0 */
#define SEG_RING1 0b00100000 /* Segment anneau 0 */
#define SEG_RING2 0b01000000 /* Segment anneau 0 */
#define SEG_RING3 0b01100000 /* Segment anneau 0 */
#define SEG_NORMAL 0b00010000 /* Segment normal pile/data/code (0 pour système) */
typedef struct gdtdes {
u16 lim0_15;

View File

@ -20,11 +20,11 @@
#define ICW4_BUF_MASTER 0x0C /* mode/master avec tampon*/
#define ICW4_SFNM 0x10 /* Complètement lié ou non */
#define INTGATE 0x8E00 /* utilise pour gerer les interruptions */
#define TRAPGATE 0x8F00 /* utilise pour faire des appels systemes */
#define TASKGATE 0x8500 /* utilise pour commuter des taches */
#define CALLGATE 0x8C00 /* utilise pour appeler du code */
#define LDTDES 0x8200 /* utilise pour pointer une LDT */
#define INTGATE 0x8E00 /* utilise pour gerer les interruptions */
#define TRAPGATE 0x8F00 /* utilise pour faire des appels systemes */
#define TASKGATE 0x8500 /* utilise pour commuter des taches */
#define CALLGATE 0x8C00 /* utilise pour appeler du code */
#define LDTDES 0x8200 /* utilise pour pointer une LDT */
/* 00-11-010-0 : Compteur 0 - LSB puis MSB - generateur taux - binaire */
#define TIMER0 0x40 /* port E/S pour le timer canal 0 */

View File

@ -3,6 +3,29 @@
/* */
#include "types.h"
#define PAGESIZE 4096 /* Taille d'une page */
#define PAGENUMBER 1024 /* Nombre de pages */
#define IDT_ADDR 0x00000000 /* adresse de la IDT */
#define GDT_ADDR 0x00000800 /* adresse de la GDT */
#define KERNEL_PGD_ADDR 0x00001000 /* adresse de la page directory */
#define KERNEL_STACK_ADDR 0x0009FFFF /* adresse de la pile du kernel */
#define KERNEL_CODE_ADDR 0x00100000
/* page directory */
#define PAGE_PRESENT 0b000000001/* page directory / table */
#define PAGE_WRITE 0b000000010 /* page lecture ecriture */
#define PAGE_ALL 0b000000100 /* accessible user & supervisor */
#define PAGE_WTROUGH 0b000001000 /* write-through cache */
#define PAGE_NOCACHE 0b000010000 /* cache desactivé */
#define PAGE_ACCESS 0b000100000 /* cache desactivé */
#define PAGE_4MB 0b010000000 /* page de 4mb au lieu de 4k (NECESSITE PSE)*/
/* page table */
#define PAGE_CACHE 0b000010000 /* page en cache */
#define PAGE_DIRTY 0b001000000 /* page écrite */
#define PAGE_GLOBAL 0b100000000 /* évite que le TLB mette à jour l'adresse dans le cache si CR4 est remis à zéro (NECESSITE CR4) */
void memset(void *dst, u8 val, u32 count,u32 size);
void memcpy(void *src, void *dst, u32 count, u32 size);
u32 memcmp(void *src, void *dst, u32 count, u32 size);

View File

@ -4,12 +4,13 @@
#include "gdt.h"
#include "asm.h"
#include "types.h"
#include "memory.h"
/* registre gdt */
static struct gdtr gdtreg;
/* table de GDT */
static gdtdes gdt[SIZEGDT];
static gdtdes gdt[GDT_SIZE];
/* TSS */
static struct tss tss0;
@ -20,23 +21,23 @@ static struct tss tss0;
void initgdt(u32 offset)
{
makegdtdes(0x0, 0x00000, 0x00, 0x00, &gdt[0]); /* descripteur nul */
makegdtdes(0x0, 0xFFFFF, 0x9B, 0x0D, &gdt[1]); /* code -> SEL_KERNEL_CODE */
makegdtdes(0x0, 0x00000, 0x97, 0x0D, &gdt[2]); /* pile -> SEL_KERNEL_STACK */
makegdtdes(0x0, 0xFFFFF, 0xFF, 0x0D, &gdt[3]); /* code -> SEL_USER_CODE */
makegdtdes(0x0, 0x00000, 0xF7, 0x0D, &gdt[4]); /* pile -> SEL_USER_STACK */
makegdtdes(0x0, 0xFFFFF, 0x93, 0x0D, &gdt[5]); /* data -> SEL_KERNEL_DATA */
makegdtdes(0x0, 0xFFFFF, 0xF3, 0x0D, &gdt[6]); /* data -> SEL_USER_DATA */
makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_CODE | SEG_RING0 | SEG_READ | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[1]); /* code -> SEL_KERNEL_CODE */
makegdtdes(0x0, 0x00000, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING0 | SEG_EXPAND_DOWN | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[2]); /* pile -> SEL_KERNEL_STACK */
makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_CODE | SEG_RING3 | SEG_CONFORMING | SEG_READ | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[3]); /* code -> SEL_USER_CODE */
makegdtdes(0x0, 0x00000, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING3 | SEG_EXPAND_DOWN | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[4]); /* pile -> SEL_USER_STACK */
makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING0 | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[5]); /* data -> SEL_KERNEL_DATA */
makegdtdes(0x0, 0xFFFFF, SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING3 | SEG_READ_WRITE | SEG_ACCESSED, GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE, &gdt[6]); /* data -> SEL_USER_DATA */
tss0.trapflag = 0x00;
tss0.iomap = 0x00;
tss0.esp0 = 0x1FFF0;
tss0.ss0 = SEL_TSS;
makegdtdes(&tss0, 0x67, 0xE9, 0x00, &gdt[7]); /* descripteur de tss */
makegdtdes(&tss0, 0x67, SEG_PRESENT | SEG_CODE | SEG_RING3 | SEG_ACCESSED , 0x00, &gdt[7]); /* descripteur de tss */
/* initialise le registre gdt */
gdtreg.limite = SIZEGDT * 8;
gdtreg.base = BASEGDT;
gdtreg.limite = GDT_SIZE * 8;
gdtreg.base = GDT_ADDR;
/* recopie de la GDT a son adresse */
memcpy(&gdt, (u8 *) gdtreg.base, gdtreg.limite, 1);
/* chargement du registre GDT */
@ -70,7 +71,7 @@ void initselectors(u32 executingoffset)
ljmp %[code], $raz \n \
raz: \n \
pushl %%ebx \n \
ret\n"::[data] "i"(SEL_KERNEL_DATA),[code] "i"(SEL_KERNEL_CODE),[stack] "i"(SEL_KERNEL_STACK),[stackoff] "i"(STACK_OFFSET),[offset] "m"(executingoffset));
ret\n"::[data] "i"(SEL_KERNEL_DATA),[code] "i"(SEL_KERNEL_CODE),[stack] "i"(SEL_KERNEL_STACK),[stackoff] "i"(KERNEL_STACK_ADDR),[offset] "m"(executingoffset));
}
/*******************************************************************************/

View File

@ -6,16 +6,15 @@
#include "asm.h"
#include "memory.h"
#include "video.h"
#include "gdt.h"
#define SIZEIDT 256 /* nombre de descripteurs */
#define BASEIDT 0x00000000 /* addr de la IDT */
#define IDT_SIZE 256 /* nombre de descripteurs */
/* registre idt */
static struct idtr idtreg;
/* table de IDT */
static idtdes idt[256];
static idtdes idt[IDT_SIZE];
/******************************************************************************/
/* Initialise le controleur d'interruption 8259A */
@ -131,9 +130,9 @@ void cpuerror(const u8 * src)
print("\033[31m***** ERREUR CPU ****\r\n -");
print(src);
dump_regs();
while (true) {
/*while (true) {
nop();
}
}*/
}
/******************************************************************************/
@ -492,53 +491,53 @@ void irq15()
void initidt(void)
{
u16 i;
putidt((u32) exception0, 0x20, INTGATE, 0);
putidt((u32) exception1, 0x20, INTGATE, 1);
putidt((u32) exception2, 0x20, INTGATE, 2);
putidt((u32) exception3, 0x20, INTGATE, 3);
putidt((u32) exception4, 0x20, INTGATE, 4);
putidt((u32) exception5, 0x20, INTGATE, 5);
putidt((u32) exception6, 0x20, INTGATE, 6);
putidt((u32) exception7, 0x20, INTGATE, 7);
putidt((u32) exception8, 0x20, INTGATE, 8);
putidt((u32) exception9, 0x20, INTGATE, 9);
putidt((u32) exception10, 0x20, INTGATE, 10);
putidt((u32) exception11, 0x20, INTGATE, 11);
putidt((u32) exception12, 0x20, INTGATE, 12);
putidt((u32) exception13, 0x20, INTGATE, 13);
putidt((u32) exception14, 0x20, INTGATE, 14);
putidt((u32) exception15, 0x20, INTGATE, 15);
putidt((u32) exception16, 0x20, INTGATE, 16);
putidt((u32) exception17, 0x20, INTGATE, 17);
putidt((u32) exception18, 0x20, INTGATE, 18);
putidt((u32) exception0, SEL_KERNEL_CODE, INTGATE, 0);
putidt((u32) exception1, SEL_KERNEL_CODE, INTGATE, 1);
putidt((u32) exception2, SEL_KERNEL_CODE, INTGATE, 2);
putidt((u32) exception3, SEL_KERNEL_CODE, INTGATE, 3);
putidt((u32) exception4, SEL_KERNEL_CODE, INTGATE, 4);
putidt((u32) exception5, SEL_KERNEL_CODE, INTGATE, 5);
putidt((u32) exception6, SEL_KERNEL_CODE, INTGATE, 6);
putidt((u32) exception7, SEL_KERNEL_CODE, INTGATE, 7);
putidt((u32) exception8, SEL_KERNEL_CODE, INTGATE, 8);
putidt((u32) exception9, SEL_KERNEL_CODE, INTGATE, 9);
putidt((u32) exception10, SEL_KERNEL_CODE, INTGATE, 10);
putidt((u32) exception11, SEL_KERNEL_CODE, INTGATE, 11);
putidt((u32) exception12, SEL_KERNEL_CODE, INTGATE, 12);
putidt((u32) exception13, SEL_KERNEL_CODE, INTGATE, 13);
putidt((u32) exception14, SEL_KERNEL_CODE, INTGATE, 14);
putidt((u32) exception15, SEL_KERNEL_CODE, INTGATE, 15);
putidt((u32) exception16, SEL_KERNEL_CODE, INTGATE, 16);
putidt((u32) exception17, SEL_KERNEL_CODE, INTGATE, 17);
putidt((u32) exception18, SEL_KERNEL_CODE, INTGATE, 18);
for (i = 19; i < 32; i++) {
putidt((u32) interruption, 0x20, TRAPGATE, i);
}
putidt((u32) irq0, 0x20, INTGATE, 32);
putidt((u32) irq1, 0x20, INTGATE, 33);
putidt((u32) irq2, 0x20, INTGATE, 34);
putidt((u32) irq3, 0x20, INTGATE, 35);
putidt((u32) irq4, 0x20, INTGATE, 36);
putidt((u32) irq5, 0x20, INTGATE, 37);
putidt((u32) irq6, 0x20, INTGATE, 38);
putidt((u32) irq7, 0x20, INTGATE, 39);
putidt((u32) irq0, SEL_KERNEL_CODE, INTGATE, 32);
putidt((u32) irq1, SEL_KERNEL_CODE, INTGATE, 33);
putidt((u32) irq2, SEL_KERNEL_CODE, INTGATE, 34);
putidt((u32) irq3, SEL_KERNEL_CODE, INTGATE, 35);
putidt((u32) irq4, SEL_KERNEL_CODE, INTGATE, 36);
putidt((u32) irq5, SEL_KERNEL_CODE, INTGATE, 37);
putidt((u32) irq6, SEL_KERNEL_CODE, INTGATE, 38);
putidt((u32) irq7, SEL_KERNEL_CODE, INTGATE, 39);
for (i = 40; i < 96; i++) {
putidt((u32) interruption, 0x20, TRAPGATE, i);
}
putidt((u32) irq8, 0x20, INTGATE, 96);
putidt((u32) irq9, 0x20, INTGATE, 97);
putidt((u32) irq10, 0x20, INTGATE, 98);
putidt((u32) irq11, 0x20, INTGATE, 99);
putidt((u32) irq12, 0x20, INTGATE, 100);
putidt((u32) irq13, 0x20, INTGATE, 101);
putidt((u32) irq14, 0x20, INTGATE, 102);
putidt((u32) irq15, 0x20, INTGATE, 103);
for (i = 104; i < SIZEIDT; i++) {
putidt((u32) irq8, SEL_KERNEL_CODE, INTGATE, 96);
putidt((u32) irq9, SEL_KERNEL_CODE, INTGATE, 97);
putidt((u32) irq10, SEL_KERNEL_CODE, INTGATE, 98);
putidt((u32) irq11, SEL_KERNEL_CODE, INTGATE, 99);
putidt((u32) irq12, SEL_KERNEL_CODE, INTGATE, 100);
putidt((u32) irq13, SEL_KERNEL_CODE, INTGATE, 101);
putidt((u32) irq14, SEL_KERNEL_CODE, INTGATE, 102);
putidt((u32) irq15, SEL_KERNEL_CODE, INTGATE, 103);
for (i = 104; i < IDT_SIZE; i++) {
putidt((u32) interruption, 0x20, TRAPGATE, i);
}
/* initialise le registre idt */
idtreg.limite = SIZEIDT * 8;
idtreg.base = BASEIDT;
idtreg.limite = IDT_SIZE * 8;
idtreg.base = IDT_ADDR;
/* recopie de la IDT a son adresse */
memcpy(&idt, (u8 *) idtreg.base, idtreg.limite, 1);
/* chargement du registre IDTR */

View File

@ -2,6 +2,34 @@
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
#include "types.h"
#include "memory.h"
u32 *pd0 = (u32 *) KERNEL_PGD_ADDR; /* page directory */
u8 *pg0 = (u8 *) 0; /* page 0 */
u8 *pg1 = (u8 *) (PAGESIZE*PAGENUMBER); /* page 1 */
/*******************************************************************************/
/* Initialisation de la mémoire paginée */
void initpaging(void)
{
u16 i;
pd0[0] = ((u32) pg0 | (PAGE_PRESENT | PAGE_WRITE | PAGE_4MB));
pd0[1] = ((u32) pg1 | (PAGE_PRESENT | PAGE_WRITE | PAGE_4MB));
for (i = 2; i < 1023; i++)
pd0[i] = ((u32) pg1 + PAGESIZE * i) | (PAGE_PRESENT | PAGE_WRITE);
pd0[1023] = ((u32) pd0 | (PAGE_PRESENT | PAGE_WRITE));
asm("mov %[pd0_addr], %%eax \n \
mov %%eax, %%cr3 \n \
mov %%cr4, %%eax \n \
or $0x00000010, %%eax \n \
mov %%eax, %%cr4 \n \
mov %%cr0, %%eax \n \
or $0x80000001, %%eax \n \
mov %%eax, %%cr0"::[pd0_addr]"m"(pd0));
}
/*******************************************************************************/
/* Copie un octet une ou plusieurs fois en mémoire */

View File

@ -173,7 +173,7 @@ int readgdt()
gdtdes *desc;
struct gdtr gdtreg;
sgdt(&gdtreg);
printf("Information sur la LGDT\r\nAdresse:%X Limite:%hX", gdtreg.base,
printf("Information sur la GDT\r\nAdresse:%X Limite:%hX", gdtreg.base,
(u32) gdtreg.limite);
desc = gdtreg.base;
for (index = 0; index < gdtreg.limite / sizeof(gdtdes); index++) {
@ -205,7 +205,7 @@ int readgdt()
print("Normal ");
} else {
print("Data.");
if ((acces >> 3) & 1 == 1)
if ((acces >> 2) & 1 == 1)
print("Down ");
else
print("up ");

View File

@ -4,6 +4,7 @@
#include <types.h>
#include <gdt.h>
#include <asm.h>
#include <memory.h>
/* 32bit SYSENTER instruction entry.
*
@ -33,7 +34,7 @@ void sysenter_handler(void)
void initsyscall(void)
{
wrmsr(0x174, SEL_KERNEL_CODE, 0x0);
wrmsr(0x175, STACK_OFFSET, 0x0);
wrmsr(0x175, KERNEL_STACK_ADDR, 0x0);
wrmsr(0x176, &sysenter_handler, 0x0);
}

View File

@ -74,6 +74,10 @@ int main(u32 magic, u32 addr)
inittr();
ok();
print("\033[37m\033[0m -Initilisation de la pagination (PAGING)");
initpaging();
ok();
print("\033[37m\033[0m -Initilisation des interruptions (IDT/PIC)");
initidt();
initpic();
@ -103,5 +107,10 @@ int main(u32 magic, u32 addr)
initsyscall();
ok();
print(" -Create a double fault error");
asm("mov $0x66666666, %eax \n \
mov %eax,0xE0000000");
error();
shell();
}