fslongjin 2 роки тому
батько
коміт
e806bbc0c8

+ 3 - 1
.vscode/settings.json

@@ -113,7 +113,9 @@
         "ia64_msi.h": "c",
         "errno.h": "c",
         "bug.h": "c",
-        "apic_timer.h": "c"
+        "apic_timer.h": "c",
+        "preempt.h": "c",
+        "softirq.h": "c"
     },
     "C_Cpp.errorSquiggles": "Enabled",
     "esbonio.sphinx.confDir": ""

+ 1 - 1
Makefile

@@ -7,7 +7,7 @@ export ARCH=__x86_64__
 export ROOT_PATH=$(shell pwd)
 
 export DEBUG=DEBUG
-export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64  -O1 -fno-stack-protector -D $(ARCH) 
+export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64  -fno-stack-protector -D $(ARCH) 
 
 ifeq ($(DEBUG), DEBUG)
 GLOBAL_CFLAGS += -g 

+ 1 - 1
kernel/Makefile

@@ -10,7 +10,7 @@ LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns)))
 
 # 控制操作系统使用的中断控制器 _INTR_8259A_ _INTR_APIC_
 PIC := _INTR_APIC_
-CFLAGS = $(GLOBAL_CFLAGS) -D $(PIC) -I $(shell pwd)
+CFLAGS = $(GLOBAL_CFLAGS) -D $(PIC) -I $(shell pwd) -O1
 
 export ASFLAGS := --64
 

+ 7 - 3
kernel/common/printk.c

@@ -10,7 +10,8 @@
 #include <driver/uart/uart.h>
 #include <driver/video/video.h>
 #include "math.h"
-
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 struct printk_screen_info pos;
 extern ul VBE_FB_phys_addr; // 由bootloader传来的帧缓存区的物理地址
 static spinlock_t printk_lock;
@@ -184,7 +185,9 @@ static void auto_newline()
 #endif
         pos.y = pos.max_y;
         int lines_to_scroll = 1;
+        barrier();
         scroll(true, lines_to_scroll * pos.char_size_y, sw_show_scroll_animation);
+        barrier();
         pos.y -= (lines_to_scroll - 1);
     }
 }
@@ -835,7 +838,6 @@ static int scroll(bool direction, int pixels, bool animation)
     int md = pixels % pos.char_size_y;
     if (md)
         pixels = pixels + pos.char_size_y - md;
-
     if (animation == false)
         return do_scroll(direction, pixels);
     else
@@ -956,4 +958,6 @@ int sprintk(char *buf, const char *fmt, ...)
     va_end(args);
 
     return count;
-}
+}
+
+#pragma GCC pop_options

+ 3 - 1
kernel/common/printk.h

@@ -2,7 +2,8 @@
 // Created by longjin on 2022/1/21.
 //
 #pragma once
-
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 #define PAD_ZERO 1 // 0填充
 #define LEFT 2     // 靠左对齐
 #define RIGHT 4    // 靠右对齐
@@ -124,3 +125,4 @@ void printk_disable_animation();
  * @return int 字符串长度
  */
 int sprintk(char *buf, const char *fmt, ...);
+#pragma GCC pop_options

+ 3 - 0
kernel/debug/bug.h

