feat: ajout de wrappers pour SYSENTER et pour toutes les exceptions. Génération automatique des API par métadonnées dans le source.

This commit is contained in:
Nicolas Hordé 2018-12-16 01:50:03 +01:00
parent 3c3f0bb88e
commit 0af99c069b
12 changed files with 337 additions and 275 deletions

View File

@ -2,7 +2,7 @@
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
#include "types.h"
__attribute__ ((noreturn)) void exception_handler(regs *dump);
__attribute__((interrupt)) void interruption(exception_stack_noerror *caller);
void exception0();
void exception1();

View File

@ -48,15 +48,10 @@
/* 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 setESP(mem) ({ \
asm volatile ("movl %[frommem],%%esp;":[frommem] "=m" (mem):); \
})
# define getEBP(mem) ({ \
asm volatile ("movl %%ebp,%[tomem];":: [tomem] "m" (mem)); \
})
# define savecpu(dump,caller,oldesp) ({\
getEBP(oldesp);\
dumpcpu();\
@ -168,24 +163,18 @@
pushl %%eax":::);\
})
# define restcpu() ({\
# define restcpu_kernel() ({\
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 \
@ -196,15 +185,26 @@
popl %%esi\n \
popl %%edx\n \
popl %%ecx\n \
mov 36(%%esp),%%eax\n \
mov 32(%%esp),%%ebx\n \
mov %%ebx,-4(%%eax)\n \
mov 28(%%esp),%%ebx\n \
mov %%ebx,-8(%%eax)\n \
mov 24(%%esp),%%ebx\n \
mov %%ebx,-12(%%eax)\n \
popl %%ebx\n \
popl %%eax\n \
popl %%gs\n \
popl %%fs\n \
popl %%es\n \
popl %%ds\n \"::);\
popl %%ds\n \
add $12,%%esp\n \
popl %%esp\n \
sub $12,%%esp\n \
iret ":::);\
})
# define restdebugcpu() ({\
# define restcpu_user() ({\
asm("\
popl %%eax \n \
popl %%edx \n \
@ -234,6 +234,7 @@
popl %%ds":::);\
})
/*
lors d'un iret en mode user:
pushl %%ss\n \

View File

@ -47,4 +47,5 @@
/* Vers 6 arguments maximum */
void initsyscall(void);
__attribute__ ((noreturn)) void sysenter_handler(void);
__attribute__ ((noreturn)) void sysenter_handler(regs *dump);

View File

