初步实现syscall

This commit is contained in:
xiaoyi1212 2024-04-20 02:43:22 +08:00
parent e982d72613
commit 982287d730
13 changed files with 325 additions and 36 deletions

View File

@ -5,10 +5,40 @@ global io_in8, io_in16, io_in32
global io_out8, io_out16, io_out32
global io_load_eflags, io_store_eflags
global load_gdtr, load_idtr
global tss_flush, gdt_flush, switch_to
global tss_flush, gdt_flush, switch_to, copy_page_physical
section .text
[GLOBAL copy_page_physical]
copy_page_physical:
push ebx ; According to __cdecl, we must preserve the contents of EBX.
pushf ; push EFLAGS, so we can pop it and reenable interrupts
; later, if they were enabled anyway.
cli ; Disable interrupts, so we aren't interrupted.
; Load these in BEFORE we disable paging!
mov ebx, [esp+12] ; Source address
mov ecx, [esp+16] ; Destination address
mov edx, cr0 ; Get the control register...
and edx, 0x7fffffff ; and...
mov cr0, edx ; Disable paging.
mov edx, 1024 ; 1024*4bytes = 4096 bytes
.loop:
mov eax, [ebx] ; Get the word at the source address
mov [ecx], eax ; Store it at the dest address
add ebx, 4 ; Source address += sizeof(word)
add ecx, 4 ; Dest address += sizeof(word)
dec edx ; One less word to do
jnz .loop
mov edx, cr0 ; Get the control register again
or edx, 0x80000000 ; and...
mov cr0, edx ; Enable paging.
popf ; Pop EFLAGS back.
pop ebx ; Get the original value of EBX back.
switch_to:
mov eax, [esp+4]

View File

