timeout=0
menuentry "$_OS_NAME" {
- multiboot /boot/$_OS_NAME.bin
+ multiboot /boot/kernel.bin
}
\ No newline at end of file
#define __ASM__ 1
#include <arch/x86/boot/multiboot.h>
-#define MB_FLAGS MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN
+#define MB_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN)
#define KPG_SIZE 10*4096
.section .multiboot
for (u32_t i = 0; i < kernel_pg_counts; i++) {
// FIXME: 只是用作用户模式(R3)测试!
// 在实际中,内核代码除了极少部分需要暴露给R3(如从信号返回),其余的应为R0。
+
+#warning "fixme: kernel pages should not be user-accessable"
+
SET_PTE(ptd,
PG_TABLE_KERNEL,
kernel_pte_index + i,
return val;
}
+static inline reg32
+cpu_rcr4()
+{
+ ptr_t val;
+ asm volatile("movl %%cr4,%0" : "=r"(val));
+ return val;
+}
+
static inline reg32
cpu_reflags()
{
#define KCODE_SEG 0x08
#define KDATA_SEG 0x10
+#define KSIZE (MEM_4MB * 16)
+
#define USTACK_SIZE MEM_4MB
#define USTACK_TOP 0x9ffffff0
#define USTACK_END (0x9fffffff - USTACK_SIZE + 1)
/* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */
#define PG_MOUNT_RANGE(l1_index) (701 <= l1_index && l1_index <= 703)
-#define VMS_MOUNT_1 (KERNEL_MM_BASE + MEM_4MB)
+#define VMS_MOUNT_1 (KERNEL_MM_BASE + KSIZE)
#define PG_MOUNT_BASE (VMS_MOUNT_1 + MEM_4MB)
#define PG_MOUNT_1 (PG_MOUNT_BASE)
#define PG_MOUNT_2 (PG_MOUNT_BASE + 0x1000)
#ifndef __LUNAIX_SYS_SIGNAL_DEFS_H
#define __LUNAIX_SYS_SIGNAL_DEFS_H
-#define SIGSEGV 1
-#define SIGALRM 2
-#define SIGCHLD 3
+#define SIGALRM 1
+#define SIGCHLD 2
#define SIGCLD SIGCHLD
-#define SIGINT 4
-#define SIGKILL 5
-#define SIGSTOP 6
-#define SIGCONT 7
+
+#define SIGSTOP 3
+#define SIGCONT 4
+
+#define SIGINT 5
+#define SIGSEGV 6
+#define SIGKILL 7
#define SIGTERM 8
#define SIG_BLOCK 1
--- /dev/null
+include os.mkinc
+include toolchain.mkinc
+
+define ksrc_dirs
+ kernel
+ hal
+ debug
+ libs
+ arch/$(ARCH)
+endef
+
+define kinc_dirs
+ includes
+ includes/usr
+endef
+
+
+kbin_dir := $(BUILD_DIR)
+kbin := $(BUILD_NAME)
+
+ksrc_files := $(foreach f, $(ksrc_dirs), $(shell find $(f) -name "*.[cS]"))
+ksrc_objs := $(addsuffix .o,$(ksrc_files))
+
+kinc_opts := $(addprefix -I,$(kinc_dirs))
+
+
+CFLAGS += -include flags.h
+
+%.S.o: %.S
+ $(call status_,AS,$<)
+ @$(CC) $(kinc_opts) -c $< -o $@
+
+%.c.o: %.c
+ $(call status_,CC,$<)
+ @$(CC) $(CFLAGS) $(kinc_opts) -c $< -o $@
+
+$(kbin): $(ksrc_objs) $(kbin_dir)
+ $(call status_,LD,$@)
+ @$(CC) -T link/linker.ld -o $(kbin) $(ksrc_objs) $(LDFLAGS)
+
+all: $(kbin)
+
+clean:
+ @rm -f $(ksrc_objs)
\ No newline at end of file
void
intr_routine_page_fault(const isr_param* param)
{
+ uint32_t errcode = param->execp->err_code;
ptr_t ptr = cpu_rcr2();
if (!ptr) {
goto segv_term;
goto segv_term;
}
+ if ((errcode & PG_ALLOW_USER)) {
+ // invalid access
+ goto segv_term;
+ }
+
volatile x86_pte_t* pte = &PTE_MOUNTED(VMS_SELF, ptr >> 12);
if (PG_IS_PRESENT(*pte)) {
if ((hit_region->attr & COW_MASK) == COW_MASK) {
goto oom;
}
- *pte = *pte | pa | PG_PRESENT;
+ *pte = *pte | pa | PG_PRESENT | PG_ALLOW_USER;
memset((void*)PG_ALIGN(ptr), 0, PG_SIZE);
goto resolved;
}
}
cpu_invplg((ptr_t)pte);
- *pte = (*pte & 0xFFF) | pa | PG_PRESENT;
+ *pte = (*pte & 0xFFF) | pa | PG_PRESENT | PG_ALLOW_USER;
memset((void*)ptr, 0, PG_SIZE);
oom:
kprintf(KERROR "out of memory\n");
+
segv_term:
- kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p)\n",
+ kprintf(KERROR "(pid: %d) Segmentation fault on %p (%p:%p,e=0x%x)\n",
__current->pid,
ptr,
param->execp->cs,
- param->execp->eip);
+ param->execp->eip,
+ param->execp->err_code);
+
__SIGSET(__current->sig_pending, _SIGSEGV);
+
schedule();
// should not reach
while (1)
}
// Convert UEFI's 512B LB representation into local LBA range.
- u64_t slba_local = (ent->start_lba * GPT_BLKSIZE) / bdev->blk_size;
+ u64_t slba_local =
+ (ent->start_lba * GPT_BLKSIZE) / (u64_t)bdev->blk_size;
u64_t elba_local = (ent->end_lba * GPT_BLKSIZE) / (u64_t)bdev->blk_size;
kprintf("%s: guid part#%d: %d..%d\n",
{
int errno = 0;
- if ((errno = exec_kexecve("/mnt/lunaix-os/usr/init", NULL, NULL))) {
+ if ((errno = exec_kexecve("/mnt/lunaix-os/usr/bin/init", NULL, NULL))) {
goto fail;
}
extern struct scheduler sched_ctx; /* kernel/sched.c */
-extern void
-_exit(int status);
-
-void __USER__
-default_sighandler_term(int signum)
-{
- _exit(signum);
-}
-
-void* default_handlers[_SIG_NUM] = {
- // TODO: 添加默认handler
- [_SIGINT] = default_sighandler_term,
- [_SIGTERM] = default_sighandler_term,
- [_SIGKILL] = default_sighandler_term,
- [_SIGSEGV] = default_sighandler_term,
-};
+static u32_t term_sigs =
+ (1 << SIGSEGV) | (1 << SIGINT) | (1 << SIGKILL) | (1 << SIGTERM);
// Referenced in kernel/asm/x86/interrupt.S
void*
return 0;
}
- // TODO: SIG{INT|TERM|KILL|SEGV} should have highest priority.
- // Terminate the process right here if any of unmaskable signal is
- // set.
-
- if (!__current->sig_handler[sig_selected] &&
- !default_handlers[sig_selected]) {
- // 如果该信号没有handler,则忽略
+ if (!__current->sig_handler[sig_selected]) {
+ if ((term_sigs & (1 << sig_selected))) {
+ terminate_proc(sig_selected);
+ schedule();
+ // never return
+ }
return 0;
}
sig_ctx->sig_num = sig_selected;
sig_ctx->signal_handler = __current->sig_handler[sig_selected];
- if (!sig_ctx->signal_handler) {
- // 如果没有用户自定义的Handler,则使用系统默认Handler。
- sig_ctx->signal_handler = default_handlers[sig_selected];
- }
-
__SIGSET(__current->sig_inprogress, sig_selected);
return sig_ctx;
.hhk_init_text BLOCK(4K) : {
* (.multiboot)
- build/obj/arch/x86/*.o (.hhk_init)
- build/obj/arch/x86/*.o (.text)
+ arch/*.o (.hhk_init)
+ arch/*.o (.text)
}
.hhk_init_bss BLOCK(4K) : {
- build/obj/arch/x86/*.o (.bss)
+ arch/*.o (.bss)
}
.hhk_init_data BLOCK(4K) : {
- build/obj/arch/x86/*.o (.data)
+ arch/*.o (.data)
}
.hhk_init_rodata BLOCK(4K) : {
- build/obj/arch/x86/*.o (.rodata)
+ arch/*.o (.rodata)
}
__init_hhk_end = ALIGN(4K);
/* 好了,我们的内核…… */
.text BLOCK(4K) : AT ( ADDR(.text) - 0xC0000000 ) {
__kernel_start = .;
- build/obj/kernel/*.o (.text)
- build/obj/hal/*.o (.text)
+ kernel/*.o (.text)
+ hal/*.o (.text)
+ debug/*.o (.text)
+ libs/*.o (.text)
}
__usrtext_start = ALIGN(4K);
.usrtext BLOCK(4K) : AT ( ADDR(.usrtext) - 0xC0000000 ) {
- build/obj/kernel/*.o (.usrtext)
+ * (.usrtext)
}
__usrtext_end = ALIGN(4K);
- .data BLOCK(4k) : AT ( ADDR(.data) - 0xC0000000 ) {
- build/obj/kernel/*.o (.data)
- build/obj/hal/*.o (.data)
+ .data BLOCK(4K) : AT ( ADDR(.data) - 0xC0000000 ) {
+ kernel/*.o (.data)
+ hal/*.o (.data)
+ debug/*.o (.data)
+ libs/*.o (.data)
}
.rodata BLOCK(4K) : AT ( ADDR(.rodata) - 0xC0000000 ) {
- build/obj/kernel/*.o (.rodata)
- build/obj/hal/*.o (.rodata)
+ kernel/*.o (.rodata)
+ hal/*.o (.rodata)
+ debug/*.o (.rodata)
+ libs/*.o (.rodata)
}
.kpg BLOCK(4K) : AT ( ADDR(.kpg) - 0xC0000000 ) {
- build/obj/arch/x86/*.o (.kpg)
+ arch/*.o (.kpg)
}
.bss BLOCK(4K) : AT ( ADDR(.bss) - 0xC0000000 ) {
- build/obj/kernel/*.o (.bss)
- build/obj/hal/*.o (.bss)
+ kernel/*.o (.bss)
+ hal/*.o (.bss)
+ debug/*.o (.bss)
+ libs/*.o (.bss)
}
__kernel_end = ALIGN(4K);
-include config/make-locations
-include config/make-os
-include config/make-cc
-include config/make-debug-tool
+mkinc_dir := $(CURDIR)/makeinc
+
+include $(mkinc_dir)/os.mkinc
+include $(mkinc_dir)/toolchain.mkinc
+include $(mkinc_dir)/qemu.mkinc
+include $(mkinc_dir)/utils.mkinc
+
+
+ARCH ?= i386
+export ARCH
DEPS := $(CC) $(LD) $(AR) xorriso grub-mkrescue
+kbuild_dir := build
+kbin_dir := $(kbuild_dir)/bin
+os_img_dir := $(kbuild_dir)/img
+
+os_build_tag := $(OS_NAME)_$(ARCH)_$(OS_VER)
+kbin := $(kbin_dir)/kernel.bin
+kimg := $(kbuild_dir)/$(os_build_tag).iso
+
$(DEPS):
@echo -n "checking $@ .... "
@if which $@ > /dev/null; then \
@echo -n "checking target i686-elf.... "
@test "`i686-elf-gcc -dumpmachine`" = "i686-elf" && echo ok || (echo "failed" && exit 1)
-$(OBJECT_DIR):
- @mkdir -p $(OBJECT_DIR)
+$(kbuild_dir):
+ @mkdir -p $(kbin_dir)
+ @mkdir -p $(os_img_dir)
+ @mkdir -p $(os_img_dir)/boot
+ @mkdir -p $(os_img_dir)/boot/grub
+ @mkdir -p $(os_img_dir)/usr
-$(BIN_DIR):
- @mkdir -p $(BIN_DIR)
+export BUILD_DIR=$(kbuild_dir)
+export BUILD_NAME=$(kbin)
+$(kbin):
+ $(call status,TASK,$(notdir $@))
+ @$(MAKE) $(MKFLAGS) -I $(mkinc_dir) -f kernel.mk all
-$(USR_DIR):
- @mkdir -p $(USR_DIR)
+$(kimg): usr/build $(kbin)
+ $(call status,TASK,$(notdir $@))
+ @./config-grub.sh ${OS_NAME} $(os_img_dir)/boot/grub/grub.cfg
+ @cp -r usr/build/* $(os_img_dir)/usr
+ @cp $(kbin) $(os_img_dir)/boot
+ @grub-mkrescue -o $(kimg) $(os_img_dir) -- -volid "$(OS_ID) $(OS_VER)" -system_id "$(OS_NAME)"
-$(ISO_DIR):
- @mkdir -p $(ISO_DIR)
- @mkdir -p $(ISO_BOOT_DIR)
- @mkdir -p $(ISO_GRUB_DIR)
+usr/build: user
check: $(DEPS) check-cc GRUB_TEMPLATE
-prepare: check $(OBJECT_DIR) $(BIN_DIR) $(ISO_DIR) $(USR_DIR)
-
-usrlib: prepare makefile.usr
- @make -f makefile.usr usr-runtime
+prepare: check $(os_img_dir)
-usrlib-debug: prepare makefile.usr
- @make -f makefile.usr usr-runtime-debug
+export BUILD_MODE=release
+bootable: $(kbuild_dir) $(kimg)
-usr-prog: prepare usrlib makefile.prog
- @make -f makefile.prog all
+export BUILD_MODE=debug
+bootable-debug: $(kbuild_dir) $(kimg)
-bootable: usr-prog usrlib makefile.ker
- @make -f makefile.ker all
-
-bootable-debug: usr-prog usrlib-debug makefile.ker
- @make -f makefile.ker all-debug
+user:
+ $(call status,$@)
+ @$(MAKE) $(MKFLAGS) -C usr all -I $(mkinc_dir)
all: bootable
instable: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) -D__LUNAIXOS_DEBUG__
instable: all
-all-debug: clean bootable-debug
- @echo "Dumping the disassembled kernel code to $(BUILD_DIR)/kdump.txt"
- @i686-elf-objdump -S $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/kdump.txt
+all-debug: bootable-debug
+ @echo "Dumping the disassembled kernel code to $(kbuild_dir)/kdump.txt"
+ @i686-elf-objdump -S $(kbin) > $(kbuild_dir)/kdump.txt
clean:
- @rm -rf $(BUILD_DIR) || exit 1
+ @rm -rf $(kbuild_dir) || exit 1
+ @$(MAKE) -C usr clean -I $(mkinc_dir)
+ @$(MAKE) -f kernel.mk clean -I $(mkinc_dir)
run: $(BUILD_DIR)/$(OS_ISO)
@qemu-system-i386 $(QEMU_OPTIONS)
@telnet 127.0.0.1 $(QEMU_MON_PORT)
debug-qemu: all-debug
- @i686-elf-objcopy --only-keep-debug $(BIN_DIR)/$(OS_BIN) $(BUILD_DIR)/kernel.dbg
- @qemu-system-i386 $(QEMU_OPTIONS)
+ @i686-elf-objcopy --only-keep-debug $(kbin) $(kbuild_dir)/kernel.dbg
+ @qemu-system-i386 $(call get_qemu_options,$(kimg))
@sleep 1
@$(QEMU_MON_TERM) -- telnet 127.0.0.1 $(QEMU_MON_PORT)
@gdb -s $(BUILD_DIR)/kernel.dbg -ex "target remote localhost:1234"
debug-qemu-vscode: all-debug
- @i686-elf-objcopy --only-keep-debug $(BIN_DIR)/$(OS_BIN) $(BUILD_DIR)/kernel.dbg
+ @i686-elf-objcopy --only-keep-debug $(kbin) $(kbuild_dir)/kernel.dbg
@qemu-system-i386 $(QEMU_OPTIONS)
@sleep 0.5
@telnet 127.0.0.1 $(QEMU_MON_PORT)
debug-metal:
@printf "@cmc" > $(PORT)
- @gdb -s $(BUILD_DIR)/kernel.dbg -ex "target remote $(PORT)"
\ No newline at end of file
+ @gdb -s $(kbuild_dir)/kernel.dbg -ex "target remote $(PORT)"
\ No newline at end of file
+++ /dev/null
-include config/make-os
-include config/make-cc
-include config/make-debug-tool
-include config/make-locations
-
-SRC_DIRS := kernel \
- hal \
- debug \
- libs \
- arch \
-
-SRC_FILES := $(foreach f, $(SRC_DIRS), $(shell find $(f) -name "*.[cS]"))
-
-OBJS := $(foreach f, $(SRC_FILES), $(OBJECT_DIR)/$(f).o)
-
-$(OBJECT_DIR)/%.S.o: %.S
- @mkdir -p $(@D)
- @echo " CC $<"
- @$(CC) $(INCLUDES) -c $< -o $@
-
-$(OBJECT_DIR)/%.c.o: %.c
- @mkdir -p $(@D)
- @echo " CC $<"
- @$(CC) $(INCLUDES) -c $< -o $@ $(CFLAGS)
-
-$(BIN_DIR)/$(OS_BIN): $(OBJECT_DIR) $(BIN_DIR) $(OBJS)
- @echo " LD $(BIN_DIR)/$(OS_BIN)"
- @$(CC) -T link/linker.ld -o $(BIN_DIR)/$(OS_BIN) $(OBJS) $(BIN_DIR)/$(USR_LIB) $(LDFLAGS)
-
-$(BUILD_DIR)/$(OS_ISO): $(BIN_DIR)/$(OS_BIN)
- @./config-grub.sh ${OS_NAME} $(ISO_GRUB_DIR)/grub.cfg
- @cp $(BIN_DIR)/$(OS_BIN) $(ISO_BOOT_DIR)
- @cp -r $(USR_DIR) $(ISO_DIR)
- @grub-mkrescue -o $(BUILD_DIR)/$(OS_ISO) $(ISO_DIR) -- -volid "$(OS_ID) $(OS_VER)" -system_id "$(OS_NAME)"
-
-all: $(BUILD_DIR)/$(OS_ISO)
-
-all-debug: O := -Og
-all-debug: CFLAGS := -g -std=gnu99 -ffreestanding $(O) $(W) $(ARCH_OPT) -D__LUNAIXOS_DEBUG__
-all-debug: LDFLAGS := -g -ffreestanding $(O) -nostdlib -lgcc
-all-debug: all
\ No newline at end of file
-OS_ARCH := x86
OS_NAME := lunaix
OS_ID := LunaixOS
OS_VER := dev$(shell date +%Y%m%d)
-OS_BIN := $(OS_NAME).bin
-OS_ISO := $(OS_NAME).iso
-
-USR_LIB := liblxusrt.a
-
-BUILD_DIR := build
-KERNEL_DIR := kernel
-OBJECT_DIR := $(BUILD_DIR)/obj
-BIN_DIR := $(BUILD_DIR)/bin
-ISO_DIR := $(BUILD_DIR)/iso
-ISO_BOOT_DIR := $(ISO_DIR)/boot
-ISO_GRUB_DIR := $(ISO_BOOT_DIR)/grub
INCLUDES := -Iincludes -Iincludes/usr
\ No newline at end of file
QEMU_MON_TERM := gnome-terminal
QEMU_MON_PORT := 45454
-QEMU_OPTIONS := -s -S -m 1G \
+get_qemu_options = -s -S -m 1G \
-rtc base=utc \
-no-reboot \
-machine q35 \
-d trace:ide_dma_cb \
-serial tcp::12345,server,nowait\
-drive id=disk,file="machine/disk0.vdi",if=none \
- -drive id=cdrom,file="$(BUILD_DIR)/$(OS_ISO)",readonly=on,if=none,format=raw \
+ -drive id=cdrom,file="$(1)",readonly=on,if=none,format=raw \
-device ahci,id=ahci \
-device ide-hd,drive=disk,bus=ahci.0 \
-device ide-cd,drive=cdrom,bus=ahci.1 \
-fno-inline-small-functions \
-fno-indirect-inlining
-CFLAGS := -std=gnu99 -ffreestanding $(O) $(OFLAGS) $(W) $(ARCH_OPT)
+CFLAGS := -std=gnu99 -ffreestanding $(OFLAGS) $(W) $(ARCH_OPT)
+
+ifeq ($(BUILD_MODE),debug)
+ O = -Og
+ CFLAGS += -g
+endif
+
+CFLAGS += $(O)
+
LDFLAGS := -ffreestanding $(O) -nostdlib -lgcc
MKFLAGS := --no-print-directory
\ No newline at end of file
+++ /dev/null
-#ifndef __LUNAIX_LD_ELF_H
-#define __LUNAIX_LD_ELF_H
-
-typedef unsigned int elf32_ptr_t;
-typedef unsigned short elf32_hlf_t;
-typedef unsigned int elf32_off_t;
-typedef unsigned int elf32_swd_t;
-typedef unsigned int elf32_wrd_t;
-
-#define ET_NONE 0
-#define ET_EXEC 2
-#define ET_DYN 3
-
-#define PT_LOAD 1
-#define PT_DYNAMIC 2
-#define PT_INTERP 3
-
-#define PF_X 0x1
-#define PF_W 0x2
-#define PF_R 0x4
-
-#define EM_NONE 0
-#define EM_386 3
-
-#define EV_CURRENT 1
-
-// [0x7f, 'E', 'L', 'F']
-#define ELFMAGIC 0x464c457fU
-#define ELFCLASS32 1
-#define ELFCLASS64 2
-#define ELFDATA2LSB 1
-#define ELFDATA2MSB 2
-
-#define EI_CLASS 4
-#define EI_DATA 5
-
-struct elf32_ehdr
-{
- unsigned char e_ident[16];
- elf32_hlf_t e_type;
- elf32_hlf_t e_machine;
- elf32_wrd_t e_version;
- elf32_ptr_t e_entry;
- elf32_off_t e_phoff;
- elf32_off_t e_shoff;
- elf32_wrd_t e_flags;
- elf32_hlf_t e_ehsize;
- elf32_hlf_t e_phentsize;
- elf32_hlf_t e_phnum;
- elf32_hlf_t e_shentsize;
- elf32_hlf_t e_shnum;
- elf32_hlf_t e_shstrndx;
-};
-
-struct elf32_phdr
-{
- elf32_wrd_t p_type;
- elf32_off_t p_offset;
- elf32_ptr_t p_va;
- elf32_ptr_t p_pa;
- elf32_wrd_t p_filesz;
- elf32_wrd_t p_memsz;
- elf32_wrd_t p_flags;
- elf32_wrd_t p_align;
-};
-
-#endif /* __LUNAIX_ELF_H */
pid_t pid;
if (!(pid = fork())) {
- err = execve("/usr/sh", NULL, NULL);
+ err = execve("/usr/bin/signal_demo", NULL, NULL);
printf("fail to execute (%d)\n", errno);
_exit(err);
}
- waitpid(pid, NULL, 0);
+ waitpid(pid, &err, 0);
+
+ if (err) {
+ printf("shell exit abnormally (%d)", err);
+ }
return 0;
}
\ No newline at end of file
@$(CC) $(CFLAGS) $(libc_include_opt) $(global_include_opt) -c $< -o $@
%.S.o: %.S
- @$(call status_,CC,$@)
+ @$(call status_,AS,$@)
@$(CC) $(libc_include_opt) $(global_include_opt) -c $< -o $@
$(build_lib)/$(BUILD_NAME): $(obj_files)