@@ -2,6 +2,8 @@
 #include <common/compiler.h>
 #include <common/kprint.h>
 
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 /**
  * @brief 当condition为true时输出警告信息
  *
@@ -19,3 +21,4 @@
         goto to;                       \
     unlikely(__ret_warn_on);           \
 })
+#pragma GCC pop_options

+ 1 - 21
kernel/driver/interrupt/apic/apic.c

@@ -96,27 +96,7 @@ void apic_io_apic_init()
 
     // 不需要手动启动IO APIC,只要初始化了RTE寄存器之后,io apic就会自动启用了。
     // 而且不是每台电脑都有RCBA寄存器,因此不需要手动启用IO APIC
-    /*
-           // get RCBA address
-           io_out32(0xcf8, 0x8000f8f0);
-           uint x = io_in32(0xcfc);
-           uint *p;
-           printk_color(RED, BLACK, "Get RCBA Address:%#010x\n", x);
-           x = x & 0xffffc000UL;
-           printk_color(RED, BLACK, "Get RCBA Address:%#010x\n", x);
-
-           // get OIC address
-           if (x > 0xfec00000 && x < 0xfee00000)
-           {
-               p = (unsigned int *)(x + 0x31feUL-apic_ioapic_map.addr_phys+apic_ioapic_map.virtual_index_addr);
-           }
-
-           // enable IOAPIC
-           x = (*p & 0xffffff00) | 0x100;
-           io_mfence();
-           *p = x;
-           io_mfence();
-           */
+    
 }
 
 /**

+ 7 - 2
kernel/driver/interrupt/apic/apic.h

@@ -5,6 +5,9 @@
 #include <exception/irq.h>
 #include <mm/mm.h>
 
+#pragma GCC push_options
+#pragma GCC optimize("O0")
+
 #define APIC_SUCCESS 0
 #define APIC_E_NOTFOUND 1
 
@@ -73,7 +76,7 @@
 // 分频配置寄存器(定时器专用)
 #define LOCAL_APIC_OFFSET_Local_APIC_CLKDIV 0x3e0
 
-uint32_t RCBA_vaddr = 0;// RCBA寄存器的虚拟地址
+uint32_t RCBA_vaddr = 0; // RCBA寄存器的虚拟地址
 
 /*
 
@@ -318,4 +321,6 @@ void apic_local_apic_edge_ack(ul irq_num); // local apic边沿触发 应答
  * @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);
+
+#pragma GCC pop_options

+ 11 - 0
kernel/driver/interrupt/apic/apic_timer.c

@@ -11,9 +11,13 @@ uint64_t apic_timer_ticks_result = 0;
 void apic_timer_enable(uint64_t irq_num)
 {
     // 启动apic定时器
+    io_mfence();
     uint64_t val = apic_timer_get_LVT();
+    io_mfence();
     val &= (~APIC_LVT_INT_MASKED);
+    io_mfence();
     apic_timer_write_LVT(val);
+    io_mfence();
 }
 
 void apic_timer_disable(uint64_t irq_num)
@@ -31,18 +35,24 @@ void apic_timer_disable(uint64_t irq_num)
 uint64_t apic_timer_install(ul irq_num, void *arg)
 {
     // 设置div16
+    io_mfence();
     apic_timer_stop();
+    io_mfence();
     apic_timer_set_div(APIC_TIMER_DIVISOR);
+    io_mfence();
 
     // 设置初始计数
     apic_timer_set_init_cnt(*(uint64_t *)arg);
+    io_mfence();
     // 填写LVT
     apic_timer_set_LVT(APIC_TIMER_IRQ_NUM, 1, APIC_LVT_Timer_Periodic);
+    io_mfence();
 }
 
 void apic_timer_uninstall(ul irq_num)
 {
     apic_timer_write_LVT(APIC_LVT_INT_MASKED);
+    io_mfence();
 }
 
 hardware_intr_controller apic_timer_intr_controller =
@@ -65,6 +75,7 @@ void apic_timer_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
 {
 
     sched_update_jiffies();
+    io_mfence();
 }
 
 /**

+ 1 - 1
kernel/driver/interrupt/apic/apic_timer.h

@@ -82,4 +82,4 @@ extern uint64_t apic_timer_ticks_result;
  */
 void apic_timer_init();
 
-#pragma GCC optimize("O0")
+#pragma GCC pop_options

+ 3 - 0
kernel/driver/timers/HPET/HPET.c

@@ -12,6 +12,8 @@
 #include <driver/interrupt/apic/apic_timer.h>
 #include <common/spinlock.h>
 
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 static struct acpi_HPET_description_table_t *hpet_table;
 static uint64_t HPET_REG_BASE = 0;
 static uint32_t HPET_COUNTER_CLK_PERIOD = 0; // 主计数器时间精度(单位:飞秒)
@@ -283,3 +285,4 @@ int HPET_init()
     // kdebug("HPET_freq=%ld", (long)HPET_freq);
     // kdebug("HPET_freq=%lf", HPET_freq);
 }
+#pragma GCC pop_options

+ 5 - 3
kernel/driver/usb/usb.c

@@ -8,9 +8,10 @@
 extern spinlock_t xhci_controller_init_lock; // xhci控制器初始化锁
 
 #define MAX_USB_NUM 8 // pci总线上的usb设备的最大数量
