From 4a993fb96a120248e830083a5f225dac2341e1cc Mon Sep 17 00:00:00 2001 From: Aren Elchinyan Date: Thu, 9 Jan 2025 15:14:57 +0300 Subject: [PATCH 1/3] Fix infinity reboot --- Makefile | 4 +- kernel/arch/amd64/boot.s | 200 +++++++++++++++++++++++++++++++-------- kernel/arch/amd64/gdt.c | 31 ------ kernel/arch/amd64/idt.c | 39 -------- kernel/kernel.c | 15 +-- scripts/linker.ld | 49 ++++++---- 6 files changed, 196 insertions(+), 142 deletions(-) delete mode 100644 kernel/arch/amd64/gdt.c delete mode 100644 kernel/arch/amd64/idt.c diff --git a/Makefile b/Makefile index 036d7af..93f4299 100644 --- a/Makefile +++ b/Makefile @@ -25,14 +25,14 @@ kernel/kernel.elf: $(OBJS) as $(ASFLAGS) -o $@ $< serial.log: cis-os.iso - timeout 10s qemu-system-x86_64 -m 256 -cdrom $< -d guest_errors -serial file:$@ || true + timeout 10s qemu-system-x86_64 -m 256 -cdrom $< -d guest_errors -serial file:$@ --no-reboot -no-shutdown || true test: serial.log cat $< grep -q '\[OK\]' $< && echo "Test passed." || (echo "Test failed." && exit 1) run: cis-os.iso - qemu-system-x86_64 -m 256 -cdrom $< -d guest_errors -serial file:serial.log + qemu-system-x86_64 -m 256 -cdrom $< -d guest_errors -serial file:serial.log --no-reboot -no-shutdown clean: rm -rf isodir diff --git a/kernel/arch/amd64/boot.s b/kernel/arch/amd64/boot.s index 9e20a9e..77d3f69 100644 --- a/kernel/arch/amd64/boot.s +++ b/kernel/arch/amd64/boot.s @@ -1,65 +1,183 @@ .section .multiboot -.align 8 +.code32 + +.extern bss_start +.extern end +.extern phys -.long 0x1BADB002 -.long 0x00000003 -.long -(0x1BADB002 + 0x00000003) +.set MULTIBOOT_MAGIC, 0x1BADB002 +.set MULTIBOOT_FLAG_PAGE_ALIGN, 1 << 0 +.set MULTIBOOT_FLAG_MEMORY_INFO, 1 << 1 +.set MULTIBOOT_FLAGS, MULTIBOOT_FLAG_PAGE_ALIGN | MULTIBOOT_FLAG_MEMORY_INFO +.set MULTIBOOT_CHECKSUM, -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) -.section .bss -.align 16 +.align 4 +multiboot_header: +.long MULTIBOOT_MAGIC +.long MULTIBOOT_FLAGS +.long MULTIBOOT_CHECKSUM +.long multiboot_header +.long phys +.long bss_start +.long end +.long _start + +.section .stack, "aw", @nobits stack_bottom: - .skip 1024 * 4 + .skip 16384 +.global stack_top stack_top: -.section .text +.section .bootstrap .code32 +.align 4 + +.extern paging_main +.extern jmp_long +.type jmp_long, @function + +.extern kernel_main64 +.type kernel_main64, @function + .global _start +.type _start, @function _start: - movl $0xFFFFFFFF, %esp - - movl $0x80000000, %eax - cpuid - cmpl $0x80000001, %eax - jb no_long_mode - movl $0x80000001, %eax - cpuid - testl $0x20000000, %edx - jnz long_mode_supported -no_long_mode: - hlt -long_mode_supported: - # PAE - movl %cr4, %eax - orl $0x20, %eax - movl %eax, %cr4 + movl %ebx, %ecx + addl $16, %ecx + mov %ecx, %esp + call _forward +_forward: + popl %ecx + subl $_forward, %ecx + + mov $stack_top, %esp + addl %ecx, %esp + and $-16, %esp + + pushl $0 + pushl %esp + pushl $0 + pushl %eax + pushl $0 + pushl %ebx + + jmp jmp_long + +.align 4 + +jmp_long: + mov $paging_main, %edi + addl %ecx, %edi + pushl %ecx + + mov $0x1007, %eax + add %edi, %eax + mov %eax, (%edi) + + add $0x1000, %edi + mov $0x1003, %eax + add %edi, %eax + mov %eax, (%edi) + + add $0x1000, %edi + + mov $0x87, %ebx + mov $32, %ecx - # GDT - call gdt64_install +.set_entry: + mov %ebx, (%edi) + add $0x200000, %ebx + add $8, %edi + loop .set_entry - # IDT - call idt_install + mov $paging_main, %edi + popl %ecx + addl %ecx, %edi + pushl %ecx + mov %edi, %cr3 - # AMD64 - movl $0x101, %eax - movl %eax, %cr0 - movl %cr0, %eax - orl $0x80000000, %eax - movl %eax, %cr0 + mov %cr4, %eax + or $32, %eax + mov %eax, %cr4 - ljmp $0x08, $enter_long_mode + mov $0xC0000080, %ecx + rdmsr + or $256, %eax + wrmsr + + mov %cr0, %eax + or $0x80000000, %eax + mov %eax, %cr0 + + popl %ecx + + lea (_lgdt+3)(%ecx), %eax + movl (%eax), %ebx + addl %ecx, %ebx + movl %ebx, (%eax) + + lea (gdtr+2)(%ecx), %eax + movl (%eax), %ebx + addl %ecx, %ebx + movl %ebx, (%eax) + + lea (_ljmp+1)(%ecx), %eax + movl (%eax), %ebx + addl %ecx, %ebx + movl %ebx, (%eax) + + pushl $0 + pushl %ecx + +_lgdt: + lgdt gdtr + +_ljmp: + ljmp $0x08, $amd64 + +.align 8 +gdtr: + .word gdt_end - gdt_base + .quad gdt_base + +gdt_base: + .quad 0 + .word 0 + .word 0 + .byte 0 + .byte 0x9a + .byte 0x20 + .byte 0 + .word 0xffff + .word 0 + .byte 0 + .byte 0x92 + .byte 0 + .byte 0 +gdt_end: .code64 -enter_long_mode: - movw $0x10, %ax +.align 8 +.section .bootstrap + +amd64: + cli + mov $0x10, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs mov %ax, %ss + finit - movq stack_top, %rsp - - call kernel_main64 + cli + pop %rcx + pop %rdi + pop %rsi + pop %rdx + callq kernel_main64 +halt: cli hlt + jmp halt \ No newline at end of file diff --git a/kernel/arch/amd64/gdt.c b/kernel/arch/amd64/gdt.c deleted file mode 100644 index 3e337eb..0000000 --- a/kernel/arch/amd64/gdt.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - -typedef struct { - uint16_t limit_low; - uint16_t base_low; - uint8_t base_middle; - uint8_t access; - uint8_t granularity; - uint8_t base_high; -} __attribute__((packed)) gdt_entry64_t; - -gdt_entry64_t gdt64[3]; - -void gdt64_set_gate(int num, uint64_t base, uint32_t limit, uint8_t access, uint8_t granularity) { - gdt64[num].limit_low = (limit & 0xFFFF); - gdt64[num].base_low = (base & 0xFFFF); - gdt64[num].base_middle = (base >> 16) & 0xFF; - gdt64[num].access = access; - gdt64[num].granularity = (granularity & 0xF) | ((limit >> 16) & 0xF0); - gdt64[num].base_high = (base >> 24) & 0xFF; -} - -void gdt64_install() { - gdt64_set_gate(0, 0, 0, 0, 0); - gdt64_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xAF); - gdt64_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); - - uint64_t gdt64_ptr = (sizeof(gdt_entry64_t) * 3) - 1; - gdt64_ptr |= (uint64_t)gdt64 << 16; - asm volatile("lgdt %0" : : "m" (*(void **) &gdt64_ptr)); -} diff --git a/kernel/arch/amd64/idt.c b/kernel/arch/amd64/idt.c deleted file mode 100644 index 255cf77..0000000 --- a/kernel/arch/amd64/idt.c +++ /dev/null @@ -1,39 +0,0 @@ -#include - -typedef struct { - uint16_t limit; - uint64_t base; -} __attribute__((packed)) idt_reg_t; - -typedef struct { - uint16_t offset_low; - uint16_t selector; - uint8_t zero; - uint8_t type_attr; - uint16_t offset_high; -} __attribute__((packed)) idt_entry_t; - -idt_entry_t idt[256]; -idt_reg_t idt_reg; - -void dummy_handler64() { - asm volatile("iretq"); -} - -void idt_set_gate(int num, uint64_t handler, uint16_t selector, uint8_t type_attr) { - idt[num].offset_low = handler & 0xFFFF; - idt[num].selector = selector; - idt[num].zero = 0; - idt[num].type_attr = type_attr; - idt[num].offset_high = (handler >> 16) & 0xFFFF; -} - -void idt_install() { - for(int i = 0; i < 256; i++) { - idt_set_gate(i, (uint64_t)dummy_handler64, 0x08, 0x8E); - } - - idt_reg.limit = (sizeof(idt_entry_t) * 256) - 1; - idt_reg.base = (uint64_t)&idt; - asm volatile("lidt %0" : : "m" (idt_reg)); -} \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index fd873ea..d4ddc15 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,5 +1,7 @@ #include +uint64_t paging_main[3][512] __attribute__((aligned(4096))) = {0}; + static inline void outb(uint16_t port, uint8_t val) { asm volatile("outb %0, %1" : : "a"(val), "Nd"(port)); } @@ -8,21 +10,10 @@ void hal_write_byte_manual(uint8_t byte) { outb(0x3f8, byte); } -void puts(char *str) { - char *video_memory = (char *)0xB8000; - uint16_t *v = (uint16_t *)video_memory; - int i = 0; - while(str[i]) { - v[i] = (str[i] << 8) | 0x0F; - i++; - } -} - -void kernel_main64() { +void kernel_main64(uint64_t *multiboot, uint32_t magic, void *esp, uint64_t base) { hal_write_byte_manual('['); hal_write_byte_manual('O'); hal_write_byte_manual('K'); hal_write_byte_manual(']'); - puts("Hello, World from CIS! "); for(;;) {} } \ No newline at end of file diff --git a/scripts/linker.ld b/scripts/linker.ld index c9c3e77..92a384d 100644 --- a/scripts/linker.ld +++ b/scripts/linker.ld @@ -1,27 +1,42 @@ +OUTPUT_FORMAT(elf64-x86-64) ENTRY(_start) -SECTIONS { - . = 0x100000; # 1MB +SECTIONS{ + . = 1M; + phys = .; - .text BLOCK(4K) : ALIGN(4K) - { + .text BLOCK(4K) : ALIGN(4K) { *(.multiboot) + *(.bootstrap) + code = .; *(.text) } - .rodata : - { - *(.rodata) - } + .rodata BLOCK(4K) : ALIGN(4K) { + *(.rodata) + } + + .data BLOCK(4K) : ALIGN(4K) { + data = .; + *(.data) + *(.symbols) + PROVIDE(kernel_symbols_start = .); + PROVIDE(kernel_symbols_end = .); + } - .data : - { - *(.data) - } + .bss BLOCK(4K) : ALIGN(4K) { + PROVIDE(bss_start = .); + bss = .; + *(COMMON) + *(.bss) + *(.stack) + } + + end = .; - .bss : - { - *(COMMON) - *(.bss) - } + /DISCARD/ : { + *(.comment) + *(.eh_frame) + *(.note.gnu.build-id) + } } \ No newline at end of file From f4801f96dc1b9f56b206440ca38625e510bc288c Mon Sep 17 00:00:00 2001 From: Aren Elchinyan Date: Thu, 9 Jan 2025 15:16:43 +0300 Subject: [PATCH 2/3] Add apt update to CI --- .github/workflows/c-cpp.yml | 6 ++++-- Makefile | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index f2e5bf5..f6d1ef3 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -14,8 +14,10 @@ jobs: steps: - uses: actions/checkout@v4 - name: configure - run: sudo apt install gcc build-essential grub2-common qemu-system-x86 xorriso mtools + run: | + sudo apt update + sudo apt install gcc build-essential grub2-common qemu-system-x86 xorriso mtools - name: make run: make - name: run and test - run: make test + run: make clean && make && make test diff --git a/Makefile b/Makefile index 93f4299..7b652fd 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ serial.log: cis-os.iso test: serial.log cat $< + ls grep -q '\[OK\]' $< && echo "Test passed." || (echo "Test failed." && exit 1) run: cis-os.iso From eff6085f3a5d97f1d82585296636e387063ef93b Mon Sep 17 00:00:00 2001 From: Aren Elchinyan Date: Thu, 9 Jan 2025 15:21:40 +0300 Subject: [PATCH 3/3] Add nographics option to test to fix gtk issue --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7b652fd..e651c91 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ kernel/kernel.elf: $(OBJS) as $(ASFLAGS) -o $@ $< serial.log: cis-os.iso - timeout 10s qemu-system-x86_64 -m 256 -cdrom $< -d guest_errors -serial file:$@ --no-reboot -no-shutdown || true + timeout 10s qemu-system-x86_64 -nographics -m 256 -cdrom $< -d guest_errors -serial file:$@ --no-reboot -no-shutdown || true test: serial.log cat $<