diff --git a/.vscode/settings.json b/.vscode/settings.json index c84e9508..1930ef11 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -110,7 +110,9 @@ "boot_info.h": "c", "pci.h": "c", "time.h": "c", - "ia64_msi.h": "c" + "ia64_msi.h": "c", + "errno.h": "c", + "bug.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/kernel/Makefile b/kernel/Makefile index 9d11f6b2..390d5dca 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -18,7 +18,7 @@ LD_LIST := head.o OBJ_LIST := head.o -kernel_subdirs := common driver process debug filesystem time arch exception mm smp sched syscall +kernel_subdirs := common driver process debug filesystem time arch exception mm smp sched syscall ktest @@ -47,7 +47,7 @@ all: kernel # 重新链接 echo "Re-Linking kernel..." - ld -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") -T link.lds + ld -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ./debug/kallsyms.o -T link.lds echo "Generating kernel ELF file..." # 生成内核文件 objcopy -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../bin/kernel/kernel.elf diff --git a/kernel/common/Makefile b/kernel/common/Makefile index 038476a5..af3636ec 100644 --- a/kernel/common/Makefile +++ b/kernel/common/Makefile @@ -3,7 +3,7 @@ CFLAGS += -I . kernel_common_subdirs:=libELF math -all: glib.o printk.o cpu.o +all: glib.o printk.o cpu.o bitree.o @list='$(kernel_common_subdirs)'; for subdir in $$list; do \ echo "make all in $$subdir";\ cd $$subdir;\ @@ -18,4 +18,7 @@ printk.o: printk.c gcc $(CFLAGS) -c printk.c -o printk.o cpu.o: cpu.c - gcc $(CFLAGS) -c cpu.c -o cpu.o \ No newline at end of file + gcc $(CFLAGS) -c cpu.c -o cpu.o + +bitree.o: bitree.c + gcc $(CFLAGS) -c bitree.c -o bitree.o \ No newline at end of file diff --git a/kernel/common/bitree.c b/kernel/common/bitree.c new file mode 100644 index 00000000..224c6b51 --- /dev/null +++ b/kernel/common/bitree.c @@ -0,0 +1,206 @@ +#include "bitree.h" +#include +#include +#include + +#define smaller(root, a, b) (root->cmp((a)->value, (b)->value) == -1) +#define equal(root, a, b) (root->cmp((a)->value, (b)->value) == 0) +#define greater(root, a, b) (root->cmp((a)->value, (b)->value) == 1) + +/** + * @brief 创建二叉搜索树 + * + * @param node 根节点 + * @param cmp 比较函数 + * @param release 用来释放结点的value的函数 + * @return struct bt_root_t* 树根结构体 + */ +struct bt_root_t *bt_create_tree(struct bt_node_t *node, int (*cmp)(void *a, void *b), int (*release)(void *value)) +{ + if (node == NULL || cmp == NULL) + return -EINVAL; + + struct bt_root_t *root = (struct bt_root_t *)kmalloc(sizeof(struct bt_root_t), 0); + memset((void *)root, 0, sizeof(struct bt_root_t)); + root->bt_node = node; + root->cmp = cmp; + root->release = release; + root->size = (node == NULL) ? 0 : 1; + + return root; +} + +/** + * @brief 创建结点 + * + * @param left 左子节点 + * @param right 右子节点 + * @param value 当前节点的值 + * @return struct bt_node_t* + */ +struct bt_node_t *bt_create_node(struct bt_node_t *left, struct bt_node_t *right, struct bt_node_t *parent, void *value) +{ + struct bt_node_t *node = (struct bt_node_t *)kmalloc(sizeof(struct bt_node_t), 0); + FAIL_ON_TO(node == NULL, nomem); + memset((void *)node, 0, sizeof(struct bt_node_t)); + + node->left = left; + node->right = right; + node->value = value; + node->parent = parent; + + return node; +nomem:; + return -ENOMEM; +} +/** + * @brief 插入结点 + * + * @param root 树根结点 + * @param value 待插入结点的值 + * @return int 返回码 + */ +int bt_insert(struct bt_root_t *root, void *value) +{ + if (root == NULL) + return -EINVAL; + + struct bt_node_t *this_node = root->bt_node; + struct bt_node_t *last_node = NULL; + struct bt_node_t *insert_node = bt_create_node(NULL, NULL, NULL, value); + FAIL_ON_TO((uint64_t)insert_node == (uint64_t)(-ENOMEM), failed); + + while (this_node != NULL) + { + last_node = this_node; + if (smaller(root, insert_node, this_node)) + this_node = this_node->left; + else + this_node = this_node->right; + } + + insert_node->parent = last_node; + if (unlikely(last_node == NULL)) + root->bt_node = insert_node; + else + { + if (smaller(root, insert_node, last_node)) + last_node->left = insert_node; + else + last_node->right = insert_node; + } + ++root->size; + return 0; + +failed:; + return -ENOMEM; +} + +/** + * @brief 搜索值为value的结点 + * + * @param value 值 + * @param ret_addr 返回的结点基地址 + * @return int 错误码 + */ +int bt_query(struct bt_root_t *root, void *value, uint64_t *ret_addr) +{ + struct bt_node_t *this_node = root->bt_node; + struct bt_node_t tmp_node = {0}; + tmp_node.value = value; + + // 如果返回地址为0 + if (ret_addr == NULL) + return -EINVAL; + + while (this_node != NULL && !equal(root, this_node, &tmp_node)) + { + if (smaller(root, &tmp_node, this_node)) + this_node = this_node->left; + else + this_node = this_node->right; + } + + if (this_node != NULL && equal(root, this_node, &tmp_node)) + { + *ret_addr = (uint64_t)this_node; + return 0; + } + else + { + // 找不到则返回-1,且addr设为0 + *ret_addr = NULL; + return -1; + } +} + +static struct bt_node_t *bt_get_minimum(struct bt_node_t *this_node) +{ + while (this_node->left != NULL) + this_node = this_node->left; + return this_node; +} + +/** + * @brief 删除结点 + * + * @param root 树根 + * @param value 待删除结点的值 + * @return int 返回码 + */ +int bt_delete(struct bt_root_t *root, void *value) +{ + uint64_t tmp_addr; + int retval; + + // 寻找待删除结点 + retval = bt_query(root, value, &tmp_addr); + if (retval != 0 || tmp_addr == NULL) + return retval; + + struct bt_node_t *this_node = (struct bt_node_t *)tmp_addr; + struct bt_node_t *to_delete = NULL, *to_delete_son = NULL; + if (this_node->left == NULL || this_node->right == NULL) + to_delete = this_node; + else + { + to_delete = bt_get_minimum(this_node->right); + // 释放要被删除的值,并把下一个结点的值替换上来 + root->release(this_node->value); + this_node->value = to_delete->value; + } + + if (to_delete->left != NULL) + to_delete_son = to_delete->left; + else + to_delete_son = to_delete->right; + + if (to_delete_son != NULL) + to_delete_son->parent = to_delete->parent; + + if (to_delete->parent == NULL) + root->bt_node = to_delete_son; + else + { + if (to_delete->parent->left == to_delete) + to_delete->parent->left = to_delete_son; + else + to_delete->parent->right = to_delete_son; + } + + --root->size; + // 释放最终要删除的结点的对象 + kfree(to_delete); +} + +/** + * @brief 释放整个二叉搜索树 + * + * @param root 树的根节点 + * @return int 错误码 + */ +int bt_destroy_tree(struct bt_root_t *root) +{ + // todo: 待kfifo完成后,使用kfifo队列来辅助destroy + return -1; +} \ No newline at end of file diff --git a/kernel/common/bitree.h b/kernel/common/bitree.h new file mode 100644 index 00000000..0d98b337 --- /dev/null +++ b/kernel/common/bitree.h @@ -0,0 +1,79 @@ +#pragma once +#include + +struct bt_node_t +{ + struct bt_node_t *left; + struct bt_node_t *right; + struct bt_node_t *parent; + void *value; // 数据 + +} __attribute__((aligned(sizeof(long)))); + +struct bt_root_t +{ + struct bt_node_t *bt_node; + int32_t size; // 树中的元素个数 + int (*cmp)(void *a, void *b); // 比较函数 a>b 返回1, a==b返回0, a #include -spinlock_t xhci_controller_init_lock; // xhci控制器初始化锁(在usb_init中被初始化) +spinlock_t xhci_controller_init_lock = {0}; // xhci控制器初始化锁(在usb_init中被初始化) static int xhci_ctrl_count = 0; // xhci控制器计数 @@ -123,13 +123,6 @@ hardware_intr_controller xhci_hc_intr_controller = ptr->cycle = 1; \ } while (0) -#define FAIL_ON(value, to) \ - do \ - { \ - if (unlikely(value != 0)) \ - goto to; \ - } while (0) - // Common TRB types enum { @@ -387,7 +380,7 @@ static int xhci_hc_pair_ports(int id) uint32_t next_off = xhci_hc[id].ext_caps_off; uint32_t offset, cnt; - uint16_t protocol_flags; + uint16_t protocol_flags = 0; // 寻找所有的usb2端口 while (next_off) @@ -560,12 +553,12 @@ uint64_t xhci_hc_irq_install(uint64_t irq_num, void *arg) struct msi_desc_t msi_desc; memset(&msi_desc, 0, sizeof(struct msi_desc_t)); - msi_desc.pci_dev = (struct pci_device_structure_header_t*)xhci_hc[cid].pci_dev_hdr; + msi_desc.pci_dev = (struct pci_device_structure_header_t *)xhci_hc[cid].pci_dev_hdr; msi_desc.assert = info->assert; msi_desc.edge_trigger = info->edge_trigger; msi_desc.processor = info->processor; msi_desc.pci.msi_attribute.is_64 = 1; - // todo: QEMU是使用msix的,因此要先在pci中实现msix + // todo: QEMU是使用msix的,因此要先在pci中实现msix int retval = pci_enable_msi(&msi_desc); kdebug("pci retval = %d", retval); kdebug("xhci irq %d installed.", irq_num); @@ -643,7 +636,7 @@ static int xhci_reset_port(const int id, const int port) break; else if (val & (1 << 21)) break; - + --timeout; usleep(500); } @@ -854,12 +847,12 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr) } // 关闭legacy支持 - FAIL_ON(xhci_hc_stop_legacy(cid), failed); + FAIL_ON_TO(xhci_hc_stop_legacy(cid), failed); // 重置xhci控制器 - FAIL_ON(xhci_hc_reset(cid), failed); + FAIL_ON_TO(xhci_hc_reset(cid), failed); // 端口配对 - FAIL_ON(xhci_hc_pair_ports(cid), failed); + FAIL_ON_TO(xhci_hc_pair_ports(cid), failed); // ========== 设置USB host controller ========= // 获取页面大小 @@ -900,7 +893,7 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr) // 写入设备通知控制寄存器 xhci_write_op_reg32(cid, XHCI_OPS_DNCTRL, (1 << 1)); // 目前只有N1被支持 - FAIL_ON(xhci_hc_init_intr(cid), failed_free_dyn); + FAIL_ON_TO(xhci_hc_init_intr(cid), failed_free_dyn); ++xhci_ctrl_count; spin_unlock(&xhci_controller_init_lock); return; diff --git a/kernel/ktest/Makefile b/kernel/ktest/Makefile new file mode 100644 index 00000000..dce56893 --- /dev/null +++ b/kernel/ktest/Makefile @@ -0,0 +1,8 @@ + +CFLAGS += -I . + + +all: bitree.o + +bitree.o: test-bitree.c + gcc $(CFLAGS) -c test-bitree.c -o test-bitree.o \ No newline at end of file diff --git a/kernel/ktest/ktest.h b/kernel/ktest/ktest.h new file mode 100644 index 00000000..a2be05fb --- /dev/null +++ b/kernel/ktest/ktest.h @@ -0,0 +1,4 @@ +#pragma once +#include + +uint64_t ktest_test_bitree(uint64_t arg); \ No newline at end of file diff --git a/kernel/ktest/ktest_utils.h b/kernel/ktest/ktest_utils.h new file mode 100644 index 00000000..b186b6f3 --- /dev/null +++ b/kernel/ktest/ktest_utils.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#define assert(condition) ({ \ + int __condition = !!(condition); \ + if (unlikely(!(__condition))) \ + { \ + printk("[ kTEST FAILED ] Ktest Assertion Failed, file:%s, Line:%d\n", __FILE__, __LINE__); \ + } \ + likely(__condition); \ +}) + +#define kTEST(...) \ + do \ + { \ + printk("[ kTEST ] file:%s, Line:%d\t", __FILE__, __LINE__); \ + printk(__VA_ARGS__); \ + printk("\n"); \ + } while (0); + +/** + * @brief 测试用例函数表 + * + */ +typedef long (*ktest_case_table)(uint64_t arg0, uint64_t arg1); \ No newline at end of file diff --git a/kernel/ktest/test-bitree.c b/kernel/ktest/test-bitree.c new file mode 100644 index 00000000..84d83a74 --- /dev/null +++ b/kernel/ktest/test-bitree.c @@ -0,0 +1,132 @@ +#include "ktest.h" +#include + +#include +#include +#include +#include + +#include + +struct test_value_t +{ + uint64_t tv; +}; +static int compare(void *a, void *b) +{ + if (((struct test_value_t *)a)->tv > ((struct test_value_t *)b)->tv) + return 1; + else if (((struct test_value_t *)a)->tv == ((struct test_value_t *)b)->tv) + return 0; + else + return -1; +} + +static int release(void *value) +{ + // kdebug("release"); +} + +/** + * @brief 测试创建二叉树 + * + * @return int + */ +static long ktest_bitree_case1(uint64_t arg0, uint64_t arg1) +{ + int val; + // ========== 测试创建树 + struct test_value_t *tv1 = (struct test_value_t *)kmalloc(sizeof(struct test_value_t), 0); + tv1->tv = 20; + struct bt_node_t *rn = bt_create_node(NULL, NULL, NULL, tv1); + + assert(rn != NULL); + assert((int64_t)rn != (-EINVAL)); + assert(rn->value == tv1); + + struct bt_root_t *tree = bt_create_tree(rn, compare, release); + assert(tree != NULL); + assert(tree->bt_node == rn); + assert(tree->cmp == compare); + assert(tree->release == release); + assert(tree->size == 1); + + // ========= 向树中插入数据10、30 + struct test_value_t *tv2 = (struct test_value_t *)kmalloc(sizeof(struct test_value_t), 0); + assert(tv2 != NULL); + tv2->tv = 10; + { + int last_size = tree->size; + val = bt_insert(tree, tv2); + assert(val == 0); + assert(last_size + 1 == tree->size); + } + struct test_value_t *tv3 = (struct test_value_t *)kmalloc(sizeof(struct test_value_t), 0); + assert(tv3 != NULL); + tv3->tv = 30; + { + int last_size = tree->size; + val = bt_insert(tree, tv3); + assert(val == 0); + assert(last_size + 1 == tree->size); + } + + // 检测树的形状 + assert(((struct test_value_t *)tree->bt_node->left->value)->tv == tv2->tv); + assert(((struct test_value_t *)tree->bt_node->right->value)->tv == tv3->tv); + + // ========= 查询结点 + // 查询值为tv2的结点 + struct bt_node_t *node2; + assert(bt_query(tree, tv2, (uint64_t*)(&node2)) == 0); + assert(node2 != NULL); + assert(node2->value == tv2); + + // ========= 插入第4个结点:15 + struct test_value_t *tv4 = (struct test_value_t *)kmalloc(sizeof(struct test_value_t), 0); + assert(tv4 != NULL); + tv4->tv = 15; + { + int last_size = tree->size; + val = bt_insert(tree, tv4); + assert(val == 0); + assert(last_size + 1 == tree->size); + } + + assert(((struct test_value_t *)node2->right->value)->tv == tv4->tv); + + // ======= 查询不存在的值 + struct bt_node_t *node_not_exists; + struct test_value_t *tv_not_exists = (struct test_value_t *)kmalloc(sizeof(struct test_value_t), 0); + assert(tv_not_exists != NULL); + tv_not_exists->tv = 100; + assert(bt_query(tree, tv_not_exists, (uint64_t*)(&node_not_exists)) == -1); + // kdebug("node_not_exists.val=%d", ((struct test_value_t*)node_not_exists->value)->tv); + assert(node_not_exists == NULL); + + // 删除根节点 + assert(bt_delete(tree, rn->value) == 0); + assert(((struct test_value_t *)tree->bt_node->value)->tv != 20); + assert(tree->bt_node->right == NULL); + + // 删除树 + assert(bt_destroy_tree(tree) == 0); + + return 0; +} + +static ktest_case_table kt_bitree_func_table[] = { + ktest_bitree_case1, +}; + +uint64_t ktest_test_bitree(uint64_t arg) +{ + kTEST("Testing bitree..."); + for (int i = 0; i < sizeof(kt_bitree_func_table) / sizeof(ktest_case_table); ++i) + { + kTEST("Testing case %d", i); + kt_bitree_func_table[i](0, 0); + } + kdebug("bitree Test done."); + return 0; +} \ No newline at end of file diff --git a/kernel/mm/mm.c b/kernel/mm/mm.c index a487729c..a3d4cf6a 100644 --- a/kernel/mm/mm.c +++ b/kernel/mm/mm.c @@ -641,7 +641,7 @@ int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_s { if (unlikely(*pde_ptr != 0 && user)) { - kwarn("page already mapped!"); + // kwarn("page already mapped!"); // 如果是用户态可访问的页,则释放当前新获取的物理页 if (likely(((ul)phys_addr_start + length_mapped) < total_2M_pages)) // 校验是否为内存中的物理页 free_pages(Phy_to_2M_Page((ul)phys_addr_start + length_mapped), 1); diff --git a/kernel/process/process.c b/kernel/process/process.c index 89d9b767..205565b4 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -15,6 +15,7 @@ #include #include +#include spinlock_t process_global_pid_write_lock; // 增加pid的写锁 long process_global_pid = 1; // 系统中最大的pid @@ -385,7 +386,7 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[]) regs->rdi = argc; regs->rsi = (uint64_t)dst_argv; } - kdebug("execve ok"); + // kdebug("execve ok"); regs->cs = USER_CS | 3; regs->ds = USER_DS | 3; @@ -413,7 +414,8 @@ ul initial_kernel_thread(ul arg) fat32_init(); usb_init(); - + pid_t test_thread_pid = kernel_thread(ktest_test_bitree, 1, 0); + kdebug("test_thread_pid=%d", test_thread_pid); // 准备切换到用户态 struct pt_regs *regs; @@ -569,7 +571,7 @@ void process_init() spin_init(&process_global_pid_write_lock); // 初始化进程的循环链表 list_init(&initial_proc_union.pcb.list); - kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_SIGNAL); // 初始化内核进程 + kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_SIGNAL); // 初始化内核线程 initial_proc_union.pcb.state = PROC_RUNNING; initial_proc_union.pcb.preempt_count = 0; initial_proc_union.pcb.cpu_id = 0; @@ -586,7 +588,6 @@ void process_init() * @param stack_size 堆栈大小 * @return unsigned long */ - unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size) { int retval = 0; @@ -642,6 +643,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned if (process_copy_flags(clone_flags, tsk)) goto copy_flags_failed; + kdebug("before copy mm"); // 拷贝内存空间分布结构体 if (process_copy_mm(clone_flags, tsk)) goto copy_mm_failed; diff --git a/kernel/process/process.h b/kernel/process/process.h index 61b2f13a..61f7f110 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -326,6 +326,17 @@ ul process_do_exit(ul code); */ void process_exit_notify(); +/** + * @brief 初始化内核进程 + * + * @param fn 目标程序的地址 + * @param arg 向目标程序传入的参数 + * @param flags + * @return int + */ + +int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigned long flags); + /** * @brief 切换页表 * @param prev 前一个进程的pcb