-
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 // 在pci总线上寻找到的usb设备控制器的header
-struct pci_device_structure_header_t *usb_pdevs[MAX_USB_NUM];
+static struct pci_device_structure_header_t *usb_pdevs[MAX_USB_NUM];
 static int usb_pdevs_count = 0;
 
 /**
@@ -56,4 +57,5 @@ void usb_init()
         }
     }
     kinfo("Successfully initialized all usb host controllers!");
-}
+}
+#pragma GCC pop_options

+ 1 - 0
kernel/driver/usb/xhci/xhci.c

@@ -9,6 +9,7 @@
 #include <exception/irq.h>
 #include <driver/interrupt/apic/apic.h>
 
+// 由于xhci寄存器读取需要对齐,因此禁用GCC优化选项
 #pragma GCC push_options
 #pragma GCC optimize("O0")
 

+ 5 - 1
kernel/exception/gate.h

@@ -12,6 +12,8 @@
 #include <common/kprint.h>
 #include <mm/mm.h>
 
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 //描述符表的结构体
 struct desc_struct
 {
@@ -184,4 +186,6 @@ void set_tss64(unsigned int *Table, unsigned long rsp0, unsigned long rsp1, unsi
     *(unsigned long *)(Table + 19) = ist6;
     *(unsigned long *)(Table + 21) = ist7;
 }
-#endif
+#endif
+
+#pragma GCC pop_options

+ 18 - 5
kernel/main.c

@@ -34,11 +34,12 @@
 #include <driver/video/video.h>
 
 #include <driver/interrupt/apic/apic_timer.h>
-
+#pragma GCC push_options
+#pragma GCC optimize("O3")
 unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址
 ul bsp_idt_size, bsp_gdt_size;
 
-struct memory_desc memory_management_struct = {{0}, 0};
+
 // struct Global_Memory_Descriptor memory_management_struct = {{0}, 0};
 void test_slab();
 
@@ -126,13 +127,18 @@ void system_initialize()
     current_pcb->preempt_count = 0;
     // 先初始化系统调用模块
     syscall_init();
+    io_mfence();
     //  再初始化进程模块。顺序不能调转
     sched_init();
+    io_mfence();
 
     timer_init();
 
+    // 这里必须加内存屏障,否则会出错
+    io_mfence();
     smp_init();
-    kdebug("after smp init");
+    io_mfence();
+
     
     cpu_init();
     ps2_keyboard_init();
@@ -146,19 +152,24 @@ void system_initialize()
 
     // process_init();
     HPET_init();
+    io_mfence();
     HPET_measure_freq();
+    io_mfence();
     // current_pcb->preempt_count = 0;
     // kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
 
     process_init();
     // 对显示模块进行高级初始化,启用double buffer
     video_init(true);
+    io_mfence();
 
     // fat32_init();
     HPET_enable();
 
+    io_mfence();
     // 系统初始化到此结束,剩下的初始化功能应当放在初始内核线程中执行
     apic_timer_init();
+    io_mfence();
 }
 
 //操作系统内核从这里开始执行
@@ -182,8 +193,9 @@ void Start_Kernel(void)
     mb2_magic &= 0xffffffff;
     multiboot2_magic = (uint)mb2_magic;
     multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
-
+    io_mfence();
     system_initialize();
+    io_mfence();
 
     while (1)
         hlt();
@@ -194,4 +206,5 @@ void ignore_int()
     kwarn("Unknown interrupt or fault at RIP.\n");
     while (1)
         ;
-}
+}
+#pragma GCC pop_options

+ 6 - 1
kernel/mm/mm.c

@@ -11,7 +11,10 @@
 static ul Total_Memory = 0;
 static ul total_2M_pages = 0;
 static ul root_page_table_phys_addr = 0; // 内核层根页表的物理地址
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 
+struct memory_desc memory_management_struct = {{0}, 0};
 /**
  * @brief 虚拟地址长度所需要的entry数量
  *
@@ -278,6 +281,7 @@ unsigned long page_init(struct Page *page, ul flags)
     if ((!page->ref_counts) || (page->attr & PAGE_SHARED))
     {
         ++page->ref_counts;
+        barrier();
         ++page->zone->total_pages_link;
     }
     return 0;
@@ -976,4 +980,5 @@ int8_t mm_is_2M_page(uint64_t paddr)
     if(likely((paddr >> PAGE_2M_SHIFT)<total_2M_pages))
         return 1;
     else return 0;
-}
+}
+#pragma GCC pop_options

+ 1 - 0
kernel/mm/mm.h

@@ -145,6 +145,7 @@
     do                              \
     {                               \
         ul tmp;                     \
+        io_mfence();\
         __asm__ __volatile__(       \
             "movq %%cr3, %0\n\t"    \
             "movq %0, %%cr3\n\t"    \

+ 14 - 3
kernel/mm/slab.c

@@ -1,6 +1,8 @@
 #include "slab.h"
 #include <common/compiler.h>
 
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 struct slab kmalloc_cache_group[16] =
     {
         {32, 0, 0, NULL, NULL, NULL, NULL},
@@ -348,9 +350,9 @@ ul slab_init()
     kinfo("Initializing SLAB...");
     // 将slab的内存池空间放置在mms的后方
     ul tmp_addr = memory_management_struct.end_of_struct;
-
     for (int i = 0; i < 16; ++i)
     {
+        io_mfence();
         spin_init(&kmalloc_cache_group[i].lock);
         // 将slab内存池对象的空间放置在mms的后面,并且预留4个unsigned long 的空间以防止内存越界
         kmalloc_cache_group[i].cache_pool_entry = (struct slab_obj *)memory_management_struct.end_of_struct;
@@ -370,7 +372,7 @@ ul slab_init()
 
         // bmp后方预留4个unsigned long的空间防止内存越界,且按照8byte进行对齐
         memory_management_struct.end_of_struct = (ul)(memory_management_struct.end_of_struct + kmalloc_cache_group[i].cache_pool_entry->bmp_len + (sizeof(ul) << 2)) & (~(sizeof(ul) - 1));
-
+        io_mfence();
         // @todo:此处可优化,直接把所有位设置为0,然后再对部分不存在对应的内存对象的位设置为1
         memset(kmalloc_cache_group[i].cache_pool_entry->bmp, 0xff, kmalloc_cache_group[i].cache_pool_entry->bmp_len);
         for (int j = 0; j < kmalloc_cache_group[i].cache_pool_entry->bmp_count; ++j)
@@ -378,6 +380,7 @@ ul slab_init()
 
         kmalloc_cache_group[i].count_total_using = 0;
         kmalloc_cache_group[i].count_total_free = kmalloc_cache_group[i].cache_pool_entry->count_free;
+        io_mfence();
     }
 
     struct Page *page = NULL;
@@ -388,13 +391,17 @@ ul slab_init()
     ul page_num = 0;
     for (int i = PAGE_2M_ALIGN(virt_2_phys(tmp_addr)) >> PAGE_2M_SHIFT; i <= tmp_page_mms_end; ++i)
     {
+
         page = memory_management_struct.pages_struct + i;
         page_num = page->addr_phys >> PAGE_2M_SHIFT;
         *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
         ++page->zone->count_pages_using;
+        io_mfence();
         --page->zone->count_pages_free;
         page_init(page, PAGE_KERNEL_INIT | PAGE_KERNEL | PAGE_PGT_MAPPED);
+
     }
+    io_mfence();
 
     // 为slab内存池对象分配内存空间
     ul *virt = NULL;
@@ -406,8 +413,11 @@ ul slab_init()
         page = Virt_To_2M_Page(virt);
 
         page_num = page->addr_phys >> PAGE_2M_SHIFT;
+
         *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
+
         ++page->zone->count_pages_using;
+        io_mfence();    // 该位置必须加一个mfence,否则O3优化运行时会报错
         --page->zone->count_pages_free;
         page_init(page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
 
@@ -696,4 +706,5 @@ unsigned long kfree(void *address)
     }
     kBUG("kfree(): Can't free memory.");
     return ECANNOT_FREE_MEM;
-}
+}
+#pragma GCC pop_options

+ 3 - 3
kernel/process/process.h

@@ -18,8 +18,8 @@
 #include <filesystem/VFS/VFS.h>
 #include <common/wait_queue.h>
 
-// #pragma GCC push_options
-// #pragma GCC optimize("O0")
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 // 进程最大可拥有的文件描述符数量
 #define PROC_MAX_FD_NUM 16
 
@@ -365,4 +365,4 @@ extern struct mm_struct initial_mm;
 extern struct thread_struct initial_thread;
 extern union proc_union initial_proc_union;
 extern struct process_control_block *initial_proc[MAX_CPU_NUM];
-// #pragma GCC pop_options
+#pragma GCC pop_options

+ 1 - 1
kernel/sched/sched.c

@@ -161,4 +161,4 @@ void sched_init()
         sched_cfs_ready_queue[i].proc_queue.virtual_runtime = 0x7fffffffffffffff;
     }
 }
-#pragma GCC optimize("O0")
+#pragma GCC pop_options

+ 5 - 1
kernel/sched/sched.h

@@ -3,6 +3,8 @@
 #include <common/glib.h>
 #include <process/process.h>
 
+#pragma GCC push_options
+#pragma GCC optimize("O0")
 // @todo: 用红黑树重写cfs的队列
 struct sched_queue_t
 {
@@ -45,4 +47,6 @@ void sched_init();
  * @brief 当时钟中断到达时,更新时间片
  * 
  */
