mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
new: vma反向映射
This commit is contained in:
parent
f3cd2b7777
commit
1dd9195d69
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -122,7 +122,10 @@
|
|||||||
"atomic.h": "c",
|
"atomic.h": "c",
|
||||||
"uart.h": "c",
|
"uart.h": "c",
|
||||||
"fat_ent.h": "c",
|
"fat_ent.h": "c",
|
||||||
"semaphore.h": "c"
|
"semaphore.h": "c",
|
||||||
|
"mm-types.h": "c",
|
||||||
|
"vfs.h": "c",
|
||||||
|
"current.h": "c"
|
||||||
},
|
},
|
||||||
"C_Cpp.errorSquiggles": "Enabled",
|
"C_Cpp.errorSquiggles": "Enabled",
|
||||||
"esbonio.sphinx.confDir": ""
|
"esbonio.sphinx.confDir": ""
|
||||||
|
2
Makefile
2
Makefile
@ -7,7 +7,7 @@ export ARCH=__x86_64__
|
|||||||
export ROOT_PATH=$(shell pwd)
|
export ROOT_PATH=$(shell pwd)
|
||||||
|
|
||||||
export DEBUG=DEBUG
|
export DEBUG=DEBUG
|
||||||
export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64 -fno-stack-protector -D $(ARCH) -O1
|
export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64 -fno-stack-protector -D $(ARCH) -O0
|
||||||
|
|
||||||
ifeq ($(DEBUG), DEBUG)
|
ifeq ($(DEBUG), DEBUG)
|
||||||
GLOBAL_CFLAGS += -g
|
GLOBAL_CFLAGS += -g
|
||||||
|
20
kernel/arch/x86_64/current.h
Normal file
20
kernel/arch/x86_64/current.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <common/glib.h>
|
||||||
|
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC optimize("O0")
|
||||||
|
struct process_control_block;
|
||||||
|
// 获取当前的pcb
|
||||||
|
static __always_inline struct process_control_block *get_current_pcb()
|
||||||
|
{
|
||||||
|
struct process_control_block *current = NULL;
|
||||||
|
// 利用了当前pcb和栈空间总大小为32k大小对齐,将rsp低15位清空,即可获得pcb的起始地址
|
||||||
|
barrier();
|
||||||
|
__asm__ __volatile__("andq %%rsp, %0 \n\t"
|
||||||
|
: "=r"(current)
|
||||||
|
: "0"(~32767UL));
|
||||||
|
barrier();
|
||||||
|
return current;
|
||||||
|
};
|
||||||
|
#define current_pcb get_current_pcb()
|
||||||
|
#pragma GCC pop_options
|
@ -10,7 +10,7 @@ $(kernel_common_subdirs): ECHO
|
|||||||
|
|
||||||
$(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)"
|
$(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)"
|
||||||
|
|
||||||
all: glib.o printk.o cpu.o bitree.o kfifo.o wait_queue.o mutex.o wait.o unistd.o string.o $(kernel_common_subdirs)
|
all: glib.o printk.o cpu.o bitree.o kfifo.o wait_queue.o mutex.o wait.o unistd.o string.o semaphore.o $(kernel_common_subdirs)
|
||||||
|
|
||||||
|
|
||||||
glib.o: glib.c
|
glib.o: glib.c
|
||||||
@ -42,3 +42,6 @@ unistd.o: unistd.c
|
|||||||
|
|
||||||
string.o: string.c
|
string.o: string.c
|
||||||
gcc $(CFLAGS) -c string.c -o string.o
|
gcc $(CFLAGS) -c string.c -o string.o
|
||||||
|
|
||||||
|
semaphore.o: semaphore.c
|
||||||
|
gcc $(CFLAGS) -c semaphore.c -o semaphore.o
|
43
kernel/common/semaphore.c
Normal file
43
kernel/common/semaphore.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include "semaphore.h"
|
||||||
|
#include <sched/sched.h>
|
||||||
|
#include <process/process.h>
|
||||||
|
|
||||||
|
|
||||||
|
void semaphore_down(semaphore_t *sema)
|
||||||
|
{
|
||||||
|
if (atomic_read(&sema->counter) > 0) // 信号量大于0,资源充足
|
||||||
|
atomic_dec(&sema->counter);
|
||||||
|
else // 资源不足,进程休眠
|
||||||
|
{
|
||||||
|
// 将当前进程加入信号量的等待队列
|
||||||
|
wait_queue_node_t wait;
|
||||||
|
wait_queue_init(&wait, current_pcb);
|
||||||
|
|
||||||
|
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||||
|
|
||||||
|
list_append(&sema->wait_queue.wait_list, &wait.wait_list);
|
||||||
|
|
||||||
|
// 执行调度
|
||||||
|
sched_cfs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void semaphore_up(semaphore_t *sema)
|
||||||
|
{
|
||||||
|
if (list_empty(&sema->wait_queue.wait_list)) // 没有进程在等待资源
|
||||||
|
{
|
||||||
|
atomic_inc(&sema->counter);
|
||||||
|
}
|
||||||
|
else // 有进程在等待资源,唤醒进程
|
||||||
|
{
|
||||||
|
|
||||||
|
wait_queue_node_t *wq = container_of(list_next(&sema->wait_queue.wait_list), wait_queue_node_t, wait_list);
|
||||||
|
list_del(&wq->wait_list);
|
||||||
|
|
||||||
|
wq->pcb->state = PROC_RUNNING;
|
||||||
|
sched_cfs_enqueue(wq->pcb);
|
||||||
|
|
||||||
|
// 当前进程缺少需要的资源,立即标为需要被调度
|
||||||
|
current_pcb->flags |= PF_NEED_SCHED;
|
||||||
|
}
|
||||||
|
};
|
@ -12,10 +12,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <common/atomic.h>
|
#include <common/atomic.h>
|
||||||
|
|
||||||
#include <process/process.h>
|
#include <common/wait_queue.h>
|
||||||
#include <sched/sched.h>
|
|
||||||
#include "wait_queue.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 信号量的结构体
|
* @brief 信号量的结构体
|
||||||
@ -27,13 +24,16 @@ typedef struct
|
|||||||
wait_queue_node_t wait_queue;
|
wait_queue_node_t wait_queue;
|
||||||
} semaphore_t;
|
} semaphore_t;
|
||||||
|
|
||||||
|
void __semaphore_invoke_sched();
|
||||||
|
void __semaphore_sched_enqueue(struct process_control_block *pcb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化信号量
|
* @brief 初始化信号量
|
||||||
*
|
*
|
||||||
* @param sema 信号量对象
|
* @param sema 信号量对象
|
||||||
* @param count 信号量的初始值
|
* @param count 信号量的初始值
|
||||||
*/
|
*/
|
||||||
void semaphore_init(semaphore_t *sema, ul count)
|
static __always_inline void semaphore_init(semaphore_t *sema, ul count)
|
||||||
{
|
{
|
||||||
atomic_set(&sema->counter, count);
|
atomic_set(&sema->counter, count);
|
||||||
wait_queue_init(&sema->wait_queue, NULL);
|
wait_queue_init(&sema->wait_queue, NULL);
|
||||||
@ -44,40 +44,6 @@ void semaphore_init(semaphore_t *sema, ul count)
|
|||||||
*
|
*
|
||||||
* @param sema
|
* @param sema
|
||||||
*/
|
*/
|
||||||
void semaphore_down(semaphore_t *sema)
|
void semaphore_down(semaphore_t *sema);
|
||||||
{
|
|
||||||
if (atomic_read(&sema->counter) > 0) // 信号量大于0,资源充足
|
|
||||||
atomic_dec(&sema->counter);
|
|
||||||
else // 资源不足,进程休眠
|
|
||||||
{
|
|
||||||
// 将当前进程加入信号量的等待队列
|
|
||||||
wait_queue_node_t wait;
|
|
||||||
wait_queue_init(&wait, current_pcb);
|
|
||||||
|
|
||||||
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
void semaphore_up(semaphore_t *sema);
|
||||||
|
|
||||||
list_append(&sema->wait_queue.wait_list, &wait.wait_list);
|
|
||||||
|
|
||||||
// 执行调度
|
|
||||||
sched_cfs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void semaphore_up(semaphore_t *sema)
|
|
||||||
{
|
|
||||||
if (list_empty(&sema->wait_queue.wait_list)) // 没有进程在等待资源
|
|
||||||
{
|
|
||||||
atomic_inc(&sema->counter);
|
|
||||||
}
|
|
||||||
else // 有进程在等待资源,唤醒进程
|
|
||||||
{
|
|
||||||
|
|
||||||
wait_queue_node_t *wq = container_of(list_next(&sema->wait_queue.wait_list), wait_queue_node_t, wait_list);
|
|
||||||
list_del(&wq->wait_list);
|
|
||||||
|
|
||||||
wq->pcb->state = PROC_RUNNING;
|
|
||||||
sched_cfs_enqueue(wq->pcb);
|
|
||||||
// 当前进程缺少需要的资源,立即标为需要被调度
|
|
||||||
current_pcb->flags |= PF_NEED_SCHED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,18 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
__volatile__ char lock; // 1:unlocked 0:locked
|
int8_t lock; // 1:unlocked 0:locked
|
||||||
} spinlock_t;
|
} spinlock_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 初始化自旋锁
|
|
||||||
*
|
|
||||||
* @param lock
|
|
||||||
*/
|
|
||||||
void spin_init(spinlock_t *lock)
|
|
||||||
{
|
|
||||||
lock->lock = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 自旋锁加锁
|
* @brief 自旋锁加锁
|
||||||
@ -63,6 +54,18 @@ void spin_unlock(spinlock_t *lock)
|
|||||||
: "=m"(lock->lock)::"memory");
|
: "=m"(lock->lock)::"memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化自旋锁
|
||||||
|
*
|
||||||
|
* @param lock
|
||||||
|
*/
|
||||||
|
void spin_init(spinlock_t *lock)
|
||||||
|
{
|
||||||
|
barrier();
|
||||||
|
lock->lock = 1;
|
||||||
|
barrier();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 自旋锁加锁(不改变自旋锁持有计数)
|
* @brief 自旋锁加锁(不改变自旋锁持有计数)
|
||||||
*
|
*
|
||||||
@ -92,8 +95,6 @@ void spin_unlock_no_preempt(spinlock_t * lock)
|
|||||||
: "=m"(lock->lock)::"memory");
|
: "=m"(lock->lock)::"memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 尝试加锁
|
* @brief 尝试加锁
|
||||||
*
|
*
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <mm/slab.h>
|
#include <mm/slab.h>
|
||||||
#include <syscall/syscall.h>
|
#include <syscall/syscall.h>
|
||||||
#include <syscall/syscall_num.h>
|
#include <syscall/syscall_num.h>
|
||||||
|
#include <sched/sched.h>
|
||||||
|
|
||||||
struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES];
|
struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES];
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "textui.h"
|
#include "textui.h"
|
||||||
#include <driver/uart/uart.h>
|
#include <driver/uart/uart.h>
|
||||||
|
#include <common/errno.h>
|
||||||
|
#include "screen_manager.h"
|
||||||
|
|
||||||
#define WHITE 0x00ffffff //白
|
#define WHITE 0x00ffffff //白
|
||||||
#define BLACK 0x00000000 //黑
|
#define BLACK 0x00000000 //黑
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <common/string.h>
|
#include <common/string.h>
|
||||||
#include <common/printk.h>
|
#include <common/printk.h>
|
||||||
#include <common/atomic.h>
|
#include <common/atomic.h>
|
||||||
|
#include <common/errno.h>
|
||||||
|
|
||||||
struct scm_ui_framework_t textui_framework;
|
struct scm_ui_framework_t textui_framework;
|
||||||
static spinlock_t __window_id_lock = {1};
|
static spinlock_t __window_id_lock = {1};
|
||||||
|
@ -27,3 +27,38 @@ void __vma_unlink_list(struct mm_struct * mm, struct vm_area_struct * vma);
|
|||||||
* @return uint64_t 已映射的物理地址
|
* @return uint64_t 已映射的物理地址
|
||||||
*/
|
*/
|
||||||
uint64_t __mm_get_paddr(struct mm_struct *mm, uint64_t vaddr);
|
uint64_t __mm_get_paddr(struct mm_struct *mm, uint64_t vaddr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建anon_vma,并将其与页面结构体进行绑定
|
||||||
|
* 若提供的页面结构体指针为NULL,则只创建,不绑定
|
||||||
|
*
|
||||||
|
* @param page 页面结构体的指针
|
||||||
|
* @param lock_page 是否将页面结构体加锁
|
||||||
|
* @return struct anon_vma_t* 创建好的anon_vma
|
||||||
|
*/
|
||||||
|
struct anon_vma_t *__anon_vma_create_alloc(struct Page *page, bool lock_page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 释放anon vma结构体
|
||||||
|
*
|
||||||
|
* @param anon_vma 待释放的anon_vma结构体
|
||||||
|
* @return int 返回码
|
||||||
|
*/
|
||||||
|
int __anon_vma_free(struct anon_vma_t *anon_vma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将指定的vma加入到anon_vma的管理范围之中
|
||||||
|
*
|
||||||
|
* @param anon_vma 页面的anon_vma
|
||||||
|
* @param vma 待加入的vma
|
||||||
|
* @return int 返回码
|
||||||
|
*/
|
||||||
|
int __anon_vma_add(struct anon_vma_t *anon_vma, struct vm_area_struct *vma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从anon_vma的管理范围中删除指定的vma
|
||||||
|
* (在进入这个函数之前,应该要加锁)
|
||||||
|
* @param vma 将要取消对应的anon_vma管理的vma结构体
|
||||||
|
* @return int 返回码
|
||||||
|
*/
|
||||||
|
int __anon_vma_del(struct vm_area_struct *vma);
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <common/glib.h>
|
#include <common/glib.h>
|
||||||
#include <common/semaphore.h>
|
#include <common/semaphore.h>
|
||||||
|
#include <common/spinlock.h>
|
||||||
#include <common/atomic.h>
|
#include <common/atomic.h>
|
||||||
|
|
||||||
struct mm_struct;
|
struct mm_struct;
|
||||||
@ -163,10 +164,18 @@ struct mm_struct
|
|||||||
*/
|
*/
|
||||||
struct anon_vma_t
|
struct anon_vma_t
|
||||||
{
|
{
|
||||||
|
// anon vma的操作信号量
|
||||||
semaphore_t sem;
|
semaphore_t sem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录当前有多少个vma与该anon_vma关联,当vma被释放时,
|
||||||
|
* 应当检查这个值。当该值为0时,应当释放anon_vma结构体
|
||||||
|
*/
|
||||||
atomic_t ref_count;
|
atomic_t ref_count;
|
||||||
|
|
||||||
// todo: 把下面的循环链表更换成红黑树
|
// todo: 把下面的循环链表更换成红黑树
|
||||||
// 与当前anon_vma相关的vma的列表
|
// 与当前anon_vma相关的vma的列表
|
||||||
struct List vma_list;
|
struct List vma_list;
|
||||||
|
// 当前anon vma对应的page
|
||||||
|
struct Page* page;
|
||||||
};
|
};
|
@ -213,6 +213,7 @@ void mm_init()
|
|||||||
barrier();
|
barrier();
|
||||||
tmp_page = memory_management_struct.pages_struct + j;
|
tmp_page = memory_management_struct.pages_struct + j;
|
||||||
page_init(tmp_page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
|
page_init(tmp_page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
|
||||||
|
barrier();
|
||||||
page_num = tmp_page->addr_phys >> PAGE_2M_SHIFT;
|
page_num = tmp_page->addr_phys >> PAGE_2M_SHIFT;
|
||||||
*(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
|
*(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
|
||||||
++tmp_page->zone->count_pages_using;
|
++tmp_page->zone->count_pages_using;
|
||||||
@ -248,7 +249,7 @@ unsigned long page_init(struct Page *page, ul flags)
|
|||||||
++page->zone->total_pages_link;
|
++page->zone->total_pages_link;
|
||||||
}
|
}
|
||||||
page->anon_vma = NULL;
|
page->anon_vma = NULL;
|
||||||
spin_init(&page->op_lock);
|
spin_init(&(page->op_lock));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,7 +589,9 @@ uint64_t mm_do_brk(uint64_t old_brk_end_addr, int64_t offset)
|
|||||||
{
|
{
|
||||||
for (uint64_t i = old_brk_end_addr; i < end_addr; i += PAGE_2M_SIZE)
|
for (uint64_t i = old_brk_end_addr; i < end_addr; i += PAGE_2M_SIZE)
|
||||||
{
|
{
|
||||||
mm_map_vma(current_pcb->mm, i, PAGE_2M_SIZE, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, VM_USER | VM_ACCESS_FLAGS, NULL);
|
struct vm_area_struct * vma=NULL;
|
||||||
|
mm_create_vma(current_pcb->mm, i, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
|
||||||
|
mm_map_vma(vma, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys);
|
||||||
}
|
}
|
||||||
current_pcb->mm->brk_end = end_addr;
|
current_pcb->mm->brk_end = end_addr;
|
||||||
}
|
}
|
||||||
|
@ -325,6 +325,7 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)
|
|||||||
vma->vm_mm = mm;
|
vma->vm_mm = mm;
|
||||||
vma->vm_prev = vma->vm_next = NULL;
|
vma->vm_prev = vma->vm_next = NULL;
|
||||||
vma->vm_ops = NULL;
|
vma->vm_ops = NULL;
|
||||||
|
list_init(&vma->anon_vma_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -442,17 +443,26 @@ void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_sta
|
|||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 创建VMA,并将物理地址映射到指定的虚拟地址处
|
* @brief 创建VMA
|
||||||
*
|
*
|
||||||
* @param mm 要绑定的内存空间分布结构体
|
* @param mm 要绑定的内存空间分布结构体
|
||||||
* @param vaddr 起始虚拟地址
|
* @param vaddr 起始虚拟地址
|
||||||
* @param length 长度(字节)
|
* @param length 长度(字节)
|
||||||
* @param paddr 起始物理地址
|
|
||||||
* @param vm_flags vma的标志
|
* @param vm_flags vma的标志
|
||||||
* @param vm_ops vma的操作接口
|
* @param vm_ops vma的操作接口
|
||||||
|
* @param res_vma 返回的vma指针
|
||||||
* @return int 错误码
|
* @return int 错误码
|
||||||
*/
|
*/
|
||||||
int mm_map_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, uint64_t paddr, vm_flags_t vm_flags, struct vm_operations_t *vm_ops);
|
int mm_create_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, vm_flags_t vm_flags, struct vm_operations_t *vm_ops, struct vm_area_struct **res_vma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将指定的物理地址映射到指定的vma处
|
||||||
|
*
|
||||||
|
* @param vma 要进行映射的VMA结构体
|
||||||
|
* @param paddr 起始物理地址
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int mm_map_vma(struct vm_area_struct *vma, uint64_t paddr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 在页表中取消指定的vma的映射
|
* @brief 在页表中取消指定的vma的映射
|
||||||
|
@ -306,17 +306,17 @@ void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_sta
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 创建VMA,并将物理地址映射到指定的虚拟地址处
|
* @brief 创建VMA
|
||||||
*
|
*
|
||||||
* @param mm 要绑定的内存空间分布结构体
|
* @param mm 要绑定的内存空间分布结构体
|
||||||
* @param vaddr 起始虚拟地址
|
* @param vaddr 起始虚拟地址
|
||||||
* @param length 长度(字节)
|
* @param length 长度(字节)
|
||||||
* @param paddr 起始物理地址
|
|
||||||
* @param vm_flags vma的标志
|
* @param vm_flags vma的标志
|
||||||
* @param vm_ops vma的操作接口
|
* @param vm_ops vma的操作接口
|
||||||
|
* @param res_vma 返回的vma指针
|
||||||
* @return int 错误码
|
* @return int 错误码
|
||||||
*/
|
*/
|
||||||
int mm_map_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, uint64_t paddr, vm_flags_t vm_flags, struct vm_operations_t *vm_ops)
|
int mm_create_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, vm_flags_t vm_flags, struct vm_operations_t *vm_ops, struct vm_area_struct **res_vma)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
struct vm_area_struct *vma = vm_area_alloc(mm);
|
struct vm_area_struct *vma = vm_area_alloc(mm);
|
||||||
@ -327,19 +327,50 @@ int mm_map_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, uint64_t p
|
|||||||
vma->vm_start = vaddr;
|
vma->vm_start = vaddr;
|
||||||
vma->vm_end = vaddr + length;
|
vma->vm_end = vaddr + length;
|
||||||
|
|
||||||
// 将vma与对应的anon_vma进行绑定
|
// 将VMA加入mm的链表
|
||||||
struct Page * pg = Phy_to_2M_Page(paddr);
|
|
||||||
// 将VMA加入链表
|
|
||||||
retval = vma_insert(mm, vma);
|
retval = vma_insert(mm, vma);
|
||||||
if (retval == -EEXIST) // 之前已经存在了相同的vma,直接返回
|
if (retval == -EEXIST) // 之前已经存在了相同的vma,直接返回
|
||||||
{
|
{
|
||||||
|
*res_vma = vma_find(mm, vma->vm_start);
|
||||||
kfree(vma);
|
kfree(vma);
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
|
*res_vma = vma;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将指定的物理地址映射到指定的vma处
|
||||||
|
*
|
||||||
|
* @param vma 要进行映射的VMA结构体
|
||||||
|
* @param paddr 起始物理地址
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int mm_map_vma(struct vm_area_struct *vma, uint64_t paddr)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
// 获取物理地址对应的页面
|
||||||
|
struct Page *pg = Phy_to_2M_Page(paddr);
|
||||||
|
if (unlikely(pg->anon_vma == NULL)) // 若页面不存在anon_vma,则为页面创建anon_vma
|
||||||
|
{
|
||||||
|
uint64_t rflags;
|
||||||
|
// todo: 查明为什么在mm_init中,spin init之后,pg会变为0
|
||||||
|
spin_init(&pg->op_lock);
|
||||||
|
spin_lock_irqsave(&pg->op_lock, rflags);
|
||||||
|
if (unlikely(pg->anon_vma == NULL))
|
||||||
|
__anon_vma_create_alloc(pg, false);
|
||||||
|
spin_unlock_irqrestore(&pg->op_lock, rflags);
|
||||||
|
}
|
||||||
|
barrier();
|
||||||
|
// 将anon vma与vma进行绑定
|
||||||
|
__anon_vma_add(pg->anon_vma, vma);
|
||||||
|
barrier();
|
||||||
|
|
||||||
|
uint64_t length = vma->vm_end - vma->vm_start;
|
||||||
|
// ==== 将地址映射到页表 ====
|
||||||
uint64_t len_4k = length % PAGE_2M_SIZE;
|
uint64_t len_4k = length % PAGE_2M_SIZE;
|
||||||
uint64_t len_2m = length - len_4k;
|
uint64_t len_2m = length - len_4k;
|
||||||
|
|
||||||
// ==== 将地址映射到页表
|
|
||||||
/*
|
/*
|
||||||
todo: 限制页面的读写权限
|
todo: 限制页面的读写权限
|
||||||
*/
|
*/
|
||||||
@ -348,12 +379,12 @@ int mm_map_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, uint64_t p
|
|||||||
if (likely(len_2m > 0))
|
if (likely(len_2m > 0))
|
||||||
{
|
{
|
||||||
uint64_t page_flags = 0;
|
uint64_t page_flags = 0;
|
||||||
if (vm_flags & VM_USER)
|
if (vma->vm_flags & VM_USER)
|
||||||
page_flags = PAGE_USER_PAGE;
|
page_flags = PAGE_USER_PAGE;
|
||||||
else
|
else
|
||||||
page_flags = PAGE_KERNEL_PAGE;
|
page_flags = PAGE_KERNEL_PAGE;
|
||||||
// 这里直接设置user标志位为false,因为该函数内部会对其进行自动校正
|
// 这里直接设置user标志位为false,因为该函数内部会对其进行自动校正
|
||||||
retval = mm_map_proc_page_table((uint64_t)mm->pgd, true, vaddr, paddr, len_2m, page_flags, false, false, false);
|
retval = mm_map_proc_page_table((uint64_t)vma->vm_mm->pgd, true, vma->vm_start, paddr, len_2m, page_flags, false, false, false);
|
||||||
if (unlikely(retval != 0))
|
if (unlikely(retval != 0))
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@ -363,12 +394,12 @@ int mm_map_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, uint64_t p
|
|||||||
len_4k = ALIGN(len_4k, PAGE_4K_SIZE);
|
len_4k = ALIGN(len_4k, PAGE_4K_SIZE);
|
||||||
|
|
||||||
uint64_t page_flags = 0;
|
uint64_t page_flags = 0;
|
||||||
if (vm_flags & VM_USER)
|
if (vma->vm_flags & VM_USER)
|
||||||
page_flags = PAGE_USER_4K_PAGE;
|
page_flags = PAGE_USER_4K_PAGE;
|
||||||
else
|
else
|
||||||
page_flags = PAGE_KERNEL_4K_PAGE;
|
page_flags = PAGE_KERNEL_4K_PAGE;
|
||||||
// 这里直接设置user标志位为false,因为该函数内部会对其进行自动校正
|
// 这里直接设置user标志位为false,因为该函数内部会对其进行自动校正
|
||||||
retval = mm_map_proc_page_table((uint64_t)mm->pgd, true, vaddr + len_2m, paddr + len_2m, len_4k, page_flags, false, false, true);
|
retval = mm_map_proc_page_table((uint64_t)vma->vm_mm->pgd, true, vma->vm_start + len_2m, paddr + len_2m, len_4k, page_flags, false, false, true);
|
||||||
if (unlikely(retval != 0))
|
if (unlikely(retval != 0))
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@ -376,9 +407,7 @@ int mm_map_vma(struct mm_struct *mm, uint64_t vaddr, uint64_t length, uint64_t p
|
|||||||
flush_tlb();
|
flush_tlb();
|
||||||
return 0;
|
return 0;
|
||||||
failed:;
|
failed:;
|
||||||
kdebug("failed.");
|
kdebug("map VMA failed.");
|
||||||
__vma_unlink_list(mm, vma);
|
|
||||||
vm_area_free(vma);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,3 +154,102 @@ int vma_insert(struct mm_struct *mm, struct vm_area_struct *vma)
|
|||||||
__vma_link_list(mm, vma, prev);
|
__vma_link_list(mm, vma, prev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建anon_vma,并将其与页面结构体进行绑定
|
||||||
|
* 若提供的页面结构体指针为NULL,则只创建,不绑定
|
||||||
|
*
|
||||||
|
* @param page 页面结构体的指针
|
||||||
|
* @param lock_page 是否将页面结构体加锁
|
||||||
|
* @return struct anon_vma_t* 创建好的anon_vma
|
||||||
|
*/
|
||||||
|
struct anon_vma_t *__anon_vma_create_alloc(struct Page *page, bool lock_page)
|
||||||
|
{
|
||||||
|
struct anon_vma_t *anon_vma = (struct anon_vma_t *)kmalloc(sizeof(struct anon_vma_t), 0);
|
||||||
|
if (unlikely(anon_vma == NULL))
|
||||||
|
return NULL;
|
||||||
|
memset(anon_vma, 0, sizeof(struct anon_vma_t));
|
||||||
|
|
||||||
|
list_init(&anon_vma->vma_list);
|
||||||
|
semaphore_init(&anon_vma->sem, 1);
|
||||||
|
|
||||||
|
// 需要和page进行绑定
|
||||||
|
if (page != NULL)
|
||||||
|
{
|
||||||
|
if (lock_page == true) // 需要加锁
|
||||||
|
{
|
||||||
|
uint64_t rflags;
|
||||||
|
spin_lock_irqsave(&page->op_lock, rflags);
|
||||||
|
page->anon_vma = anon_vma;
|
||||||
|
spin_unlock_irqrestore(&page->op_lock, rflags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
page->anon_vma = anon_vma;
|
||||||
|
|
||||||
|
anon_vma->page = page;
|
||||||
|
}
|
||||||
|
return anon_vma;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将指定的vma加入到anon_vma的管理范围之中
|
||||||
|
*
|
||||||
|
* @param anon_vma 页面的anon_vma
|
||||||
|
* @param vma 待加入的vma
|
||||||
|
* @return int 返回码
|
||||||
|
*/
|
||||||
|
int __anon_vma_add(struct anon_vma_t *anon_vma, struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
semaphore_down(&anon_vma->sem);
|
||||||
|
list_add(&anon_vma->vma_list, &vma->anon_vma_list);
|
||||||
|
vma->anon_vma = anon_vma;
|
||||||
|
atomic_inc(&anon_vma->ref_count);
|
||||||
|
semaphore_up(&anon_vma->sem);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 释放anon vma结构体
|
||||||
|
*
|
||||||
|
* @param anon_vma 待释放的anon_vma结构体
|
||||||
|
* @return int 返回码
|
||||||
|
*/
|
||||||
|
int __anon_vma_free(struct anon_vma_t *anon_vma)
|
||||||
|
{
|
||||||
|
if (anon_vma->page != NULL)
|
||||||
|
{
|
||||||
|
spin_lock(&anon_vma->page->op_lock);
|
||||||
|
anon_vma->page->anon_vma = NULL;
|
||||||
|
spin_unlock(&anon_vma->page->op_lock);
|
||||||
|
}
|
||||||
|
kfree(anon_vma);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从anon_vma的管理范围中删除指定的vma
|
||||||
|
* (在进入这个函数之前,应该要加锁)
|
||||||
|
* @param vma 将要取消对应的anon_vma管理的vma结构体
|
||||||
|
* @return int 返回码
|
||||||
|
*/
|
||||||
|
int __anon_vma_del(struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
// 当前vma没有绑定anon_vma
|
||||||
|
if (vma->anon_vma == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
list_del(&vma->anon_vma_list);
|
||||||
|
semaphore_down(&vma->anon_vma->sem);
|
||||||
|
atomic_dec(&vma->anon_vma->ref_count);
|
||||||
|
|
||||||
|
if (unlikely(atomic_read(&vma->anon_vma->ref_count) == 0)) // 应当释放该anon_vma
|
||||||
|
{
|
||||||
|
__anon_vma_free(vma->anon_vma);
|
||||||
|
// 释放了anon_vma之后,清理当前vma的关联数据
|
||||||
|
vma->anon_vma = NULL;
|
||||||
|
list_init(&vma->anon_vma_list);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
semaphore_up(&vma->anon_vma->sem);
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <process/process.h>
|
#include <arch/x86_64/current.h>
|
||||||
|
#include "proc-types.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 增加自旋锁计数变量
|
* @brief 增加自旋锁计数变量
|
||||||
|
131
kernel/process/proc-types.h
Normal file
131
kernel/process/proc-types.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common/wait_queue.h>
|
||||||
|
|
||||||
|
// 进程最大可拥有的文件描述符数量
|
||||||
|
#define PROC_MAX_FD_NUM 16
|
||||||
|
|
||||||
|
// 进程的内核栈大小 32K
|
||||||
|
#define STACK_SIZE 32768
|
||||||
|
|
||||||
|
// 进程的运行状态
|
||||||
|
// 正在运行
|
||||||
|
#define PROC_RUNNING (1 << 0)
|
||||||
|
// 可被中断
|
||||||
|
#define PROC_INTERRUPTIBLE (1 << 1)
|
||||||
|
// 不可被中断
|
||||||
|
#define PROC_UNINTERRUPTIBLE (1 << 2)
|
||||||
|
// 挂起
|
||||||
|
#define PROC_ZOMBIE (1 << 3)
|
||||||
|
// 已停止
|
||||||
|
#define PROC_STOPPED (1 << 4)
|
||||||
|
|
||||||
|
// 内核代码段基地址
|
||||||
|
#define KERNEL_CS (0x08)
|
||||||
|
// 内核数据段基地址
|
||||||
|
#define KERNEL_DS (0x10)
|
||||||
|
// 用户代码段基地址
|
||||||
|
#define USER_CS (0x28)
|
||||||
|
// 用户数据段基地址
|
||||||
|
#define USER_DS (0x30)
|
||||||
|
|
||||||
|
// 进程初始化时的数据拷贝标志位
|
||||||
|
#define CLONE_FS (1 << 0) // 在进程间共享打开的文件
|
||||||
|
#define CLONE_SIGNAL (1 << 1)
|
||||||
|
#define CLONE_VM (1 << 2) // 在进程间共享虚拟内存空间
|
||||||
|
|
||||||
|
struct thread_struct
|
||||||
|
{
|
||||||
|
// 内核层栈基指针
|
||||||
|
ul rbp; // in tss rsp0
|
||||||
|
// 内核层代码指针
|
||||||
|
ul rip;
|
||||||
|
// 内核层栈指针
|
||||||
|
ul rsp;
|
||||||
|
|
||||||
|
ul fs, gs;
|
||||||
|
|
||||||
|
ul cr2;
|
||||||
|
// 异常号
|
||||||
|
ul trap_num;
|
||||||
|
// 错误码
|
||||||
|
ul err_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========= pcb->flags =========
|
||||||
|
// 进程标志位
|
||||||
|
#define PF_KTHREAD (1UL << 0) // 内核线程
|
||||||
|
#define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
|
||||||
|
#define PF_VFORK (1UL << 2) // 标志进程是否由于vfork而存在资源共享
|
||||||
|
#define PF_KFORK (1UL << 3) // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 进程控制块
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct process_control_block
|
||||||
|
{
|
||||||
|
// 进程的状态
|
||||||
|
volatile long state;
|
||||||
|
// 进程标志:进程、线程、内核线程
|
||||||
|
unsigned long flags;
|
||||||
|
int64_t preempt_count; // 持有的自旋锁的数量
|
||||||
|
long signal;
|
||||||
|
long cpu_id; // 当前进程在哪个CPU核心上运行
|
||||||
|
// 内存空间分布结构体, 记录内存页表和程序段信息
|
||||||
|
struct mm_struct *mm;
|
||||||
|
|
||||||
|
// 进程切换时保存的状态信息
|
||||||
|
struct thread_struct *thread;
|
||||||
|
|
||||||
|
// 连接各个pcb的双向链表
|
||||||
|
struct List list;
|
||||||
|
|
||||||
|
// 地址空间范围
|
||||||
|
// 用户空间: 0x0000 0000 0000 0000 ~ 0x0000 7fff ffff ffff
|
||||||
|
// 内核空间: 0xffff 8000 0000 0000 ~ 0xffff ffff ffff ffff
|
||||||
|
uint64_t addr_limit;
|
||||||
|
|
||||||
|
long pid;
|
||||||
|
long priority; // 优先级
|
||||||
|
int64_t virtual_runtime; // 虚拟运行时间
|
||||||
|
|
||||||
|
// 进程拥有的文件描述符的指针数组
|
||||||
|
// todo: 改用动态指针数组
|
||||||
|
struct vfs_file_t *fds[PROC_MAX_FD_NUM];
|
||||||
|
|
||||||
|
// 链表中的下一个pcb
|
||||||
|
struct process_control_block *next_pcb;
|
||||||
|
// 父进程的pcb
|
||||||
|
struct process_control_block *parent_pcb;
|
||||||
|
|
||||||
|
int32_t exit_code; // 进程退出时的返回码
|
||||||
|
wait_queue_node_t wait_child_proc_exit; // 子进程退出等待队列
|
||||||
|
};
|
||||||
|
|
||||||
|
// 将进程的pcb和内核栈融合到一起,8字节对齐
|
||||||
|
union proc_union
|
||||||
|
{
|
||||||
|
struct process_control_block pcb;
|
||||||
|
ul stack[STACK_SIZE / sizeof(ul)];
|
||||||
|
} __attribute__((aligned(8)));
|
||||||
|
|
||||||
|
struct tss_struct
|
||||||
|
{
|
||||||
|
unsigned int reserved0;
|
||||||
|
ul rsp0;
|
||||||
|
ul rsp1;
|
||||||
|
ul rsp2;
|
||||||
|
ul reserved1;
|
||||||
|
ul ist1;
|
||||||
|
ul ist2;
|
||||||
|
ul ist3;
|
||||||
|
ul ist4;
|
||||||
|
ul ist5;
|
||||||
|
ul ist6;
|
||||||
|
ul ist7;
|
||||||
|
ul reserved2;
|
||||||
|
unsigned short reserved3;
|
||||||
|
// io位图基地址
|
||||||
|
unsigned short io_map_base_addr;
|
||||||
|
} __attribute__((packed)); // 使用packed表明是紧凑结构,编译器不会对成员变量进行字节对齐。
|
@ -262,10 +262,13 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
|
|||||||
{
|
{
|
||||||
|
|
||||||
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
|
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
|
||||||
int ret = mm_map_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, pa, VM_USER | VM_ACCESS_FLAGS, NULL);
|
struct vm_area_struct *vma = NULL;
|
||||||
|
int ret = mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
|
||||||
// 防止内存泄露
|
// 防止内存泄露
|
||||||
if (ret == -EEXIST)
|
if (ret == -EEXIST)
|
||||||
free_pages(Phy_to_2M_Page(pa), 1);
|
free_pages(Phy_to_2M_Page(pa), 1);
|
||||||
|
else
|
||||||
|
mm_map_vma(vma, pa);
|
||||||
memset((void *)virt_base, 0, PAGE_2M_SIZE);
|
memset((void *)virt_base, 0, PAGE_2M_SIZE);
|
||||||
map_size = PAGE_2M_SIZE;
|
map_size = PAGE_2M_SIZE;
|
||||||
}
|
}
|
||||||
@ -278,9 +281,12 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
|
|||||||
{
|
{
|
||||||
uint64_t paddr = virt_2_phys((uint64_t)kmalloc(PAGE_4K_SIZE, 0));
|
uint64_t paddr = virt_2_phys((uint64_t)kmalloc(PAGE_4K_SIZE, 0));
|
||||||
|
|
||||||
int val = mm_map_vma(current_pcb->mm, virt_base + off, PAGE_4K_SIZE, paddr, VM_USER | VM_ACCESS_FLAGS, NULL);
|
struct vm_area_struct *vma = NULL;
|
||||||
|
int val = mm_create_vma(current_pcb->mm, virt_base + off, PAGE_4K_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
|
||||||
if (val == -EEXIST)
|
if (val == -EEXIST)
|
||||||
kfree(phys_2_virt(paddr));
|
kfree(phys_2_virt(paddr));
|
||||||
|
else
|
||||||
|
mm_map_vma(vma, paddr);
|
||||||
memset((void *)(virt_base + off), 0, PAGE_4K_SIZE);
|
memset((void *)(virt_base + off), 0, PAGE_4K_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,10 +313,13 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
|
|||||||
regs->rbp = current_pcb->mm->stack_start;
|
regs->rbp = current_pcb->mm->stack_start;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
struct vm_area_struct *vma = NULL;
|
||||||
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
|
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
|
||||||
int val = mm_map_vma(current_pcb->mm, current_pcb->mm->stack_start - PAGE_2M_SIZE, PAGE_2M_SIZE, pa, VM_USER | VM_ACCESS_FLAGS, NULL);
|
int val = mm_create_vma(current_pcb->mm, current_pcb->mm->stack_start - PAGE_2M_SIZE, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
|
||||||
if (val == -EEXIST)
|
if (val == -EEXIST)
|
||||||
free_pages(Phy_to_2M_Page(pa), 1);
|
free_pages(Phy_to_2M_Page(pa), 1);
|
||||||
|
else
|
||||||
|
mm_map_vma(vma, pa);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空栈空间
|
// 清空栈空间
|
||||||
@ -928,8 +937,14 @@ uint64_t process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb
|
|||||||
{
|
{
|
||||||
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
|
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
|
||||||
|
|
||||||
mm_map_vma(new_mms, vma->vm_start + i * PAGE_2M_SIZE, PAGE_2M_SIZE, pa, vma->vm_flags, vma->vm_ops);
|
struct vm_area_struct *new_vma = NULL;
|
||||||
// kdebug("phys_2_virt(pa)=%#018lx, vaddr=%#018lx", phys_2_virt(pa), vma->vm_start + i * PAGE_2M_SIZE);
|
int ret = mm_create_vma(new_mms, vma->vm_start + i * PAGE_2M_SIZE, PAGE_2M_SIZE, vma->vm_flags, vma->vm_ops, &new_vma);
|
||||||
|
// 防止内存泄露
|
||||||
|
if (unlikely(ret == -EEXIST))
|
||||||
|
free_pages(Phy_to_2M_Page(pa), 1);
|
||||||
|
else
|
||||||
|
mm_map_vma(new_vma, pa);
|
||||||
|
|
||||||
memcpy((void *)phys_2_virt(pa), (void *)(vma->vm_start + i * PAGE_2M_SIZE), (vma_size >= PAGE_2M_SIZE) ? PAGE_2M_SIZE : vma_size);
|
memcpy((void *)phys_2_virt(pa), (void *)(vma->vm_start + i * PAGE_2M_SIZE), (vma_size >= PAGE_2M_SIZE) ? PAGE_2M_SIZE : vma_size);
|
||||||
vma_size -= PAGE_2M_SIZE;
|
vma_size -= PAGE_2M_SIZE;
|
||||||
}
|
}
|
||||||
@ -938,7 +953,15 @@ uint64_t process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb
|
|||||||
{
|
{
|
||||||
uint64_t map_size = PAGE_4K_ALIGN(vma_size);
|
uint64_t map_size = PAGE_4K_ALIGN(vma_size);
|
||||||
uint64_t va = (uint64_t)kmalloc(map_size, 0);
|
uint64_t va = (uint64_t)kmalloc(map_size, 0);
|
||||||
mm_map_vma(new_mms, vma->vm_start, map_size, virt_2_phys(va), vma->vm_flags, vma->vm_ops);
|
|
||||||
|
struct vm_area_struct *new_vma = NULL;
|
||||||
|
int ret = mm_create_vma(new_mms, vma->vm_start, map_size, vma->vm_flags, vma->vm_ops, &new_vma);
|
||||||
|
// 防止内存泄露
|
||||||
|
if (unlikely(ret == -EEXIST))
|
||||||
|
kfree((void *)va);
|
||||||
|
else
|
||||||
|
mm_map_vma(new_vma, virt_2_phys(va));
|
||||||
|
|
||||||
memcpy((void *)va, (void *)vma->vm_start, vma_size);
|
memcpy((void *)va, (void *)vma->vm_start, vma_size);
|
||||||
}
|
}
|
||||||
vma = vma->vm_next;
|
vma = vma->vm_next;
|
||||||
|
@ -17,114 +17,8 @@
|
|||||||
#include <filesystem/VFS/VFS.h>
|
#include <filesystem/VFS/VFS.h>
|
||||||
#include <common/wait_queue.h>
|
#include <common/wait_queue.h>
|
||||||
#include <mm/mm-types.h>
|
#include <mm/mm-types.h>
|
||||||
|
#include <arch/x86_64/current.h>
|
||||||
// 进程最大可拥有的文件描述符数量
|
#include "proc-types.h"
|
||||||
#define PROC_MAX_FD_NUM 16
|
|
||||||
|
|
||||||
// 进程的内核栈大小 32K
|
|
||||||
#define STACK_SIZE 32768
|
|
||||||
|
|
||||||
// 进程的运行状态
|
|
||||||
// 正在运行
|
|
||||||
#define PROC_RUNNING (1 << 0)
|
|
||||||
// 可被中断
|
|
||||||
#define PROC_INTERRUPTIBLE (1 << 1)
|
|
||||||
// 不可被中断
|
|
||||||
#define PROC_UNINTERRUPTIBLE (1 << 2)
|
|
||||||
// 挂起
|
|
||||||
#define PROC_ZOMBIE (1 << 3)
|
|
||||||
// 已停止
|
|
||||||
#define PROC_STOPPED (1 << 4)
|
|
||||||
|
|
||||||
// 内核代码段基地址
|
|
||||||
#define KERNEL_CS (0x08)
|
|
||||||
// 内核数据段基地址
|
|
||||||
#define KERNEL_DS (0x10)
|
|
||||||
// 用户代码段基地址
|
|
||||||
#define USER_CS (0x28)
|
|
||||||
// 用户数据段基地址
|
|
||||||
#define USER_DS (0x30)
|
|
||||||
|
|
||||||
// 进程初始化时的数据拷贝标志位
|
|
||||||
#define CLONE_FS (1 << 0) // 在进程间共享打开的文件
|
|
||||||
#define CLONE_SIGNAL (1 << 1)
|
|
||||||
#define CLONE_VM (1 << 2) // 在进程间共享虚拟内存空间
|
|
||||||
|
|
||||||
struct thread_struct
|
|
||||||
{
|
|
||||||
// 内核层栈基指针
|
|
||||||
ul rbp; // in tss rsp0
|
|
||||||
// 内核层代码指针
|
|
||||||
ul rip;
|
|
||||||
// 内核层栈指针
|
|
||||||
ul rsp;
|
|
||||||
|
|
||||||
ul fs, gs;
|
|
||||||
|
|
||||||
ul cr2;
|
|
||||||
// 异常号
|
|
||||||
ul trap_num;
|
|
||||||
// 错误码
|
|
||||||
ul err_code;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ========= pcb->flags =========
|
|
||||||
// 进程标志位
|
|
||||||
#define PF_KTHREAD (1UL << 0) // 内核线程
|
|
||||||
#define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
|
|
||||||
#define PF_VFORK (1UL << 2) // 标志进程是否由于vfork而存在资源共享
|
|
||||||
#define PF_KFORK (1UL << 3) // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 进程控制块
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct process_control_block
|
|
||||||
{
|
|
||||||
// 进程的状态
|
|
||||||
volatile long state;
|
|
||||||
// 进程标志:进程、线程、内核线程
|
|
||||||
unsigned long flags;
|
|
||||||
int64_t preempt_count; // 持有的自旋锁的数量
|
|
||||||
long signal;
|
|
||||||
long cpu_id; // 当前进程在哪个CPU核心上运行
|
|
||||||
// 内存空间分布结构体, 记录内存页表和程序段信息
|
|
||||||
struct mm_struct *mm;
|
|
||||||
|
|
||||||
// 进程切换时保存的状态信息
|
|
||||||
struct thread_struct *thread;
|
|
||||||
|
|
||||||
// 连接各个pcb的双向链表
|
|
||||||
struct List list;
|
|
||||||
|
|
||||||
// 地址空间范围
|
|
||||||
// 用户空间: 0x0000 0000 0000 0000 ~ 0x0000 7fff ffff ffff
|
|
||||||
// 内核空间: 0xffff 8000 0000 0000 ~ 0xffff ffff ffff ffff
|
|
||||||
uint64_t addr_limit;
|
|
||||||
|
|
||||||
long pid;
|
|
||||||
long priority; // 优先级
|
|
||||||
int64_t virtual_runtime; // 虚拟运行时间
|
|
||||||
|
|
||||||
// 进程拥有的文件描述符的指针数组
|
|
||||||
// todo: 改用动态指针数组
|
|
||||||
struct vfs_file_t *fds[PROC_MAX_FD_NUM];
|
|
||||||
|
|
||||||
// 链表中的下一个pcb
|
|
||||||
struct process_control_block *next_pcb;
|
|
||||||
// 父进程的pcb
|
|
||||||
struct process_control_block *parent_pcb;
|
|
||||||
|
|
||||||
int32_t exit_code; // 进程退出时的返回码
|
|
||||||
wait_queue_node_t wait_child_proc_exit; // 子进程退出等待队列
|
|
||||||
};
|
|
||||||
|
|
||||||
// 将进程的pcb和内核栈融合到一起,8字节对齐
|
|
||||||
union proc_union
|
|
||||||
{
|
|
||||||
struct process_control_block pcb;
|
|
||||||
ul stack[STACK_SIZE / sizeof(ul)];
|
|
||||||
} __attribute__((aligned(8)));
|
|
||||||
|
|
||||||
// 设置初始进程的PCB
|
// 设置初始进程的PCB
|
||||||
#define INITIAL_PROC(proc) \
|
#define INITIAL_PROC(proc) \
|
||||||
@ -151,25 +45,7 @@ union proc_union
|
|||||||
* @brief 任务状态段结构体
|
* @brief 任务状态段结构体
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct tss_struct
|
|
||||||
{
|
|
||||||
unsigned int reserved0;
|
|
||||||
ul rsp0;
|
|
||||||
ul rsp1;
|
|
||||||
ul rsp2;
|
|
||||||
ul reserved1;
|
|
||||||
ul ist1;
|
|
||||||
ul ist2;
|
|
||||||
ul ist3;
|
|
||||||
ul ist4;
|
|
||||||
ul ist5;
|
|
||||||
ul ist6;
|
|
||||||
ul ist7;
|
|
||||||
ul reserved2;
|
|
||||||
unsigned short reserved3;
|
|
||||||
// io位图基地址
|
|
||||||
unsigned short io_map_base_addr;
|
|
||||||
} __attribute__((packed)); // 使用packed表明是紧凑结构,编译器不会对成员变量进行字节对齐。
|
|
||||||
|
|
||||||
// 设置初始进程的tss
|
// 设置初始进程的tss
|
||||||
#define INITIAL_TSS \
|
#define INITIAL_TSS \
|
||||||
@ -191,22 +67,7 @@ struct tss_struct
|
|||||||
.io_map_base_addr = 0 \
|
.io_map_base_addr = 0 \
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC push_options
|
|
||||||
#pragma GCC optimize("O0")
|
|
||||||
// 获取当前的pcb
|
|
||||||
struct process_control_block *get_current_pcb()
|
|
||||||
{
|
|
||||||
struct process_control_block *current = NULL;
|
|
||||||
// 利用了当前pcb和栈空间总大小为32k大小对齐,将rsp低15位清空,即可获得pcb的起始地址
|
|
||||||
barrier();
|
|
||||||
__asm__ __volatile__("andq %%rsp, %0 \n\t"
|
|
||||||
: "=r"(current)
|
|
||||||
: "0"(~32767UL));
|
|
||||||
barrier();
|
|
||||||
return current;
|
|
||||||
};
|
|
||||||
#pragma GCC pop_options
|
|
||||||
#define current_pcb get_current_pcb()
|
|
||||||
|
|
||||||
#define GET_CURRENT_PCB \
|
#define GET_CURRENT_PCB \
|
||||||
"movq %rsp, %rbx \n\t" \
|
"movq %rsp, %rbx \n\t" \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user