mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 15:26:47 +00:00
🆕 do_execve函数,跳转至应用层
This commit is contained in:
parent
781a105d2f
commit
0757e7a3cd
10
README.md
10
README.md
@ -1,12 +1,14 @@
|
||||
# DragonOS
|
||||
|
||||
**Languages** 中文|[English](README_EN.md)
|
||||
|
||||
|
||||
|
||||
这是一个运行于x86_64平台的64位操作系统。目前正在开发之中!
|
||||
|
||||
## 开发环境
|
||||
|
||||
GCC==8.0
|
||||
GCC>=8.0
|
||||
|
||||
bochs==2.7
|
||||
|
||||
@ -48,7 +50,7 @@ bximage
|
||||
|
||||
- [ ] 图形驱动
|
||||
|
||||
- [ ] 第一个进程
|
||||
- [x] 第一个进程
|
||||
|
||||
- [ ] 进程管理
|
||||
|
||||
@ -101,7 +103,3 @@ fslongjin
|
||||
## 赞赏者列表
|
||||
|
||||
暂无
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -90,22 +90,6 @@ static inline void list_append(struct List *entry, struct List *node)
|
||||
list_add(tail, node);
|
||||
}
|
||||
|
||||
void list_add_to_behind(struct List * entry,struct List * new) ////add to entry behind
|
||||
{
|
||||
new->next = entry->next;
|
||||
new->prev = entry;
|
||||
new->next->prev = new;
|
||||
entry->next = new;
|
||||
}
|
||||
|
||||
void list_add_to_before(struct List * entry,struct List * new) ////add to entry behind
|
||||
{
|
||||
new->next = entry;
|
||||
entry->prev->next = new;
|
||||
new->prev = entry->prev;
|
||||
entry->prev = new;
|
||||
}
|
||||
|
||||
static inline void list_del(struct List *entry)
|
||||
{
|
||||
/**
|
||||
@ -274,7 +258,6 @@ void io_out32(unsigned short port, unsigned int value)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 读取rsp寄存器的值(存储了页目录的基地址)
|
||||
*
|
||||
@ -343,3 +326,32 @@ unsigned long *get_rbx()
|
||||
: "=r"(tmp)::"memory");
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// ========= MSR寄存器组操作 =============
|
||||
/**
|
||||
* @brief 向msr寄存器组的address处的寄存器写入值value
|
||||
*
|
||||
* @param address 地址
|
||||
* @param value 要写入的值
|
||||
*/
|
||||
void wrmsr(ul address, ul value)
|
||||
{
|
||||
__asm__ __volatile__("wrmsr \n\t" ::"d"(value >> 32), "a"(value & 0xffffffff), "c"(address)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从msr寄存器组的address地址处读取值
|
||||
*
|
||||
* @param address 地址
|
||||
* @return ul address处的寄存器的值
|
||||
*/
|
||||
ul rdmsr(ul address)
|
||||
{
|
||||
unsigned int tmp0, tmp1;
|
||||
__asm__ __volatile__("rdmsr \n\t"
|
||||
: "=d"(tmp0), "=a"(tmp1)
|
||||
: "c"(address)
|
||||
: "memory");
|
||||
return ((ul)tmp0 << 32) | tmp1;
|
||||
}
|
||||
|
@ -99,6 +99,38 @@ Err_Code:
|
||||
|
||||
jmp ret_from_exception
|
||||
|
||||
// 从系统调用中返回
|
||||
ENTRY(ret_from_system_call)
|
||||
movq %rax, 0x80(%rsp) // 将当前rax的值先存到栈中rax的位置
|
||||
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rbx
|
||||
popq %rcx
|
||||
popq %rdx
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
|
||||
popq %rax // 不允许直接pop到ds
|
||||
movq %rax, %ds
|
||||
|
||||
popq %rax
|
||||
movq %rax, %es
|
||||
|
||||
popq %rax
|
||||
|
||||
addq $0x38, %rsp
|
||||
|
||||
.byte 0x48
|
||||
sysexit
|
||||
|
||||
|
||||
// 0 #DE 除法错误
|
||||
ENTRY(divide_error)
|
||||
|
@ -111,12 +111,12 @@ SetUp_TSS64:
|
||||
addq $103, %rax // 设置段长度
|
||||
|
||||
leaq GDT_Table(%rip), %rdi
|
||||
movq %rax, 64(%rdi) // 把低八B存储到GDT第8项
|
||||
movq %rax, 80(%rdi) // 把低八B存储到GDT第10项
|
||||
shrq $32, %rdx
|
||||
movq %rdx, 72(%rdi) // 高8B存到GDT低9项
|
||||
movq %rdx, 88(%rdi) // 高8B存到GDT第11项
|
||||
|
||||
// 装载任务状态段寄存器(已改为在main.c中使用load_TR宏进行装载)
|
||||
// mov $0x40, %ax // 设置起始地址为64
|
||||
// mov $0x50, %ax // 设置起始地址为80
|
||||
// ltr %ax
|
||||
|
||||
// 切换到内核主程序
|
||||
@ -152,7 +152,7 @@ ENTRY(_stack_start)
|
||||
.org 0x1000 //设置页表位置为内核执行头程序的0x1000处
|
||||
|
||||
__PML4E:
|
||||
.quad 0x102007 // 系统访问,可读写,已存在, 地址在31~12位
|
||||
.quad 0x102007 // 用户访问,可读写,已存在, 地址在31~12位
|
||||
.fill 255,8,0
|
||||
.quad 0x102007
|
||||
.fill 255,8,0
|
||||
@ -161,26 +161,26 @@ __PML4E:
|
||||
|
||||
__PDPTE:
|
||||
|
||||
.quad 0x103003 // 用户访问,可读写,已存在
|
||||
.quad 0x103007 // 用户访问,可读写,已存在
|
||||
.fill 511,8,0
|
||||
|
||||
.org 0x3000
|
||||
|
||||
__PDE:
|
||||
|
||||
.quad 0x000083 // 用户访问,可读写,已存在
|
||||
.quad 0x200083
|
||||
.quad 0x400083
|
||||
.quad 0x600083
|
||||
.quad 0x800083
|
||||
.quad 0xe0000083 /*0x a00000*/
|
||||
.quad 0xe0200083
|
||||
.quad 0xe0400083
|
||||
.quad 0xe0600083 /*0x1000000*/
|
||||
.quad 0xe0800083
|
||||
.quad 0xe0a00083
|
||||
.quad 0xe0c00083
|
||||
.quad 0xe0e00083
|
||||
.quad 0x000087 // 用户访问,可读写,已存在
|
||||
.quad 0x200087
|
||||
.quad 0x400087
|
||||
.quad 0x600087
|
||||
.quad 0x800087
|
||||
.quad 0xe0000087 /*0x a00000*/
|
||||
.quad 0xe0200087
|
||||
.quad 0xe0400087
|
||||
.quad 0xe0600087 /*0x1000000*/
|
||||
.quad 0xe0800087
|
||||
.quad 0xe0a00087
|
||||
.quad 0xe0c00087
|
||||
.quad 0xe0e00087
|
||||
.fill 499,8,0
|
||||
|
||||
// GDT表
|
||||
@ -188,14 +188,16 @@ __PDE:
|
||||
.global GDT_Table // 使得GDT可以被外部程序引用或者访问
|
||||
|
||||
GDT_Table:
|
||||
.quad 0x0000000000000000 // 0 空描述符 00
|
||||
.quad 0x0020980000000000 // 1 内核64位代码段描述符 08
|
||||
.quad 0x0000920000000000 // 2 内核64位数据段描述符 10
|
||||
.quad 0x0020f80000000000 // 3 用户64位代码段描述符 18
|
||||
.quad 0x0000f20000000000 // 4 用户64位数据段描述符 20
|
||||
.quad 0x00cf9a000000ffff // 5 内核32位代码段描述符 28
|
||||
.quad 0x00cf92000000ffff // 6 内核32位数据段描述符 30
|
||||
.fill 10, 8, 0 // 8~9 TSS(跳过了第七段) 重复十次填充8字节的空间,赋值为0
|
||||
.quad 0x0000000000000000 // 0 空描述符 0x00
|
||||
.quad 0x0020980000000000 // 1 内核64位代码段描述符 0x08
|
||||
.quad 0x0000920000000000 // 2 内核64位数据段描述符 0x10
|
||||
.quad 0x0000000000000000 // 3 用户32位代码段描述符 0x18
|
||||
.quad 0x0000000000000000 // 4 用户32位数据段描述符 0x20
|
||||
.quad 0x0020f80000000000 // 5 用户64位代码段描述符 0x28
|
||||
.quad 0x0000f20000000000 // 6 用户64位数据段描述符 0x30
|
||||
.quad 0x00cf9a000000ffff // 7 内核32位代码段描述符 0x38
|
||||
.quad 0x00cf92000000ffff // 8 内核32位数据段描述符 0x40
|
||||
.fill 10, 8, 0 // 10-11 TSS(跳过了第9段) 重复十次填充8字节的空间,赋值为0
|
||||
GDT_END:
|
||||
|
||||
GDT_POINTER:
|
||||
|
@ -65,7 +65,7 @@ void system_initialize()
|
||||
// 初始化printk
|
||||
init_printk(1440, 900, FR_address, 1440 * 900 * 4, 8, 16);
|
||||
|
||||
load_TR(8); // 加载TR寄存器
|
||||
load_TR(10); // 加载TR寄存器
|
||||
|
||||
// 初始化任务状态段表
|
||||
ul tss_item_addr = 0xffff800000007c00;
|
||||
|
@ -191,10 +191,11 @@ void mm_init()
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
// 消除一致性页表映射,将页目录(PML4E)的前10项清空
|
||||
for (int i = 0; i < 10; ++i)
|
||||
*(phys_2_virt(global_CR3) + i) = 0UL;
|
||||
|
||||
*/
|
||||
|
||||
flush_tlb();
|
||||
|
||||
|
@ -26,7 +26,38 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
|
||||
|
||||
__asm__ __volatile__("movq %0, %%fs \n\t" ::"a"(next->thread->fs));
|
||||
__asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 这是一个用户态的程序
|
||||
*
|
||||
*/
|
||||
void user_level_function()
|
||||
{
|
||||
kinfo("Program (user_level_function) is runing...");
|
||||
|
||||
while(1);
|
||||
}
|
||||
/**
|
||||
* @brief 使当前进程去执行新的代码
|
||||
*
|
||||
* @param regs 当前进程的寄存器
|
||||
* @return ul 错误码
|
||||
*/
|
||||
ul do_execve(struct pt_regs *regs)
|
||||
{
|
||||
// 选择这两个寄存器是对应了sysexit指令的需要
|
||||
regs->rdx = 0x800000; // rip 应用层程序的入口地址 这里的地址选择没有特殊要求,只要是未使用的内存区域即可。
|
||||
regs->rcx = 0xa00000; // rsp 应用层程序的栈顶地址
|
||||
|
||||
regs->rax = 1;
|
||||
regs->ds = 0;
|
||||
regs->es = 0;
|
||||
|
||||
kdebug("do_execve is running...");
|
||||
// 将程序代码拷贝到对应的内存中
|
||||
memcpy((void *)0x800000, user_level_function, 1024);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,6 +69,21 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
|
||||
ul initial_kernel_thread(ul arg)
|
||||
{
|
||||
kinfo("initial proc running...\targ:%#018lx", arg);
|
||||
|
||||
struct pt_regs *regs;
|
||||
|
||||
current_pcb->thread->rip = (ul)ret_from_system_call;
|
||||
current_pcb->thread->rsp = (ul)current_pcb + STACK_SIZE - sizeof(struct pt_regs);
|
||||
|
||||
regs = (struct pt_regs *)current_pcb->thread->rsp;
|
||||
|
||||
// 将返回用户层的代码压入堆栈,向rdx传入regs的地址,然后jmp到do_execve这个系统调用api的处理函数 这里的设计思路和switch_proc类似
|
||||
__asm__ __volatile__("movq %1, %%rsp \n\t"
|
||||
"pushq %2 \n\t"
|
||||
"jmp do_execve \n\t" ::"D"(regs),
|
||||
"m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip)
|
||||
: "memory");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -88,9 +134,7 @@ __asm__ (
|
||||
" movq %rdx, %rdi \n\t"
|
||||
" callq *%rbx \n\t"
|
||||
" movq %rax, %rdi \n\t"
|
||||
" callq do_exit \n\t"
|
||||
);
|
||||
|
||||
" callq do_exit \n\t");
|
||||
|
||||
/**
|
||||
* @brief 初始化内核进程
|
||||
@ -116,7 +160,6 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne
|
||||
regs.cs = KERNEL_CS;
|
||||
regs.ss = KERNEL_DS;
|
||||
|
||||
|
||||
// 置位中断使能标志位
|
||||
regs.rflags = (1 << 9);
|
||||
|
||||
@ -129,7 +172,6 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne
|
||||
void process_init()
|
||||
{
|
||||
|
||||
|
||||
initial_mm.pgd = (pml4t_t *)global_CR3;
|
||||
|
||||
initial_mm.code_addr_start = memory_management_struct.kernel_code_start;
|
||||
@ -146,16 +188,17 @@ 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);
|
||||
|
||||
initial_tss[0].rsp0 = initial_thread.rbp;
|
||||
|
||||
|
||||
// 初始化进程的循环链表
|
||||
list_init(&initial_proc_union.pcb.list);
|
||||
|
||||
|
||||
kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); // 初始化内核进程
|
||||
initial_proc_union.pcb.state = PROC_RUNNING;
|
||||
|
||||
@ -180,14 +223,11 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
||||
{
|
||||
struct process_control_block *tsk = NULL;
|
||||
|
||||
|
||||
// 获取一个物理页并在这个物理页内初始化pcb
|
||||
struct Page *pp = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED | PAGE_ACTIVE | PAGE_KERNEL);
|
||||
|
||||
|
||||
tsk = (struct process_control_block *)phys_2_virt(pp->addr_phys);
|
||||
|
||||
|
||||
memset(tsk, 0, sizeof(*tsk));
|
||||
|
||||
// 将当前进程的pcb复制到新的pcb内
|
||||
@ -198,7 +238,6 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
||||
|
||||
list_add(&initial_proc_union.pcb.list, &tsk->list);
|
||||
|
||||
|
||||
++(tsk->pid);
|
||||
tsk->state = PROC_UNINTERRUPTIBLE;
|
||||
|
||||
@ -214,9 +253,9 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
||||
thd->rip = regs->rip;
|
||||
thd->rsp = (ul)tsk + STACK_SIZE - sizeof(struct pt_regs);
|
||||
|
||||
// 若进程不是内核层的进程,则跳转到ret from intr
|
||||
// 若进程不是内核层的进程,则跳转到ret from system call
|
||||
if (!(tsk->flags & PF_KTHREAD))
|
||||
thd->rip = regs->rip = (ul)ret_from_intr;
|
||||
thd->rip = regs->rip = (ul)ret_from_system_call;
|
||||
|
||||
tsk->state = PROC_RUNNING;
|
||||
|
||||
|
@ -16,7 +16,8 @@
|
||||
#include "ptrace.h"
|
||||
|
||||
extern unsigned long _stack_start; // 导出内核层栈基地址(定义在head.S)
|
||||
extern void ret_from_intr(); // 导出从中断返回的函数(定义在entry.S)
|
||||
extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S)
|
||||
extern void ret_from_system_call(void); // 导出从中断返回的函数(定义在entry.S)
|
||||
|
||||
// 进程的内核栈大小 32K
|
||||
#define STACK_SIZE 32768
|
||||
|
Loading…
x
Reference in New Issue
Block a user