-void sched_update_jiffies();
+void sched_update_jiffies();
+
+#pragma GCC pop_options

+ 9 - 8
kernel/smp/smp.c

@@ -11,7 +11,7 @@
 
 #include "ipi.h"
 #pragma GCC push_options
-#pragma GCC optimize("O0")
+#pragma GCC optimize("O1")
 void ipi_0xc8_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs); // 由BSP转发的HPET中断处理函数
 
 static spinlock_t multi_core_starting_lock; // 多核启动锁
@@ -50,19 +50,20 @@ void smp_init()
     kdebug("total_processor_num=%d", total_processor_num);
     for (int i = 1; i < total_processor_num; ++i) // i从1开始,不初始化bsp
     {
+        io_mfence();
         if (proc_local_apic_structs[i]->ACPI_Processor_UID == 0)
             --total_processor_num;
         if (proc_local_apic_structs[i]->local_apic_id > total_processor_num)
-            {
-                --total_processor_num;
-                continue;}
+        {
+            --total_processor_num;
+            continue;
+        }
         kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i, proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->local_apic_id, proc_local_apic_structs[i]->flags);
 
         spin_lock(&multi_core_starting_lock);
-        preempt_enable();   // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,bsp的自旋锁持有计数不会发生改变,需要手动恢复preempt count
+        preempt_enable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,bsp的自旋锁持有计数不会发生改变,需要手动恢复preempt count
         current_starting_cpu = proc_local_apic_structs[i]->local_apic_id;
 