@ -22,21 +22,72 @@ __attribute__((interrupt)) void interruption(exception_stack_noerror *caller)
/******************************************************************************/
/* Les expections */
void exception0()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
cpuerror("#DE Divide error", dump, false);
}
static u8 ex14_errors1[] =
"Supervisory process tried to read a non-present page entry";
static u8 ex14_errors2[] =
"Supervisory process tried to read a page and caused a protection fault";
static u8 ex14_errors3[] =
"Supervisory process tried to write to a non-present page entry";
static u8 ex14_errors4[] =
"Supervisory process tried to write a page and caused a protection fault";
static u8 ex14_errors5[] =
"User process tried to read a non-present page entry";
static u8 ex14_errors6[] =
"User process tried to read a page and caused a protection fault";
static u8 ex14_errors7[] =
"User process tried to write to a non-present page entry";
static u8 ex14_errors8[] =
"User process tried to write a page and caused a protection fault";
static u8 *ex14_errors[] =
{ &ex14_errors1, &ex14_errors2, &ex14_errors3, &ex14_errors4,
&ex14_errors5, &ex14_errors6, &ex14_errors7, &ex14_errors8
};
void exception1()
__attribute__ ((noreturn)) void exception_handler(regs *dump)
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
u32 exception=dump->eip;
exception_stack_noerror *caller = (exception_stack_noerror*) ((u32*)dump->esp+1);
bool noerror,user;
if (caller->cs==SEL_KERNEL_CODE || caller->cs==SEL_USER_CODE)
{
noerror=true;
dump->eip = caller->eip;
dump->cs = caller->cs;
dump->eflags = caller->eflags;
if (dump->cs==SEL_KERNEL_CODE)
{
dump->esp = (u32) caller + sizeof(exception_stack_noerror);
user=false;
}
else
{
dump->esp = (u32) ((exception_stack_noerror_user*) caller)->esp;
dump->ss = (u32) ((exception_stack_noerror_user*) caller)->ss;
user=true;
}
}
else
{
noerror=false;
dump->eip = ((exception_stack*)caller)->eip;
dump->cs = ((exception_stack*)caller)->cs;
if (dump->cs==SEL_KERNEL_CODE)
{
dump->esp = (u32) caller + sizeof(exception_stack);
user=false;
}
else
{
dump->esp = (u32) ((exception_stack_user*) caller)->esp;
dump->ss = (u32) ((exception_stack_user*) caller)->ss;
user=true;
}
}
switch (exception)
{
case 0:
cpuerror("#DE Divide error", dump, false);
case 1:
changevc(6);
clearscreen();
show_lightcpu(dump);
@ -59,158 +110,33 @@ void exception1()
initselectors(getinitretry());
}
changevc(0);
restdebugcpu();
iret();
}
void exception2()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
goto endofexception;
case 2:
cpuerror("NMI Non-maskable hardware interrupt", dump, false);
}
void exception3()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 3:
cpuerror("#BP INT3 instruction", dump, true);
iret();
}
void exception4()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 4:
cpuerror("#OF INTO instruction detected overflow", dump, false);
}
void exception5()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 5:
cpuerror("#BR BOUND instruction detected overrange", dump, false);
}
void exception6()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 6:
cpuerror("#UD Invalid instruction opcode", dump, false);
}
void exception7()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 7:
cpuerror("#NM No coprocessor", dump, false);
}
void exception8()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 8:
cpuerror("#DF Double fault", dump, false);
}
void exception9()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 9:
cpuerror("Coprocessor segment overrun", dump, false);
}
void exception10()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 10:
cpuerror("#TS Invalid task state segment (TSS)", dump, false);
}
void exception11()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 11:
cpuerror("#NP Segment not present", dump, false);
}
void exception12()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 12:
cpuerror("#SS Stack fault", dump, false);
}
void exception13()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu(dump, caller, oldesp);
case 13:
cpuerror("#GP General protection fault (GPF)", dump, false);
}
static u8 ex14_errors1[] =
"Supervisory process tried to read a non-present page entry";
static u8 ex14_errors2[] =
"Supervisory process tried to read a page and caused a protection fault";
static u8 ex14_errors3[] =
"Supervisory process tried to write to a non-present page entry";
static u8 ex14_errors4[] =
"Supervisory process tried to write a page and caused a protection fault";
static u8 ex14_errors5[] =
"User process tried to read a non-present page entry";
static u8 ex14_errors6[] =
"User process tried to read a page and caused a protection fault";
static u8 ex14_errors7[] =
"User process tried to write to a non-present page entry";
static u8 ex14_errors8[] =
"User process tried to write a page and caused a protection fault";
static u8 *ex14_errors[] =
{ &ex14_errors1, &ex14_errors2, &ex14_errors3, &ex14_errors4,
&ex14_errors5, &ex14_errors6, &ex14_errors7, &ex14_errors8
};
void exception14()
{
regs *dump;
exception_stack *caller;
u32 *oldesp;
getEBP(oldesp);
dumpcpu();
getESP(dump);
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;
}
case 14:
if (dump->cr2 >= USER_CODE && dump->cr2 < USER_STACK)
{
virtual_range_new(getcurrentprocess()->pdd,
@ -220,48 +146,32 @@ void exception14()
else
{
printf("Page fault - %s at adress %Y cs:eip - %Y:%Y\r\n",
ex14_errors[caller->error_code & 0xF], dump->cr2,
ex14_errors[((exception_stack*) caller)->error_code & 0xF], dump->cr2,
dump->cs, dump->eip);
cpuerror("#PGF Page fault", dump, false);
}
restdebugcpu();
iret();
}
void exception15()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
goto endofexception;
case 15:
cpuerror("(reserved)", dump, false);
}
void exception16()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 16:
cpuerror("#MF Coprocessor error", dump, false);
}
void exception17()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 17:
cpuerror("#AC Alignment check", dump, false);
}
void exception18()
{
regs *dump;
exception_stack_noerror *caller;
u32 *oldesp;
savecpu_noerror(dump, caller, oldesp);
case 18:
cpuerror("#MC Machine check", dump, false);
}
endofexception:
if (dump->cs==SEL_KERNEL_CODE)
{
setESP(dump);
restcpu_kernel();
}
else
{
setESP(dump);
restcpu_user();
iret();
}
}
/******************************************************************************/

120
lib/handlers_asm.S Normal file
View File