@ -4,7 +4,7 @@
#include "../include/queue.h"
#include "../include/io.h"
static KEY_STATUS *key_status;
KEY_STATUS *key_status;
Queue *key_char_queue;
struct key_listener* head_listener;
@ -122,6 +122,7 @@ void init_keyboard(){
key_char_queue = create_queue();
head_listener = (struct key_listener*) kmalloc(sizeof(struct key_listener));
head_listener->func = default_handle;
head_listener->lid = 0;
register_interrupt_handler(0x21,handle_keyboard_input);
}
@ -142,6 +143,59 @@ int handle_keyboard_input(){
return 0;
}
static void found_listener(int lid,struct key_listener *head,struct key_listener *base,struct key_listener **argv,int first){
struct key_listener *t = base;
if(t == NULL){
argv = NULL;
return;
}
if(t->lid == lid){
*argv = t;
return;
} else{
if(!first)
if(head->lid == t->lid){
argv = NULL;
return;
}
found_listener(lid,head,t->next,argv,0);
}
}
struct key_listener* found_listener_id(int lid){
struct task_struct *argv = NULL;
found_listener(lid,head_listener,head_listener,&argv,1);
if(argv == NULL){
printf("Cannot found key listener id:[%d].\n",lid);
return NULL;
}
return argv;
}
void remove_listener(int lid){
struct key_listener *argv = found_listener_id(lid);
if(argv == NULL){
printf("Cannot found listener id:[%d].\n",lid);
return;
}
if(argv->lid == 0){
printf("[\033driver\036]: Cannot remove default listener.\n");
return;
}
kfree(argv);
struct key_listener *head = head_listener;
struct key_listener *last = NULL;
while (1){
if(head->lid == argv->lid){
last->next = argv->next;
return;
}
last = head;
head = head->next;
}
}
void add_listener(struct key_listener* listener){
if(listener == NULL) return;

View File

@ -36,6 +36,8 @@ void load_idtr(int limit, int addr);
uint16_t inw(uint16_t port);
void copy_page_physical(uint32_t,uint32_t);
extern char read_port(unsigned short port);
static inline void outb(uint16_t port, uint8_t data) {

View File

@ -18,6 +18,7 @@ typedef struct {
}KEY_MAP;
typedef struct key_listener{
int lid;
void (*func)(uint32_t key,int release,char c);
struct key_listener *next;
}kl_t;
@ -25,5 +26,6 @@ typedef struct key_listener{
void init_keyboard();
int handle_keyboard_input();
void add_listener(struct key_listener* listener);
void remove_listener(int lid);
#endif //CRASHPOWEROS_KEYBOARD_H

View File

@ -63,6 +63,8 @@ uint32_t first_frame();
void page_fault(registers_t *regs);
page_directory_t *clone_directory(page_directory_t *src);
void flush_tlb();
void *ksbrk(int incr);

13
include/pcat.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef CRASHPOWEROS_PCAT_H
#define CRASHPOWEROS_PCAT_H
#include "task.h"
#include "fat16.h"
struct pcat_process{
uint8_t is_e;
};
void pcat_launch(struct task_struct *father,struct File *file);
#endif

58
include/syscall.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef CRASHPOWEROS_SYSCALL_H
#define CRASHPOWEROS_SYSCALL_H
#include <stddef.h>
#define SYSCALL_NUM 10
#define DEFN_SYSCALL0(fn, num) \
int syscall_##fn() \
{ \
int a; \
asm volatile("int $0x80" : "=a" (a) : "0" (num)); \
return a; \
}
#define DEFN_SYSCALL1(fn, num, P1) \
int syscall_##fn(P1 p1) \
{ \
int a; \
asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1)); \
return a; \
}
#define DEFN_SYSCALL2(fn, num, P1, P2) \
int syscall_##fn(P1 p1, P2 p2) \
{ \
int a; \
asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2)); \
return a; \
}
#define DEFN_SYSCALL3(fn, num, P1, P2, P3) \
int syscall_##fn(P1 p1, P2 p2, P3 p3) \
{ \
int a; \
asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2), "d"((int)p3)); \
return a; \
}
#define DEFN_SYSCALL4(fn, num, P1, P2, P3, P4) \
int syscall_##fn(P1 p1, P2 p2, P3 p3, P4 p4) \
{ \
int a; \
asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2), "d" ((int)p3), "S" ((int)p4)); \
return a; \
}
#define DEFN_SYSCALL5(fn, num) \
int syscall_##fn(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) \
{ \
int a; \
asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2), "d" ((int)p3), "S" ((int)p4), "D" ((int)p5)); \
return a; \
}
void syscall_install();
#endif

View File