-
         // 为每个AP处理器分配栈空间
         cpu_core_info[current_starting_cpu].stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE;
         cpu_core_info[current_starting_cpu].ist_stack_start = (uint64_t)(kmalloc(STACK_SIZE, 0)) + STACK_SIZE;
@@ -78,7 +79,7 @@ void smp_init()
         memset(&initial_tss[current_starting_cpu], 0, sizeof(struct tss_struct));
 
         set_tss_descriptor(10 + (current_starting_cpu * 2), (void *)(cpu_core_info[current_starting_cpu].tss_vaddr));
-
+        io_mfence();
         set_tss64((uint *)cpu_core_info[current_starting_cpu].tss_vaddr, cpu_core_info[current_starting_cpu].stack_start, cpu_core_info[current_starting_cpu].stack_start, cpu_core_info[current_starting_cpu].stack_start,
                   cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start);
 
@@ -155,7 +156,7 @@ void smp_ap_start()
 
     // kdebug("IDT_addr = %#018lx", phys_2_virt(IDT_Table));
     spin_unlock(&multi_core_starting_lock);
-    preempt_disable();// 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,需要手动恢复preempt count
+    preempt_disable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,需要手动恢复preempt count
     sti();
 
     while (1)

+ 9 - 0
tools/batch_delete_loop.py

@@ -0,0 +1,9 @@
+import os
+
+start = int(input("Start from: "))
+end = int(input("End at: "))
+
+for i in range(start, end+1):
+    print("Deleting: " + str(i))
+    os.system("sudo losetup -d /dev/loop" + str(i))
+print("Done!")