@ -0,0 +1,120 @@
/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
.section .text
.macro exception num
.global wrapper_exception\num
wrapper_exception\num:
pushl %ss
pushl %esp
pushf
pushl %cs
pushl $\num
jmp dumpcpu
.endm
exception 0
exception 1
exception 2
exception 3
exception 4
exception 5
exception 6
exception 7
exception 8
exception 9
exception 10
exception 11
exception 12
exception 13
exception 14
exception 15
exception 16
exception 17
exception 18
.global wrapper_sysenter
wrapper_sysenter:
pushl %ss
pushl %esp
pushf
pushl %cs
pushl $0x00
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushl %eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
pushl %ebp
mov %cr0, %eax
pushl %eax
mov %cr2, %eax
pushl %eax
mov %cr3, %eax
pushl %eax
mov %cr4, %eax
pushl %eax
mov %dr0, %eax
pushl %eax
mov %dr1, %eax
pushl %eax
mov %dr2, %eax
pushl %eax
mov %dr3, %eax
pushl %eax
mov %dr6, %eax
pushl %eax
mov %dr7, %eax
pushl %eax
mov $0xC0000080, %ecx
rdmsr
pushl %edx
pushl %eax
pushl %esp
call sysenter_handler
dumpcpu:
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushl %eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
pushl %ebp
mov %cr0, %eax
pushl %eax
mov %cr2, %eax
pushl %eax
mov %cr3, %eax
pushl %eax
mov %cr4, %eax
pushl %eax
mov %dr0, %eax
pushl %eax
mov %dr1, %eax
pushl %eax
mov %dr2, %eax
pushl %eax
mov %dr3, %eax
pushl %eax
mov %dr6, %eax
pushl %eax
mov %dr7, %eax
pushl %eax
mov $0xC0000080, %ecx
rdmsr
pushl %edx
pushl %eax
pushl %esp
call exception_handler

View File

