/*******************************************************************************/ /* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ /* */ #include "types.h" #include "asm.h" #ifndef _INTERRUPTS # define _INTERRUPTS # define PIC1_CMD 0x20 /*PIC 8259A Commandes n°1 */ # define PIC1_DATA 0x21 /*PIC 8259A Données n°1 */ # define PIC2_CMD 0xa0 /*PIC 8259A Commandes n°2 */ # define PIC2_DATA 0xa1 /*PIC 8259A Données n°1 */ # define ICW1_ICW4 0x01 /* ICW4 ou pas */ # define ICW1_SINGLE 0x02 /* mode seul ou cascadé */ # define ICW1_INTERVAL4 0x04 /* adresses appel d'interval 4 ou 8 */ # define ICW1_LEVEL 0x08 /* déclenchement sur niveau ou sur front */ # define ICW1_INIT 0x10 /* Initialization */ # define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ # define ICW4_AUTO 0x02 /* Auto EOI ou normal */ # define ICW4_BUF_SLAVE 0x08 /* mode/slave avec tampon */ # define ICW4_BUF_MASTER 0x0C /* mode/master avec tampon */ # define ICW4_SFNM 0x10 /* Complètement lié ou non */ # define INTGATE 0x0E00 /* utilise pour gerer les interruptions */ # define TRAPGATE 0x0F00 /* utilise pour faire des appels systemes */ # define TASKGATE 0x0500 /* utilise pour commuter des taches */ # define CALLGATE 0x0C00 /* utilise pour appeler du code */ # define LDTDES 0x0200 /* utilise pour pointer une LDT */ # define ENTRY_PRESENT 0b1000000000000000 /* Segment défini (obligatoire) */ # define ENTRY_STORAGE 0b0001000000000000 /* Segment défini (obligatoire) */ # define ENTRY_RING0 0b0000000000000000 /* Segment anneau 0 */ # define ENTRY_RING1 0b0010000000000000 /* Segment anneau 1 */ # define ENTRY_RING2 0b0100000000000000 /* Segment anneau 2 */ # define ENTRY_RING3 0b0110000000000000 /* Segment anneau 3 */ /* 00-11-010-0 : Compteur 0 - LSB puis MSB - generateur taux - binaire */ # define TIMER0 0x40 /* port E/S pour le timer canal 0 */ # define TIMER_MODE 0x43 /* port E/S pour le mode controle du timer */ # define RATE_GENERATOR 0x34 /* générateur de fréquence */ # define SQUARE_WAVE 0x36 /* générateur d'onde carrée */ # define TIMER_FREQ 1193180 /* fréquence pour timer dans un PC ou AT */ # define HZ 100 /* Fréquence d'horloge (ajutste logiciellement sur IBM-PC) */ # define getESP(mem) ({ \ asm volatile ("movl %%esp,%[tomem];":: [tomem] "m" (mem)); \ }) # define getEBP(mem) ({ \ asm volatile ("movl %%ebp,%[tomem];":: [tomem] "m" (mem)); \ }) # define savecpu(dump,caller,oldesp) ({\ getEBP(oldesp);\ dumpcpu();\ getESP(dump);\ caller = (exception_stack *) (oldesp + 1);\ dump->ebp = *oldesp;\ dump->eip = caller->eip;\ dump->cs = caller->cs;\ if (caller->cs==SEL_KERNEL_CODE)\ dump->esp = (u32) oldesp + sizeof(exception_stack);\ else\ {\ dump->esp = (u32) ((exception_stack_user*) caller)->esp;\ dump->ss = (u32) ((exception_stack_user*) caller)->ss;\ }\ }) # define savecpu_noerror(dump,caller,oldesp) ({\ getEBP(oldesp);\ dumpcpu();\ getESP(dump);\ caller = (exception_stack_noerror *) (oldesp + 1);\ dump->ebp = *oldesp;\ dump->eip = caller->eip;\ dump->cs = caller->cs;\ if (caller->cs==SEL_KERNEL_CODE)\ dump->esp = (u32) oldesp + sizeof(exception_stack_noerror);\ else\ {\ dump->esp = (u32) ((exception_stack_noerror_user*) caller)->esp;\ dump->ss = (u32) ((exception_stack_noerror_user*) caller)->ss;\ }\ }) # define createdump(dump) ({ \ push(dump.ss);\ push(dump.esp);\ push(dump.eflags);\ push(dump.cs);\ push(dump.eip);\ push(dump.ds);\ push(dump.es);\ push(dump.fs);\ push(dump.gs);\ push(dump.eax);\ push(dump.ebx);\ push(dump.ecx);\ push(dump.edx);\ push(dump.esi);\ push(dump.edi);\ push(dump.ebp);\ push(dump.cr0);\ push(dump.cr2);\ push(dump.cr3);\ push(dump.cr4);\ push(dump.dr0);\ push(dump.dr1);\ push(dump.dr2);\ push(dump.dr3);\ push(dump.dr6);\ push(dump.dr7);\ u32 eferlow=(u32) dump.efer & 0xFFFF;\ u32 eferhigh=(u32) dump.efer >> 32;\ push(eferlow);\ push(eferhigh);\ }) # define dumpcpu() ({ \ asm("\ pushl %%ss\n \ pushl %%esp\n \ pushf \n \ pushl %%cs\n \ pushl $0x0\n \ pushl %%ds\n \ pushl %%es\n \ pushl %%fs\n \ pushl %%gs\n \ pushl %%eax\n \ pushl %%ebx\n \ pushl %%ecx\n \ pushl %%edx\n \ pushl %%esi\n \ pushl %%edi\n \ pushl %%ebp\n \ mov %%cr0, %%eax \n \ pushl %%eax\n \ mov %%cr2, %%eax \n \ pushl %%eax\n \ mov %%cr3, %%eax \n \ pushl %%eax\n \ mov %%cr4, %%eax \n \ pushl %%eax \n \ mov %%dr0, %%eax \n \ pushl %%eax\n \ mov %%dr1, %%eax \n \ pushl %%eax\n \ mov %%dr2, %%eax \n \ pushl %%eax\n \ mov %%dr3, %%eax \n \ pushl %%eax\n \ mov %%dr6, %%eax \n \ pushl %%eax\n \ mov %%dr7, %%eax \n \ pushl %%eax\n \ mov $0xC0000080, %%ecx \n \ rdmsr \n \ pushl %%edx \n \ pushl %%eax":::);\ }) # define restcpu() ({\ asm("\ popl %%eax \n \ popl %%edx \n \ mov $0xC0000080, %%ecx \n \ wrmsr\n \ popl %%eax\n \ mov %%eax,%%dr7 \n \ popl %%eax \n \ mov %%eax,%%dr6 \n \ popl %%eax \n \ mov %%eax,%%dr3 \n \ popl %%eax \n \ mov %%eax,%%dr2 \n \ popl %%eax \n \ mov %%eax,%%dr1 \n \ popl %%eax \n \ mov %%eax,%%dr0 \n \ popl %%eax \n \ popl %%eax \n \ mov %%eax,%%cr3 \n \ popl %%eax \n \ popl %%eax \n \ popl %%ebp\n \ popl %%edi\n \ popl %%esi\n \ popl %%edx\n \ popl %%ecx\n \ popl %%ebx\n \ popl %%eax\n \ popl %%gs\n \ popl %%fs\n \ popl %%es\n \ popl %%ds\n \"::);\ }) # define restdebugcpu() ({\ asm("\ popl %%eax \n \ popl %%edx \n \ mov $0xC0000080, %%ecx \n \ wrmsr\n \ popl %%eax\n \ popl %%eax \n \ popl %%eax \n \ popl %%eax \n \ popl %%eax \n \ popl %%eax \n \ popl %%eax \n \ popl %%eax \n \ mov %%eax,%%cr3 \n \ popl %%eax \n \ popl %%eax \n \ popl %%ebp\n \ popl %%edi\n \ popl %%esi\n \ popl %%edx\n \ popl %%ecx\n \ popl %%ebx\n \ popl %%eax\n \ popl %%gs\n \ popl %%fs\n \ popl %%es\n \ popl %%ds":::);\ }) /* lors d'un iret en mode user: pushl %%ss\n \ pushl %%esp\n \ lors d'un iret en mode kernel: pushf \n \ pushl $cs\n \ pushl $0x0\ */ /* save pile */ typedef struct regs { u64 efer; u32 dr7; u32 dr6; u32 dr3; u32 dr2; u32 dr1; u32 dr0; u32 cr4; u32 cr3; u32 cr2; u32 cr0; u32 ebp; u32 edi; u32 esi; u32 edx; u32 ecx; u32 ebx; u32 eax; u32 gs; u32 fs; u32 es; u32 ds; u32 eip; u32 cs; u32 eflags; u32 esp; u32 ss; } regs __attribute__ ((packed)); /* exception pile depuis code kernel*/ typedef struct exception_stack { u32 error_code; u32 eip; u32 cs; u32 eflags; } exception_stack __attribute__ ((packed)); /* sans code erreur depuis code kernel*/ typedef struct exception_stack_noerror { u32 eip; u32 cs; u32 eflags; } exception_stack_noerror __attribute__ ((packed)); /* exception pile depuis code user */ typedef struct exception_stack_user { u32 error_code; u32 eip; u32 cs; u32 eflags; u32 esp; u32 ss; } exception_stack_user __attribute__ ((packed)); /* sans code erreu depuis code user */ typedef struct exception_stack_noerror_user { u32 eip; u32 cs; u32 eflags; u32 esp; u32 ss; } exception_stack_noerror_user __attribute__ ((packed)); /* descripteur de segment */ typedef struct idtdes { u16 offset0_15; u16 select; u16 type; u16 offset16_31; } idtdes __attribute__ ((packed)); struct idtr { u16 limite; u32 base; } __attribute__ ((packed)); void initretry(u32 address); void initidt(void); u32 getinitretry(void); void setidt(u32 offset, u16 select, u16 type, u16 index); void makeidtdes(u32 offset, u16 select, u16 type, idtdes * desc); void initpic(void); void enableirq(u8 irq); void disableirq(u8 irq); void cpuerror(const u8 * src, const regs * stack, bool returnto); #endif