@ -11,6 +11,7 @@
#include "../include/shell.h"
#include "../include/date.h"
#include "../include/acpi.h"
#include "../include/syscall.h"
extern uint32_t end;
extern int status;
@ -60,6 +61,7 @@ void kernel_main(multiboot_t *multiboot) {
init_keyboard();
printf("[\035kernel\036]: Keyboard driver load success!\n");
syscall_install();
print_cpu_id();
io_sti();

View File

@ -110,16 +110,15 @@ void page_fault(registers_t *regs) {
printf("[ERROR]: Page fault |");
if (present) {
printf("Type: present;\n\taddress: %x ", faulting_address);
printf("Type: present;\n\taddress: %x \n", faulting_address);
if (current->pid == 0) {
printf(" ======= Kernel Error ======= ");
printf(" ======= Kernel Error ======= \n");
while (1) io_hlt();
} else {
current->state = TASK_ZOMBIE;
printf("Taskkill process PID:%d Name:%s",current->pid,current->name);
printf("Taskkill process PID:%d Name:%s\n", current->pid, current->name);
}
}
else if (rw) {
} else if (rw) {
printf("Type: read-only;\n\taddress: %x", faulting_address);
if (current->pid == 0) {
printf(" ======= Kernel Error ======= ");
@ -128,8 +127,7 @@ void page_fault(registers_t *regs) {
current->state = TASK_ZOMBIE;
printf("Taskkill process PID:%d Name:%s", current->pid, current->name);
}
}
else if (us) {
} else if (us) {
printf("Type: user-mode;\n\taddres: %x", faulting_address);
if (current->pid == 0) {
printf(" ======= Kernel Error ======= ");
@ -138,8 +136,7 @@ void page_fault(registers_t *regs) {
current->state = TASK_ZOMBIE;
printf("Taskkill process PID:%d Name:%s", current->pid, current->name);
}
}
else if (reserved) {
} else if (reserved) {
printf("Type: reserved;\n\taddress: %x", faulting_address);
if (current->pid == 0) {
printf(" ======= Kernel Error ======= ");
@ -148,19 +145,60 @@ void page_fault(registers_t *regs) {
current->state = TASK_ZOMBIE;
printf("Taskkill process PID:%d Name:%s", current->pid, current->name);
}
}
else if (id) {
printf("Type: decode address;\n\taddress: %x", faulting_address);
} else if (id) {
printf("Type: decode address;\n\taddress: %x\n", faulting_address);
if (current->pid == 0) {
printf(" ======= Kernel Error ======= ");
printf(" ======= Kernel Error ======= \n");
while (1) io_hlt();
} else {
current->state = TASK_ZOMBIE;
printf("Taskkill process PID:%d Name:%s",current->pid,current->name);
printf("Taskkill process PID:%d Name:%s\n", current->pid, current->name);
}
}
}
static page_table_t *clone_table(page_table_t *src, uint32_t *physAddr) {
page_table_t *table = (page_table_t *) kmalloc_ap(sizeof(page_table_t), physAddr);
memset(table, 0, sizeof(page_directory_t));
int i;
for (i = 0; i < 1024; i++) {
if (!src->pages[i].frame)
continue;
alloc_frame(&table->pages[i], 0, 0);
if (src->pages[i].present) table->pages[i].present = 1;
if (src->pages[i].rw) table->pages[i].rw = 1;
if (src->pages[i].user) table->pages[i].user = 1;
if (src->pages[i].accessed)table->pages[i].accessed = 1;
if (src->pages[i].dirty) table->pages[i].dirty = 1;
copy_page_physical(src->pages[i].frame * 0x1000, table->pages[i].frame * 0x1000);
}
return table;
}
page_directory_t *clone_directory(page_directory_t *src) {
uint32_t phys;
page_directory_t *dir = (page_directory_t *) kmalloc_ap(sizeof(page_directory_t), &phys);
memset(dir, 0, sizeof(page_directory_t));
uint32_t offset = (uint32_t) dir->tablesPhysical - (uint32_t) dir;
dir->physicalAddr = phys + offset;
int i;
for (i = 0; i < 1024; i++) {
if (!src->tables[i])
continue;
if (kernel_directory->tables[i] == src->tables[i]) {
dir->tables[i] = src->tables[i];
dir->tablesPhysical[i] = src->tablesPhysical[i];
} else {
uint32_t phys;
dir->tables[i] = clone_table(src->tables[i], &phys);
dir->tablesPhysical[i] = phys | 0x07;
}
}
return dir;
}
void init_page() {
uint32_t mem_end_page = 0xFFFFFFFF; // 4GB Page

29
kernel/syscall.c Normal file
View File

@ -0,0 +1,29 @@
#include "../include/syscall.h"
#include "../include/isr.h"
void syscall_handler(registers_t *regs){
if (regs->eax >= SYSCALL_NUM)
return;
void *location = NULL;//syscalls[regs->eax];
int ret;
asm volatile (" \
push %1; \
push %2; \
push %3; \
push %4; \
push %5; \
call *%6; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
pop %%ebx; \
" : "=a" (ret) : "r" (regs->edi), "r" (regs->esi), "r" (regs->edx), "r" (regs->ecx), "r" (regs->ebx), "r" (location));
regs->eax = ret;
}
void syscall_install(){
register_interrupt_handler(0x80,syscall_handler);
}

View File

@ -95,7 +95,7 @@ struct task_struct* found_task_pid(int pid){
found_task(pid,running_proc_head,running_proc_head,&argv,1);
if(argv == NULL){
printf("Cannot found task Pid:[%d].\n",pid);
return;
return NULL;
}
return argv;
}
@ -167,7 +167,7 @@ void change_task_to(struct task_struct *next) {
struct task_struct *prev = current;
current = next;
//switch_page_directory(current->pgd_dir);
switch_page_directory(current->pgd_dir);
switch_to(&(prev->context), &(current->context));
}
@ -183,7 +183,7 @@ int32_t kernel_thread(int (*fn)(void *), void *arg,char* name) {
new_task->state = TASK_RUNNABLE;
new_task->stack = current;
new_task->pid = now_pid++;
new_task->pgd_dir = (page_directory_t *) kmalloc_a(sizeof(page_directory_t));
new_task->pgd_dir = kernel_directory;
new_task->name = name;

40
sysapp/pcat.c Normal file
View File

@ -0,0 +1,40 @@
#include "../include/pcat.h"
#include "../include/keyboard.h"
#include <stddef.h>
struct task_struct *father_pcat;
struct pcat_process *this_process;
uint32_t pid_pcat;
extern KEY_STATUS *key_status;
void pcat_key_listener(uint32_t key,int release,char c){
}
void start_pcat_thread(){
this_process = (struct pcat_process*) kmalloc(sizeof(struct pcat_process));
struct key_listener *listener = (struct key_listener*) kmalloc(sizeof(struct key_listener));
listener->func = pcat_key_listener;
listener->func = 2;
add_listener(listener);
while (1){
if(key_status->is_ctrl){
if(this_process->is_e){
kfree(this_process);
start_task(father_pcat);
task_kill(get_current());
}
}
}
}
void pcat_launch(struct task_struct *father,struct File *file){
father_pcat = father;
pid_pcat = kernel_thread(start_pcat_thread,NULL,"CPOS-PCAT");
wait_task(father);
while (1){
if(father->state != TASK_SLEEPING) break;
}
}

View File

@ -5,8 +5,7 @@
#include "../include/task.h"
#include "../include/cmos.h"
#include "../include/fat16.h"
#include "../include/timer.h"
#include "../include/io.h"
#include "../include/pcat.h"
extern Queue *key_char_queue;
@ -211,6 +210,23 @@ void cmd_debug(){
printf("ESI: 0x%08x | EDI 0x%08x | EBP 0x%08x | EFLAGS 0x%08x\n",esi,edi,ebp,get_current()->context.eflags);
}
void cmd_pcat(int argc,char **argv){
if (argc == 1) {
return;
}
char name[8] = {0};
char ext[3] = {0};
analyse_fullname(argv[1], name, ext);
int isfind = find_file(name, ext, 0);
struct File* file;
if(isfind){
file = open_file(argv[1]);
} else file = create_file(argv[1]);
pcat_launch(get_current(),file);
}
void setup_shell(){
vga_clear();
printf("%s for x86 [Version %s] \n",OS_NAME, OS_VERSION);
@ -256,6 +272,8 @@ void setup_shell(){
cmd_shutdown();
else if (!strcmp("debug", argv[0]))
cmd_debug();
else if (!strcmp("pcat", argv[0]))
cmd_pcat(argc,argv);
else if (!strcmp("help", argv[0]) || !strcmp("?", argv[0]) || !strcmp("h", argv[0])) {
vga_writestring("-=[\037CrashPowerShell Helper\036]=-\n");
vga_writestring("help ? h \032Print shell help info.\036\n");
@ -271,6 +289,7 @@ void setup_shell(){
vga_writestring("reset \032Reset OS.\036\n");
vga_writestring("shutdown exit \032Shutdown OS.\036\n");
vga_writestring("debug \032Print os debug info.\036\n");
vga_writestring("pcat [filename] \032Launch pcat application.\036\n");
} else printf("\033[Shell]: Unknown command '%s'.\036\n", argv[0]);
}
}