mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 19:36:47 +00:00
🆕 syscall模块,实现了第一个系统调用函数sys_printf
This commit is contained in:
parent
7238e3c13a
commit
d3a5048f66
@ -56,7 +56,7 @@ bximage
|
||||
|
||||
- [ ] IPC进程间通信
|
||||
|
||||
- [ ] 第一个系统调用函数
|
||||
- [x] 第一个系统调用函数
|
||||
|
||||
- [ ] 在物理平台上启动DragonOS
|
||||
|
||||
|
@ -56,7 +56,7 @@ bximage
|
||||
|
||||
- [ ] IPC
|
||||
|
||||
- [ ] First system call function
|
||||
- [x] First system call function
|
||||
|
||||
- [ ] Start dragonos on the physical platform
|
||||
|
||||
|
@ -10,8 +10,8 @@ all: kernel
|
||||
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary kernel ../bin/kernel/kernel.bin
|
||||
|
||||
|
||||
kernel: head.o entry.o main.o printk.o trap.o mm.o irq.o 8259A.o process.o
|
||||
ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o exception/8259A.o mm/mm.o process/process.o -T link.lds
|
||||
kernel: head.o entry.o main.o printk.o trap.o mm.o irq.o 8259A.o process.o syscall.o
|
||||
ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o exception/8259A.o mm/mm.o process/process.o syscall/syscall.o -T link.lds
|
||||
|
||||
head.o: head.S
|
||||
gcc -E head.S > head.s # 预处理
|
||||
@ -46,6 +46,8 @@ mm.o: mm/mm.c
|
||||
|
||||
process.o: process/process.c
|
||||
gcc -mcmodel=large -fno-builtin -m64 -c process/process.c -o process/process.o
|
||||
syscall.o: syscall/syscall.c
|
||||
gcc -mcmodel=large -fno-builtin -m64 -c syscall/syscall.c -o syscall/syscall.o
|
||||
|
||||
clean:
|
||||
rm -rf $(GARBAGE)
|
@ -99,6 +99,46 @@ Err_Code:
|
||||
|
||||
jmp ret_from_exception
|
||||
|
||||
// 系统调用入口
|
||||
// 保存寄存器
|
||||
ENTRY(system_call)
|
||||
// 由于sysenter指令会禁用中断,因此要在这里手动开启中断
|
||||
sti;
|
||||
|
||||
subq $0x38, %rsp
|
||||
|
||||
cld;
|
||||
|
||||
pushq %rax
|
||||
movq %es, %rax
|
||||
pushq %rax
|
||||
movq %ds, %rax
|
||||
pushq %rax
|
||||
pushq %rbp
|
||||
pushq %rdi
|
||||
pushq %rsi
|
||||
pushq %rdx
|
||||
pushq %rcx
|
||||
pushq %rbx
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
|
||||
movq $0x10, %rdx
|
||||
movq %rdx, %ds
|
||||
movq %rdx, %es
|
||||
// 将rsp作为参数传递给system_call_function
|
||||
movq %rsp, %rdi
|
||||
|
||||
callq system_call_function
|
||||
|
||||
|
||||
|
||||
// 从系统调用中返回
|
||||
ENTRY(ret_from_system_call)
|
||||
movq %rax, 0x80(%rsp) // 将当前rax的值先存到栈中rax的位置
|
||||
|
@ -212,7 +212,21 @@ void do_general_protection(struct pt_regs * regs, unsigned long error_code)
|
||||
printk("[ ");
|
||||
printk_color(RED, BLACK, "ERROR");
|
||||
printk(" ] do_general_protection(13),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, regs->rsp, regs->rip);
|
||||
return;
|
||||
if(error_code & 0x01)
|
||||
printk_color(RED,BLACK,"The exception occurred during delivery of an event external to the program,such as an interrupt or an earlier exception.\n");
|
||||
|
||||
if(error_code & 0x02)
|
||||
printk_color(RED,BLACK,"Refers to a gate descriptor in the IDT;\n");
|
||||
else
|
||||
printk_color(RED,BLACK,"Refers to a descriptor in the GDT or the current LDT;\n");
|
||||
|
||||
if((error_code & 0x02) == 0)
|
||||
if(error_code & 0x04)
|
||||
printk_color(RED,BLACK,"Refers to a segment or gate descriptor in the LDT;\n");
|
||||
else
|
||||
printk_color(RED,BLACK,"Refers to a descriptor in the current GDT;\n");
|
||||
|
||||
printk_color(RED,BLACK,"Segment Selector Index:%#010x\n",error_code & 0xfff8);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "exception/irq.h"
|
||||
#include "mm/mm.h"
|
||||
#include "process/process.h"
|
||||
#include "syscall/syscall.h"
|
||||
|
||||
unsigned int *FR_address = (unsigned int *)0xffff800000a00000; //帧缓存区的地址
|
||||
// char fxsave_region[512] __attribute__((aligned(16)));
|
||||
@ -84,6 +85,9 @@ void system_initialize()
|
||||
// 初始化中断模块
|
||||
init_irq();
|
||||
|
||||
// 先初始化系统调用模块
|
||||
syscall_init();
|
||||
// 再初始化进程模块。顺序不能调转
|
||||
process_init();
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "../exception/gate.h"
|
||||
#include "../common/printk.h"
|
||||
#include "../common/kprint.h"
|
||||
#include "../syscall/syscall.h"
|
||||
#include "../syscall/syscall_num.h"
|
||||
|
||||
/**
|
||||
* @brief 切换进程
|
||||
@ -28,6 +30,7 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
|
||||
__asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 这是一个用户态的程序
|
||||
*
|
||||
@ -35,6 +38,12 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
|
||||
void user_level_function()
|
||||
{
|
||||
kinfo("Program (user_level_function) is runing...");
|
||||
kinfo("Try to enter syscall id 15...");
|
||||
enter_syscall(15,0,0,0,0,0,0,0,0);
|
||||
|
||||
enter_syscall(SYS_PRINTF, (ul)"test_sys_printf\n", 0,0,0,0,0,0,0);
|
||||
kinfo("Return from syscall id 15...");
|
||||
|
||||
|
||||
while(1);
|
||||
}
|
||||
@ -169,6 +178,10 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne
|
||||
return do_fork(®s, flags, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化进程模块
|
||||
* ☆前置条件:已完成系统调用模块的初始化
|
||||
*/
|
||||
void process_init()
|
||||
{
|
||||
|
||||
@ -188,8 +201,7 @@ void process_init()
|
||||
|
||||
initial_mm.stack_start = _stack_start;
|
||||
|
||||
// 向MSR寄存器组中的 IA32_SYSENTER_CS寄存器写入内核的代码段的地址
|
||||
wrmsr(0x174, KERNEL_CS);
|
||||
|
||||
|
||||
// 初始化进程和tss
|
||||
set_TSS64(initial_thread.rbp, initial_tss[0].rsp1, initial_tss[0].rsp2, initial_tss[0].ist1, initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5, initial_tss[0].ist6, initial_tss[0].ist7);
|
||||
|
@ -13,11 +13,12 @@
|
||||
#include "../common/cpu.h"
|
||||
#include "../common/glib.h"
|
||||
#include "../mm/mm.h"
|
||||
#include "../syscall/syscall.h"
|
||||
#include "ptrace.h"
|
||||
|
||||
extern unsigned long _stack_start; // 导出内核层栈基地址(定义在head.S)
|
||||
extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S)
|
||||
extern void ret_from_system_call(void); // 导出从中断返回的函数(定义在entry.S)
|
||||
|
||||
|
||||
// 进程的内核栈大小 32K
|
||||
#define STACK_SIZE 32768
|
||||
|
72
kernel/syscall/syscall.c
Normal file
72
kernel/syscall/syscall.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include "syscall.h"
|
||||
#include "../process/process.h"
|
||||
|
||||
// 导出系统调用入口函数,定义在entry.S中
|
||||
extern void system_call(void);
|
||||
|
||||
/**
|
||||
* @brief 系统调用函数,从entry.S中跳转到这里
|
||||
*
|
||||
* @param regs 3特权级下的寄存器值,rax存储系统调用号
|
||||
* @return ul 对应的系统调用函数的地址
|
||||
*/
|
||||
ul system_call_function(struct pt_regs *regs)
|
||||
{
|
||||
return system_call_table[regs->rax](regs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化系统调用模块
|
||||
*
|
||||
*/
|
||||
void syscall_init()
|
||||
{
|
||||
// 向MSR寄存器组中的 IA32_SYSENTER_CS寄存器写入内核的代码段的地址
|
||||
wrmsr(0x174, KERNEL_CS);
|
||||
// 向MSR寄存器组中的 IA32_SYSENTER_ESP寄存器写入内核进程的rbp(在syscall入口中会将rsp减去相应的数值)
|
||||
wrmsr(0x175, current_pcb->thread->rbp);
|
||||
|
||||
// 向MSR寄存器组中的 IA32_SYSENTER_EIP寄存器写入系统调用入口的地址。
|
||||
wrmsr(0x176, (ul)system_call);
|
||||
}
|
||||
|
||||
long enter_syscall(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg4, ul arg5, ul arg6, ul arg7)
|
||||
{
|
||||
long err_code;
|
||||
__asm__ __volatile__("leaq sysexit_return_address(%%rip), %%rdx \n\t"
|
||||
"movq %%rsp, %%rcx \n\t"
|
||||
"movq %2, %%r8 \n\t"
|
||||
"movq %3, %%r9 \n\t"
|
||||
"movq %4, %%r10 \n\t"
|
||||
"movq %5, %%r11 \n\t"
|
||||
"movq %6, %%r12 \n\t"
|
||||
"movq %7, %%r13 \n\t"
|
||||
"movq %8, %%r14 \n\t"
|
||||
"movq %9, %%r15 \n\t"
|
||||
"sysenter \n\t"
|
||||
"sysexit_return_address: \n\t"
|
||||
: "=a"(err_code)
|
||||
: "0"(syscall_id), "m"(arg0), "m"(arg1), "m"(arg2), "m"(arg3), "m"(arg4), "m"(arg5), "m"(arg6), "m"(arg7)
|
||||
: "memory", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15");
|
||||
return err_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 打印字符串的系统调用
|
||||
*
|
||||
* 当arg1和arg2均为0时,打印黑底白字,否则按照指定的前景色和背景色来打印
|
||||
*
|
||||
* @param regs 寄存器
|
||||
* @param arg0 要打印的字符串
|
||||
* @param arg1 前景色
|
||||
* @param arg2 背景色
|
||||
* @return ul 返回值
|
||||
*/
|
||||
ul sys_printf(struct pt_regs *regs)
|
||||
{
|
||||
if(regs->r9 == 0 &®s->r10 == 0)
|
||||
printk((char*)regs->r8);
|
||||
else printk_color(regs->r9, regs->r10, (char*)regs->r8);
|
||||
|
||||
return 0;
|
||||
}
|
62
kernel/syscall/syscall.h
Normal file
62
kernel/syscall/syscall.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "../common/glib.h"
|
||||
#include "../common/kprint.h"
|
||||
#include "../process/ptrace.h"
|
||||
|
||||
// 定义最大系统调用数量
|
||||
#define MAX_SYSTEM_CALL_NUM 128
|
||||
|
||||
#define ESYSCALL_NOT_EXISTS 1
|
||||
|
||||
|
||||
|
||||
typedef unsigned long (*system_call_t)(struct pt_regs *regs);
|
||||
|
||||
extern void ret_from_system_call(void); // 导出从系统调用返回的函数(定义在entry.S)
|
||||
|
||||
/**
|
||||
* @brief 初始化系统调用模块
|
||||
*
|
||||
*/
|
||||
void syscall_init();
|
||||
|
||||
/**
|
||||
* @brief 用户态系统调用入口函数
|
||||
* 从用户态进入系统调用
|
||||
* @param syscall_id 系统调用id
|
||||
* @return long 错误码
|
||||
*/
|
||||
long enter_syscall(ul syscall_id,ul arg0, ul arg1, ul arg2, ul arg3, ul arg4, ul arg5, ul arg6, ul arg7);
|
||||
|
||||
/**
|
||||
* @brief 系统调用不存在时的处理函数
|
||||
*
|
||||
* @param regs 进程3特权级下的寄存器
|
||||
* @return ul
|
||||
*/
|
||||
ul system_call_not_exists(struct pt_regs *regs)
|
||||
{
|
||||
kerror("System call [ ID #%d ] not exists.", regs->rax);
|
||||
return ESYSCALL_NOT_EXISTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 打印字符串的系统调用
|
||||
*
|
||||
* 当arg1和arg2均为0时,打印黑底白字,否则按照指定的前景色和背景色来打印
|
||||
*
|
||||
* @param regs 寄存器
|
||||
* @param arg0 要打印的字符串
|
||||
* @param arg1 前景色
|
||||
* @param arg2 背景色
|
||||
* @return ul 返回值
|
||||
*/
|
||||
ul sys_printf(struct pt_regs *regs);
|
||||
|
||||
system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] =
|
||||
{
|
||||
[0] = system_call_not_exists,
|
||||
[1] = sys_printf,
|
||||
[2 ... MAX_SYSTEM_CALL_NUM - 1] = system_call_not_exists
|
||||
};
|
4
kernel/syscall/syscall_num.h
Normal file
4
kernel/syscall/syscall_num.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#define SYS_NOT_EXISTS 0
|
||||
#define SYS_PRINTF 1
|
Loading…
x
Reference in New Issue
Block a user