@ -22,6 +22,25 @@ static idtdes idt[IDT_SIZE];
static u32 retry_address;
extern wrapper_exception0;
extern wrapper_exception1;
extern wrapper_exception2;
extern wrapper_exception3;
extern wrapper_exception4;
extern wrapper_exception5;
extern wrapper_exception6;
extern wrapper_exception7;
extern wrapper_exception8;
extern wrapper_exception9;
extern wrapper_exception10;
extern wrapper_exception11;
extern wrapper_exception12;
extern wrapper_exception13;
extern wrapper_exception14;
extern wrapper_exception15;
extern wrapper_exception16;
extern wrapper_exception17;
extern wrapper_exception18;
/******************************************************************************/
/* Initialise la reprise après erreur */
@ -149,43 +168,43 @@ void putidt(u32 offset, u16 select, u16 type, u16 index)
void initidt(void)
{
u16 i;
putidt((u32) exception0, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception0, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 0);
putidt((u32) exception1, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception1, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 1);
putidt((u32) exception2, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception2, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 2);
putidt((u32) exception3, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception3, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 3);
putidt((u32) exception4, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception4, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 4);
putidt((u32) exception5, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception5, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 5);
putidt((u32) exception6, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception6, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 6);
putidt((u32) exception7, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception7, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 7);
putidt((u32) exception8, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception8, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 8);
putidt((u32) exception9, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception9, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 9);
putidt((u32) exception10, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception10, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 10);
putidt((u32) exception11, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception11, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 11);
putidt((u32) exception12, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception12, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 12);
putidt((u32) exception13, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception13, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 13);
putidt((u32) exception14, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception14, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 14);
putidt((u32) exception15, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception15, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 15);
putidt((u32) exception16, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception16, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 16);
putidt((u32) exception17, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception17, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 17);
putidt((u32) exception18, SEL_KERNEL_CODE,
putidt((u32) &wrapper_exception18, SEL_KERNEL_CODE,
ENTRY_PRESENT | ENTRY_RING0 | INTGATE, 18);
for (i = 19; i < 32; i++)
{

View File

@ -1,7 +1,10 @@
CC=gcc -O0 -g -nostdinc -ffreestanding -fno-builtin -Wall -w -m32 -F elf_i386 -fno-pie -no-pie -I ../include -c
ASM=gcc -nostdinc -ffreestanding -fno-builtin -m32 -c -fno-pie -no-pie
LINK=ld -m elf_i386 -r -o
SRCS= $(wildcard *.c)
OBJS= $(SRCS:.c=.o)
SRCASM= $(wildcard *.S)
OBJASM= $(SRCASM:.S=.o)
CONVERT=dos2unix
INDENT=indent -nhnl -l75 -ppi3 -ts8 -bls -nbc -di8 -nbad -nbap -nsob -i8 -bl -bli0 -ncdw -nce -cli8 -cbi0 -npcs -cs -saf -sai -saw -nprs -lp -npsl
REMOVE=rm -f
@ -12,8 +15,11 @@ all: libs.o
togit: clean indent
libs.o:$(OBJS)
$(LINK) libs.o $(OBJS)
libs.o:$(OBJS) $(OBJASM)
$(LINK) libs.o $(OBJS) $(OBJASM)
.o: .S
$(ASM) $^
handlers.o:handlers.c
$(CC) -mgeneral-regs-only $^

View File

@ -235,7 +235,10 @@ void task_switch(u32 pid, bool fromkernelmode)
setTSS(0x0, 0x0);
current->dump.eflags = (current->dump.eflags | 0x200) & 0xFFFFBFFF;
createdump(current->dump);
restdebugcpu();
if (current->dump.cs==SEL_KERNEL_CODE)
restcpu_kernel();
else
restcpu_user();
iret();
}

View File

@ -17,6 +17,8 @@
* %esi Arg2
* %edi Arg3*/
extern wrapper_sysenter;
/*******************************************************************************/
/* Initialise les appels système par SYSENTER/SYSEXIT */
@ -24,7 +26,8 @@ void initsyscall(void)
{
wrmsr(0x174, SEL_KERNEL_CODE, 0x0);
wrmsr(0x175, 0x60000, 0x0);
wrmsr(0x176, &sysenter_handler, 0x0);
wrmsr(0x176, &wrapper_sysenter, 0x0);
return;
}
/*******************************************************************************/
@ -54,15 +57,8 @@ u32 testapi(u32 arg1, u32 arg2, u32 arg3, regs* dump)
/*******************************************************************************/
/* Entrée pour les appels système SYSENTER */
__attribute__ ((noreturn)) void sysenter_handler(void)
__attribute__ ((noreturn)) void sysenter_handler(regs *dump)
{
cli();
regs *dump;
dumpcpu();
getESP(dump);
dump->cs=SEL_USER_CODE;
dump->eip=dump->edx;
sti();
switch (dump->eax)
{
@ -86,7 +82,10 @@ __attribute__ ((noreturn)) void sysenter_handler(void)
printf("Appel syscall vers fonction inexistante en %Y:%Y", dump->cs, dump->eip);
break;
}
restdebugcpu();
//dump->eflags &= ~(1 << 6);
dump->eflags |= (1 << 6);
setESP(dump);
restcpu_user();
sysexit();
}

View File

@ -9,6 +9,11 @@ bits64: ARCH=bits64
bits64: lib/libs.o system/system.sys
sync
syscall: clean remakeapi all
remakeapi:
python makesyscall.py
programs: programs/test lib/TEST/test.c
lib/TEST/test.c:

View File

@ -8,8 +8,8 @@
void main(void)
{
//u32 result = testapi(0x1234,0x88888888,0x2505);
u32 result = testapi(0x1234,0x88888888,0x2505);
print("ceci est un test d'appel");
waitkey();
//exit(result);
exit(result);
}

View File

@ -17,6 +17,8 @@
* %esi Arg2
* %edi Arg3*/
extern wrapper_sysenter;
/*******************************************************************************/
/* Initialise les appels système par SYSENTER/SYSEXIT */
@ -24,7 +26,7 @@ void initsyscall(void)
{
wrmsr(0x174, SEL_KERNEL_CODE, 0x0);
wrmsr(0x175, 0x60000, 0x0);
wrmsr(0x176, &sysenter_handler, 0x0);
wrmsr(0x176, &wrapper_sysenter, 0x0);
return;
}
@ -55,15 +57,8 @@ u32 testapi(u32 arg1, u32 arg2, u32 arg3, regs* dump)
/*******************************************************************************/
/* Entrée pour les appels système SYSENTER */
__attribute__ ((noreturn)) void sysenter_handler(void)
__attribute__ ((noreturn)) void sysenter_handler(regs *dump)
{
cli();
regs *dump;
dumpcpu();
getESP(dump);
dump->cs=SEL_USER_CODE;
dump->eip=dump->edx;
sti();
switch (dump->eax)
{
@ -72,7 +67,10 @@ __attribute__ ((noreturn)) void sysenter_handler(void)
printf("Appel syscall vers fonction inexistante en %Y:%Y", dump->cs, dump->eip);
break;
}
restdebugcpu();
//dump->eflags &= ~(1 << 6);
dump->eflags |= (1 << 6);
setESP(dump);
restcpu_user();
sysexit();
}