diff --git a/kernel/src/Makefile b/kernel/src/Makefile index e61d2da5..bb60001a 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -17,7 +17,7 @@ export ASFLAGS := --64 LD_LIST := head.o -kernel_subdirs := common driver process debug filesystem time arch exception mm smp sched syscall ktest libs ipc +kernel_subdirs := common driver process debug filesystem time arch exception mm smp sched syscall ktest libs ipc io diff --git a/kernel/src/arch/x86_64/cpu.rs b/kernel/src/arch/x86_64/cpu.rs index 89f48387..b6260cca 100644 --- a/kernel/src/arch/x86_64/cpu.rs +++ b/kernel/src/arch/x86_64/cpu.rs @@ -2,17 +2,17 @@ use core::arch::asm; /// @brief 获取当前cpu的apic id #[inline] -pub fn arch_current_apic_id() -> u8 { +pub fn current_cpu_id() -> u8 { let cpuid_res: u32; unsafe { asm!( "mov eax, 1", "cpuid", - "mov r15, ebx", + "mov r15, rbx", lateout("r15") cpuid_res ); } - return (cpuid_res >> 24) as u8; + return ((cpuid_res >> 24) & 0xff) as u8; } /// @brief 通过pause指令,让cpu休息一会儿。降低空转功耗 diff --git a/kernel/src/common/blk_types.h b/kernel/src/common/blk_types.h index 59fda4e8..b1c1cc4b 100644 --- a/kernel/src/common/blk_types.h +++ b/kernel/src/common/blk_types.h @@ -40,11 +40,8 @@ struct block_device_request_packet uint64_t LBA_start; uint32_t count; uint64_t buffer_vaddr; - uint8_t device_type; // 0: ahci void (*end_handler)(ul num, ul arg); - - wait_queue_node_t wait_queue; }; /** @@ -53,7 +50,6 @@ struct block_device_request_packet */ struct block_device_request_queue { - wait_queue_node_t wait_queue_list; struct block_device_request_packet *in_service; // 正在请求的结点 ul request_count; }; @@ -64,13 +60,12 @@ struct block_device_request_queue */ struct block_device { - sector_t bd_start_sector; // 该分区的起始扇区 - uint64_t bd_start_LBA; // 起始LBA号 - sector_t bd_sectors_num; // 该分区的扇区数 - struct vfs_superblock_t *bd_superblock; // 执行超级块的指针 - struct blk_gendisk *bd_disk; // 当前分区所属的磁盘 - struct block_device_request_queue *bd_queue; // 请求队列 - uint16_t bd_partno; // 在磁盘上的分区号 + sector_t bd_start_sector; // 该分区的起始扇区 + uint64_t bd_start_LBA; // 起始LBA号 + sector_t bd_sectors_num; // 该分区的扇区数 + struct vfs_superblock_t *bd_superblock; // 执行超级块的指针 + struct blk_gendisk *bd_disk; // 当前分区所属的磁盘 + uint16_t bd_partno; // 在磁盘上的分区号 }; // 定义blk_gendisk中的标志位 @@ -85,10 +80,8 @@ struct blk_gendisk char disk_name[DISK_NAME_LEN]; // 磁盘驱动器名称 uint16_t part_cnt; // 磁盘分区计数 uint16_t flags; - struct block_device *partition; // 磁盘分区数组 - const struct block_device_operation *fops; // 磁盘操作 - struct block_device_request_queue *request_queue; // 磁盘请求队列 + struct block_device *partition; // 磁盘分区数组 + const struct block_device_operation *fops; // 磁盘操作 void *private_data; - mutex_t open_mutex; // open()/close()操作的互斥锁 }; \ No newline at end of file diff --git a/kernel/src/common/completion.h b/kernel/src/common/completion.h index dfc2937f..0cf58118 100644 --- a/kernel/src/common/completion.h +++ b/kernel/src/common/completion.h @@ -30,7 +30,7 @@ long wait_for_completion_interruptible_timeout(struct completion *x, long timeou void wait_for_multicompletion(struct completion x[], int n); bool try_wait_for_completion(struct completion *x); bool completion_done(struct completion *x); - +struct completion *completion_alloc(); /** * 测试函数声明 (测试代码辅助函数) */ diff --git a/kernel/src/common/kthread.h b/kernel/src/common/kthread.h index 30dba8ca..37d8961d 100644 --- a/kernel/src/common/kthread.h +++ b/kernel/src/common/kthread.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include /** @@ -21,9 +21,7 @@ struct kthread_info_t char *full_name; // 内核线程的名称 }; -struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data), - void *data, - int node, +struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data), void *data, int node, const char name_fmt[], ...); /** * @brief 在当前结点上创建一个内核线程 @@ -35,12 +33,12 @@ struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data * * 请注意,该宏会创建一个内核线程,并将其设置为停止状态 */ -#define kthread_create(thread_fn, data, name_fmt, arg...) \ +#define kthread_create(thread_fn, data, name_fmt, arg...) \ kthread_create_on_node(thread_fn, data, NUMA_NO_NODE, name_fmt, ##arg) /** * @brief 创建内核线程,并将其唤醒 - * + * * @param thread_fn 该内核线程要执行的函数 * @param data 传递给 thread_fn 的参数数据 * @param name_fmt printf-style format string for the thread name @@ -56,32 +54,34 @@ struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data /** * @brief 创建内核实时线程,并将其唤醒 - * + * * @param thread_fn 该内核线程要执行的函数 * @param data 传递给 thread_fn 的参数数据 * @param name_fmt printf-style format string for the thread name * @param arg name_fmt的参数 */ -#define kthread_run_rt(thread_fn, data, name_fmt, ...) \ - ({ \ - struct process_control_block *__kt = kthread_create(thread_fn, data, name_fmt, ##__VA_ARGS__); \ - __kt=process_init_rt_pcb(__kt); \ - if (!IS_ERR(__kt)){ \ - process_wakeup(__kt);} \ - __kt; \ +#define kthread_run_rt(thread_fn, data, name_fmt, ...) \ + ({ \ + struct process_control_block *__kt = kthread_create(thread_fn, data, name_fmt, ##__VA_ARGS__); \ + __kt = process_init_rt_pcb(__kt); \ + if (!IS_ERR(__kt)) \ + { \ + process_wakeup(__kt); \ + } \ + __kt; \ }) /** * @brief 向kthread发送停止信号,请求其结束 - * + * * @param pcb 内核线程的pcb * @return int 错误码 */ -int kthread_stop(struct process_control_block * pcb); +int kthread_stop(struct process_control_block *pcb); /** * @brief 内核线程调用该函数,检查自身的标志位,判断自己是否应该执行完任务后退出 - * + * * @return true 内核线程应该退出 * @return false 无需退出 */ @@ -89,14 +89,14 @@ bool kthread_should_stop(void); /** * @brief 让当前内核线程退出,并返回result参数给kthread_stop()函数 - * + * * @param result 返回值 */ void kthread_exit(long result); /** * @brief 初始化kthread机制(只应被process_init调用) - * + * * @return int 错误码 */ int kthread_mechanism_init(); @@ -119,7 +119,7 @@ struct kthread_info_t *to_kthread(struct process_control_block *pcb); /** * @brief 释放pcb指向的worker private - * + * * @param pcb 要释放的pcb */ void free_kthread_struct(struct process_control_block *pcb); \ No newline at end of file diff --git a/kernel/src/driver/disk/ahci/ahci.c b/kernel/src/driver/disk/ahci/ahci.c index e3e1e0fd..3f50a45a 100644 --- a/kernel/src/driver/disk/ahci/ahci.c +++ b/kernel/src/driver/disk/ahci/ahci.c @@ -8,11 +8,10 @@ #include #include #include +#include struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES]; -struct block_device_request_queue ahci_req_queue; - struct blk_gendisk ahci_gendisk0 = {0}; // 暂时硬性指定一个ahci_device static int __first_port = -1; // 临时用于存储 ahci控制器的第一个可用端口 的变量 @@ -24,10 +23,6 @@ static uint64_t ahci_port_base_phys_addr; // 端口映射的物理基地址(ah static void start_cmd(HBA_PORT *port); static void stop_cmd(HBA_PORT *port); static void port_rebase(HBA_PORT *port, int portno); -static long ahci_query_disk(); - -// Find a free command list slot -static int ahci_find_cmdslot(HBA_PORT *port); // 计算HBA_MEM的虚拟内存地址 #define cal_HBA_MEM_VIRT_ADDR(device_num) (AHCI_MAPPING_BASE + (ul)(((struct pci_device_structure_general_device_t *)(ahci_devs[device_num]))->BAR5 - ((((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5) & PAGE_2M_MASK))) @@ -92,7 +87,7 @@ static int ahci_init_gendisk() ahci_gendisk0.flags = BLK_GF_AHCI; ahci_gendisk0.fops = &ahci_operation; mutex_init(&ahci_gendisk0.open_mutex); - ahci_gendisk0.request_queue = &ahci_req_queue; + // 为存储分区结构,分配内存空间 ahci_gendisk0.private_data = __alloc_private_data(); // 读取分区表 @@ -127,7 +122,7 @@ static int ahci_init_gendisk() // 初始化分区结构体 ahci_gendisk0.partition[cnt].bd_disk = &ahci_gendisk0; ahci_gendisk0.partition[cnt].bd_partno = cnt; - ahci_gendisk0.partition[cnt].bd_queue = &ahci_req_queue; + // FIXME 需要注释 ahci_gendisk0.partition[cnt].bd_sectors_num = ptable->DPTE[i].total_sectors; ahci_gendisk0.partition[cnt].bd_start_sector = ptable->DPTE[i].starting_sector; ahci_gendisk0.partition[cnt].bd_superblock = NULL; // 挂载文件系统时才会初始化superblock @@ -175,11 +170,6 @@ void ahci_init() kdebug("ahci_port_base_vaddr=%#018lx", ahci_port_base_vaddr); ahci_probe_port(0); - // 初始化请求队列 - ahci_req_queue.in_service = NULL; - wait_queue_init(&ahci_req_queue.wait_queue_list, NULL); - ahci_req_queue.request_count = 0; - BUG_ON(ahci_init_gendisk() != 0); kinfo("AHCI initialized."); } @@ -333,17 +323,23 @@ static void port_rebase(HBA_PORT *port, int portno) * @param starth high 32bits of start addr * @param count total sectors to read * @param buf buffer + * @param ret_slot 执行命令的插槽号(传出参数) * @return true done * @return false failed */ -static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, uint64_t buf) +static int ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, uint64_t buf, int8_t *ret_slot) { port->is = (uint32_t)-1; // Clear pending interrupt bits - int spin = 0; // Spin lock timeout counter + + int spin = 0; // Spin lock timeout counter int slot = ahci_find_cmdslot(port); if (slot == -1) return E_NOEMPTYSLOT; + if (ret_slot) + { + *ret_slot = slot; + } HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb); cmdheader += slot; @@ -402,43 +398,59 @@ static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t port->ci = 1 << slot; // Issue command - current_pcb->flags |= PF_NEED_SCHED; + return 0; +} - int retval = AHCI_SUCCESS; - // Wait for completion - while (1) - { - // In some longer duration reads, it may be helpful to spin on the DPS bit - // in the PxIS port field as well (1 << 5) - if ((port->ci & (1 << slot)) == 0) - break; - if (port->is & HBA_PxIS_TFES) // Task file error - { - kerror("Read disk error"); - retval = E_TASK_FILE_ERROR; - break; - } - } +/** + * @brief 检查请求包是否已完成 + * + * @param port_num HBA PORT 编号 + * @param ahci_ctrl_num ahci控制号 + * @param ret_slot 执行命令的插槽号 + * @param err 错误信息 + */ +int ahci_check_complete(uint8_t port_num, uint8_t ahci_ctrl_num, int8_t slot, char *err) +{ - // Check again - if (port->is & HBA_PxIS_TFES) + HBA_PORT *port = ahci_get_port(port_num, ahci_ctrl_num); + int retval = -EBUSY; + if (slot == -1) + retval = -EINVAL; + // In some longer duration reads, it may be helpful to spin on the DPS bit + // in the PxIS port field as well (1 << 5) + if ((port->ci & (1 << slot)) == 0) + retval = 0; + if (port->is & HBA_PxIS_TFES) // Task file error { - kerror("Read disk error"); + if (err != NULL) + kerror(*err); retval = E_TASK_FILE_ERROR; } - enter_syscall_int(SYS_AHCI_END_REQ, 0, 0, 0, 0, 0, 0, 0, 0); return retval; } -static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, - uint64_t buf) +/** + * @brief write data to SATA device using 48bit LBA address + * + * @param port HBA PORT + * @param startl low 32bits of start addr + * @param starth high 32bits of start addr + * @param count total sectors to read + * @param buf buffer + * @param ret_slot 执行命令的插槽号(传出参数) + * @return success 0 + */ +static int ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, + uint64_t buf, int8_t *ret_slot) { - // kdebug("ahci write"); port->is = 0xffff; // Clear pending interrupt bits int slot = ahci_find_cmdslot(port); if (slot == -1) return E_NOEMPTYSLOT; - + if (ret_slot) + { + *ret_slot = slot; + } HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb); cmdheader += slot; @@ -479,37 +491,13 @@ static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_ cmdfis->countl = count & 0xff; cmdfis->counth = count >> 8; - // printk("[slot]{%d}", slot); port->ci = 1; // Issue command - current_pcb->flags |= PF_NEED_SCHED; - int retval = AHCI_SUCCESS; - - while (1) - { - // In some longer duration reads, it may be helpful to spin on the DPS bit - // in the PxIS port field as well (1 << 5) - if ((port->ci & (1 << slot)) == 0) - break; - if (port->is & HBA_PxIS_TFES) - { // Task file error - kerror("Write disk error"); - retval = E_TASK_FILE_ERROR; - break; - } - } - if (port->is & HBA_PxIS_TFES) - { - kerror("Write disk error"); - retval = E_TASK_FILE_ERROR; - } - // kdebug("ahci write retval=%d", retval); - enter_syscall_int(SYS_AHCI_END_REQ, 0, 0, 0, 0, 0, 0, 0, 0); - return retval; + return 0; } // Find a free command list slot -static int ahci_find_cmdslot(HBA_PORT *port) +int ahci_find_cmdslot(HBA_PORT *port) { // If not set in SACT and CI, the slot is free uint32_t slots = (port->sact | port->ci); @@ -547,9 +535,7 @@ long ahci_close() */ static struct ahci_request_packet_t *ahci_make_request(long cmd, uint64_t base_addr, uint64_t count, uint64_t buffer, uint8_t ahci_ctrl_num, uint8_t port_num) { - struct ahci_request_packet_t *pack = (struct ahci_request_packet_t *)kmalloc(sizeof(struct ahci_request_packet_t), 0); - - wait_queue_init(&pack->blk_pak.wait_queue, current_pcb); + struct ahci_request_packet_t *pack = (struct ahci_request_packet_t *)kzalloc(sizeof(struct ahci_request_packet_t), 0); pack->blk_pak.device_type = BLK_TYPE_AHCI; // 由于ahci不需要中断即可读取磁盘,因此end handler为空 @@ -572,72 +558,32 @@ static struct ahci_request_packet_t *ahci_make_request(long cmd, uint64_t base_a pack->blk_pak.LBA_start = base_addr; pack->blk_pak.count = count; pack->blk_pak.buffer_vaddr = buffer; - pack->ahci_ctrl_num = ahci_ctrl_num; pack->port_num = port_num; return pack; } -/** - * @brief 结束磁盘请求 - * - */ -void ahci_end_request() +long ahci_query_disk(struct ahci_request_packet_t *pack, int8_t *ret_slot) { - ahci_req_queue.in_service->wait_queue.pcb->state = PROC_RUNNING; - // ahci_req_queue.in_service->wait_queue.pcb->flags |= PF_NEED_SCHED; - // current_pcb->flags |= PF_NEED_SCHED; - kfree((uint64_t *)ahci_req_queue.in_service); - ahci_req_queue.in_service = NULL; - // 进行下一轮的磁盘请求 (由于未实现单独的io调度器,这里会造成长时间的io等待) - if (ahci_req_queue.request_count > 0) - ahci_query_disk(); -} - -static long ahci_query_disk() -{ - wait_queue_node_t *wait_queue_tmp = container_of(list_next(&ahci_req_queue.wait_queue_list.wait_list), wait_queue_node_t, wait_list); - struct ahci_request_packet_t *pack = (struct ahci_request_packet_t *)container_of(wait_queue_tmp, struct block_device_request_packet, wait_queue); - - ahci_req_queue.in_service = (struct block_device_request_packet *)pack; - list_del(&(ahci_req_queue.in_service->wait_queue.wait_list)); - --ahci_req_queue.request_count; - // kdebug("ahci_query_disk"); long ret_val = 0; - switch (pack->blk_pak.cmd) { case AHCI_CMD_READ_DMA_EXT: - ret_val = ahci_read(&(ahci_devices[pack->ahci_ctrl_num].hba_mem->ports[pack->port_num]), pack->blk_pak.LBA_start & 0xFFFFFFFF, ((pack->blk_pak.LBA_start) >> 32) & 0xFFFFFFFF, pack->blk_pak.count, pack->blk_pak.buffer_vaddr); + ret_val = ahci_read(&(ahci_devices[pack->ahci_ctrl_num].hba_mem->ports[pack->port_num]), pack->blk_pak.LBA_start & 0xFFFFFFFF, ((pack->blk_pak.LBA_start) >> 32) & 0xFFFFFFFF, pack->blk_pak.count, pack->blk_pak.buffer_vaddr, ret_slot); break; case AHCI_CMD_WRITE_DMA_EXT: - ret_val = ahci_write(&(ahci_devices[pack->ahci_ctrl_num].hba_mem->ports[pack->port_num]), pack->blk_pak.LBA_start & 0xFFFFFFFF, ((pack->blk_pak.LBA_start) >> 32) & 0xFFFFFFFF, pack->blk_pak.count, pack->blk_pak.buffer_vaddr); + ret_val = ahci_write(&(ahci_devices[pack->ahci_ctrl_num].hba_mem->ports[pack->port_num]), pack->blk_pak.LBA_start & 0xFFFFFFFF, ((pack->blk_pak.LBA_start) >> 32) & 0xFFFFFFFF, pack->blk_pak.count, pack->blk_pak.buffer_vaddr, ret_slot); break; default: kerror("Unsupport ahci command: %#05lx", pack->blk_pak.cmd); ret_val = E_UNSUPPORTED_CMD; break; } - // kdebug("ahci_query_disk: retval=%d", ret_val); - // ahci_end_request(); + return ret_val; } -/** - * @brief 将请求包提交到io队列 - * - * @param pack - */ -static void ahci_submit(struct ahci_request_packet_t *pack) -{ - list_append(&(ahci_req_queue.wait_queue_list.wait_list), &(pack->blk_pak.wait_queue.wait_list)); - ++ahci_req_queue.request_count; - - if (ahci_req_queue.in_service == NULL) // 当前没有正在请求的io包,立即执行磁盘请求 - ahci_query_disk(); -} - /** * @brief ahci驱动程序的传输函数 * @@ -656,10 +602,13 @@ static long ahci_transfer(struct blk_gendisk *gd, long cmd, uint64_t base_addr, if (cmd == AHCI_CMD_READ_DMA_EXT || cmd == AHCI_CMD_WRITE_DMA_EXT) { pack = ahci_make_request(cmd, base_addr, count, buf, pdata->ahci_ctrl_num, pdata->ahci_port_num); - ahci_submit(pack); + ahci_push_request(pack); } else + { + kdebug("ahci_transfer: E_UNSUPPORTED_CMD"); return E_UNSUPPORTED_CMD; + } return AHCI_SUCCESS; } @@ -675,3 +624,13 @@ static long ahci_ioctl(long cmd, long arg) { return 0; } + +/** + * @brief 根据端口号获取端口结构体 + * @param port_num 端口号 + * @param ahci_ctrl_num 控制号 + */ +HBA_PORT *ahci_get_port(uint8_t port_num, uint8_t ahci_ctrl_num) +{ + return &(ahci_devices[ahci_ctrl_num].hba_mem->ports[port_num]); +} diff --git a/kernel/src/driver/disk/ahci/ahci.h b/kernel/src/driver/disk/ahci/ahci.h index 40112e95..0863a152 100644 --- a/kernel/src/driver/disk/ahci/ahci.h +++ b/kernel/src/driver/disk/ahci/ahci.h @@ -380,10 +380,10 @@ static void ahci_probe_port(const uint32_t device_num); * @param starth high 32bits of start addr * @param count total sectors to read * @param buf buffer - * @return true done - * @return false failed + * @param ret_slot 执行命令的插槽号(传出参数) + * @return success 0 */ -static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, uint64_t buf); +static int ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, uint64_t buf, int8_t *ret_slot); /** * @brief write data to SATA device using 48bit LBA address @@ -393,10 +393,40 @@ static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t * @param starth high 32bits of start addr * @param count total sectors to read * @param buf buffer - * @return true done - * @return false failed + * @param ret_slot 执行命令的插槽号(传出参数) + * @return success 0 */ -static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, - uint64_t buf); +static int ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, + uint64_t buf, int8_t *ret_slot); -void ahci_end_request(); \ No newline at end of file +void ahci_end_request(); + +/** + * @brief 检查请求包是否已完成 + * + * @param port_num HBA PORT 编号 + * @param ahci_ctrl_num ahci控制号 + * @param ret_slot 执行命令的插槽号 + * @param err 错误信息 + */ +int ahci_check_complete(uint8_t port_num, uint8_t ahci_ctrl_num, int8_t slot, char *err); + +/** + * @brief 根据端口号获取端口结构体 + * @param port_num 端口号 + * @param ahci_ctrl_num 控制号 + */ +HBA_PORT *ahci_get_port(uint8_t port_num, uint8_t ahci_ctrl_num); + +/** + * @brief Find a free command list slot + * @param port + */ +int ahci_find_cmdslot(HBA_PORT *port); + +/** + * @brief 读取磁盘信息 + * @param pack io请求包 + * @param ret_slot 执行命令的插槽号(传出参数) + */ +long ahci_query_disk(struct ahci_request_packet_t *pack, int8_t *ret_slot); diff --git a/kernel/src/driver/interrupt/apic/apic.c b/kernel/src/driver/interrupt/apic/apic.c index 78c493e3..0b45fb5b 100644 --- a/kernel/src/driver/interrupt/apic/apic.c +++ b/kernel/src/driver/interrupt/apic/apic.c @@ -1,11 +1,11 @@ #include "apic.h" #include "apic_timer.h" -#include -#include #include #include -#include +#include +#include #include +#include #include #include @@ -62,7 +62,8 @@ void apic_io_apic_init() // kdebug("MADT->length= %d bytes", madt->header.Length); // 寻找io apic的ICS void *ent = (void *)(madt_addr) + sizeof(struct acpi_Multiple_APIC_Description_Table_t); - struct apic_Interrupt_Controller_Structure_header_t *header = (struct apic_Interrupt_Controller_Structure_header_t *)ent; + struct apic_Interrupt_Controller_Structure_header_t *header = + (struct apic_Interrupt_Controller_Structure_header_t *)ent; while (header->length > 2) { header = (struct apic_Interrupt_Controller_Structure_header_t *)ent; @@ -85,7 +86,8 @@ void apic_io_apic_init() // kdebug("(ul)apic_ioapic_map.virtual_index_addr=%#018lx", (ul)apic_ioapic_map.virtual_index_addr); // 填写页表,完成地址映射 - mm_map_phys_addr((ul)apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false); + mm_map_phys_addr((ul)apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE, + PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false); // 设置IO APIC ID 为0x0f000000 *apic_ioapic_map.virtual_index_addr = 0x00; @@ -99,7 +101,8 @@ void apic_io_apic_init() // 获取IO APIC Version *apic_ioapic_map.virtual_index_addr = 0x01; io_mfence(); - kdebug("IO APIC Version=%d, Max Redirection Entries=%d", *apic_ioapic_map.virtual_data_addr & 0xff, (((*apic_ioapic_map.virtual_data_addr) >> 16) & 0xff) + 1); + kdebug("IO APIC Version=%d, Max Redirection Entries=%d", *apic_ioapic_map.virtual_data_addr & 0xff, + (((*apic_ioapic_map.virtual_data_addr) >> 16) & 0xff) + 1); // 初始化RTE表项,将所有RTE表项屏蔽 for (int i = 0x10; i < 0x40; i += 2) @@ -171,7 +174,8 @@ static void __local_apic_xapic_init() local_apic_max_LVT_entries = ((qword >> 16) & 0xff) + 1; local_apic_version = qword & 0xff; - kdebug("local APIC Version:%#010x,Max LVT Entry:%#010x,SVR(Suppress EOI Broadcast):%#04x\t", local_apic_version, local_apic_max_LVT_entries, (qword >> 24) & 0x1); + kdebug("local APIC Version:%#010x,Max LVT Entry:%#010x,SVR(Suppress EOI Broadcast):%#04x\t", local_apic_version, + local_apic_max_LVT_entries, (qword >> 24) & 0x1); if ((qword & 0xff) < 0x10) { @@ -189,7 +193,8 @@ static void __local_apic_xapic_init() *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL) = APIC_LVT_INT_MASKED; io_mfence(); - *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR) = APIC_LVT_INT_MASKED; + *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR) = + APIC_LVT_INT_MASKED; io_mfence(); *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0) = APIC_LVT_INT_MASKED; io_mfence(); @@ -232,7 +237,8 @@ static void __local_apic_x2apic_init() local_apic_max_LVT_entries = ((eax >> 16) & 0xff) + 1; local_apic_version = eax & 0xff; - kdebug("local APIC Version:%#010x,Max LVT Entry:%#010x,SVR(Suppress EOI Broadcast):%#04x\t", local_apic_version, local_apic_max_LVT_entries, (eax >> 24) & 0x1); + kdebug("local APIC Version:%#010x,Max LVT Entry:%#010x,SVR(Suppress EOI Broadcast):%#04x\t", local_apic_version, + local_apic_max_LVT_entries, (eax >> 24) & 0x1); if ((eax & 0xff) < 0x10) kdebug("82489DX discrete APIC"); @@ -269,7 +275,8 @@ void apic_local_apic_init() uint64_t ia32_apic_base = rdmsr(0x1b); // kdebug("apic base=%#018lx", (ia32_apic_base & 0x1FFFFFFFFFF000)); // 映射Local APIC 寄存器地址 - mm_map_phys_addr(APIC_LOCAL_APIC_VIRT_BASE_ADDR, (ia32_apic_base & 0x1FFFFFFFFFFFFF), PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false); + mm_map_phys_addr(APIC_LOCAL_APIC_VIRT_BASE_ADDR, (ia32_apic_base & 0x1FFFFFFFFFFFFF), PAGE_2M_SIZE, + PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false); uint a, b, c, d; cpu_cpuid(1, 0, &a, &b, &c, &d); @@ -588,7 +595,8 @@ void apic_local_apic_edge_ack(ul irq_num) uint apic_get_ics(const uint type, ul ret_vaddr[], uint *total) { void *ent = (void *)(madt) + sizeof(struct acpi_Multiple_APIC_Description_Table_t); - struct apic_Interrupt_Controller_Structure_header_t *header = (struct apic_Interrupt_Controller_Structure_header_t *)ent; + struct apic_Interrupt_Controller_Structure_header_t *header = + (struct apic_Interrupt_Controller_Structure_header_t *)ent; bool flag = false; uint cnt = 0; @@ -626,7 +634,8 @@ uint apic_get_ics(const uint type, ul ret_vaddr[], uint *total) * @param dest_apicID 目标apicID */ void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, uint8_t deliver_mode, uint8_t dest_mode, - uint8_t deliver_status, uint8_t polarity, uint8_t irr, uint8_t trigger, uint8_t mask, uint8_t dest_apicID) + uint8_t deliver_status, uint8_t polarity, uint8_t irr, uint8_t trigger, uint8_t mask, + uint8_t dest_apicID) { entry->vector = vector; @@ -652,4 +661,35 @@ void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, u entry->destination.logical.reserved1 = 0; } } + +/** + * @brief 获取当前处理器的local apic id + * + * @return uint32_t + */ +uint32_t apic_get_local_apic_id() +{ + // 获取Local APIC的基础信息 (参见英特尔开发手册Vol3A 10-39) + // Table 10-6. Local APIC Register Address Map Supported by x2APIC + + if (flag_support_x2apic) + { + // 获取 Local APIC ID + // 0x802处是x2APIC ID 位宽32bits 的 Local APIC ID register + uint32_t x = 0; + __asm__ __volatile__("movq $0x802, %%rcx \n\t" + "rdmsr \n\t" + : "=a"(x)::"memory"); + return x; + } + else + { + // kdebug("get Local APIC ID: edx=%#010x, eax=%#010x", edx, eax); + // kdebug("local_apic_id=%#018lx", ); + + uint32_t x = *(uint32_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_ID); + x = ((x >> 24) & 0xff); + return x; + } +} #pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/driver/interrupt/apic/apic.h b/kernel/src/driver/interrupt/apic/apic.h index 3a001ce0..57cb4c5b 100644 --- a/kernel/src/driver/interrupt/apic/apic.h +++ b/kernel/src/driver/interrupt/apic/apic.h @@ -330,4 +330,5 @@ void apic_local_apic_edge_ack(ul irq_num); // local apic边沿触发 应答 void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, uint8_t deliver_mode, uint8_t dest_mode, uint8_t deliver_status, uint8_t polarity, uint8_t irr, uint8_t trigger, uint8_t mask, uint8_t dest_apicID); +uint32_t apic_get_local_apic_id(); #pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/driver/interrupt/apic/apic_timer.c b/kernel/src/driver/interrupt/apic/apic_timer.c index 83d524e6..2c443865 100644 --- a/kernel/src/driver/interrupt/apic/apic_timer.c +++ b/kernel/src/driver/interrupt/apic/apic_timer.c @@ -1,12 +1,29 @@ #include "apic_timer.h" +#include #include #include -#include #include // #pragma GCC push_options // #pragma GCC optimize("O0") uint64_t apic_timer_ticks_result = 0; +static spinlock_t apic_timer_init_lock = {1}; +// bsp 是否已经完成apic时钟初始化 +static bool bsp_initialized = false; + +/** + * @brief 初始化AP核的apic时钟 + * + */ +void apic_timer_ap_core_init() +{ + while (!bsp_initialized) + { + pause(); + } + + apic_timer_init(); +} void apic_timer_enable(uint64_t irq_num) { @@ -55,13 +72,12 @@ void apic_timer_uninstall(ul irq_num) io_mfence(); } -hardware_intr_controller apic_timer_intr_controller = - { - .enable = apic_timer_enable, - .disable = apic_timer_disable, - .install = apic_timer_install, - .uninstall = apic_timer_uninstall, - .ack = apic_local_apic_edge_ack, +hardware_intr_controller apic_timer_intr_controller = { + .enable = apic_timer_enable, + .disable = apic_timer_disable, + .install = apic_timer_install, + .uninstall = apic_timer_uninstall, + .ack = apic_local_apic_edge_ack, }; /** @@ -84,15 +100,23 @@ void apic_timer_handler(uint64_t number, uint64_t param, struct pt_regs *regs) */ void apic_timer_init() { + if (apic_timer_ticks_result == 0) { kBUG("APIC timer ticks in 5ms is equal to ZERO!"); while (1) hlt(); } + spin_lock(&apic_timer_init_lock); kinfo("Initializing apic timer for cpu %d", proc_current_cpu_id); io_mfence(); - irq_register(APIC_TIMER_IRQ_NUM, &apic_timer_ticks_result, &apic_timer_handler, 0, &apic_timer_intr_controller, "apic timer"); + irq_register(APIC_TIMER_IRQ_NUM, &apic_timer_ticks_result, &apic_timer_handler, 0, &apic_timer_intr_controller, + "apic timer"); io_mfence(); + if (proc_current_cpu_id == 0) + { + bsp_initialized = true; + } + spin_unlock(&apic_timer_init_lock); // kinfo("Successfully initialized apic timer for cpu %d", proc_current_cpu_id); } \ No newline at end of file diff --git a/kernel/src/driver/interrupt/apic/apic_timer.h b/kernel/src/driver/interrupt/apic/apic_timer.h index a0c09b2d..ec97b86d 100644 --- a/kernel/src/driver/interrupt/apic/apic_timer.h +++ b/kernel/src/driver/interrupt/apic/apic_timer.h @@ -105,4 +105,6 @@ static __always_inline uint32_t apic_timer_get_current() */ void apic_timer_init(); +void apic_timer_ap_core_init(); + #pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/exception/irq.h b/kernel/src/exception/irq.h index 6fbfed4f..f733c6ae 100644 --- a/kernel/src/exception/irq.h +++ b/kernel/src/exception/irq.h @@ -102,6 +102,8 @@ extern void (*local_apic_interrupt_table[LOCAL_APIC_IRQ_NUM])(void); 200 ~ 255 MP IPI + 200 kick cpu 功能(使得某个核心立即运行进程调度) + */ typedef struct hardware_intr_type diff --git a/kernel/src/filesystem/fat32/fat32.c b/kernel/src/filesystem/fat32/fat32.c index 6db79515..cd25bee0 100644 --- a/kernel/src/filesystem/fat32/fat32.c +++ b/kernel/src/filesystem/fat32/fat32.c @@ -372,10 +372,11 @@ find_lookup_success:; // 找到目标dentry */ struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk) { + // BUG // 读取文件系统的boot扇区 uint8_t buf[512] = {0}; - blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, blk->bd_start_LBA, 1, (uint64_t)&buf); + blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, blk->bd_start_LBA, 1, (uint64_t)&buf); // 分配超级块的空间 struct vfs_superblock_t *sb_ptr = (struct vfs_superblock_t *)kzalloc(sizeof(struct vfs_superblock_t), 0); blk->bd_superblock = sb_ptr; @@ -445,7 +446,6 @@ struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk) finode->create_date = 0; finode->write_date = 0; finode->write_time; - return sb_ptr; } @@ -1411,8 +1411,6 @@ void fat32_init() // 在VFS中注册fat32文件系统 vfs_register_filesystem(&fat32_fs_type); - // 挂载根文件系统 fat32_register_partition(ahci_gendisk0.partition + 0, 0); - kinfo("FAT32 initialized."); } \ No newline at end of file diff --git a/kernel/src/include/bindings/wrapper.h b/kernel/src/include/bindings/wrapper.h index af1b2d35..d9d6ffb1 100644 --- a/kernel/src/include/bindings/wrapper.h +++ b/kernel/src/include/bindings/wrapper.h @@ -10,6 +10,8 @@ */ #pragma once +#include +#include #include #include #include @@ -18,16 +20,18 @@ #include #include #include +#include #include #include #include #include +#include #include -#include +#include #include #include #include #include #include #include -#include